android 加载外部 dex文件中的类 的源码实例
在一篇文章中,我们讨论了 安卓类加载机制分析 的理论知识, 这篇文章用一篇具体的实例来演示 插件化功能的 雏形。
类加载机制 是 研究插件化 和 热修复 的基础。 加载外部 dex文件中的类,我们在这部分主要做的流程有:
- 1.编写基本的Java文件并编译为.class文件。
- 2.将.class文件转为.dex文件。
- 3.将转好的dex文件放入创建好的Android工程内并在启动时将其写入本地。
- 4.加载解压后的.dex文件中的类,并调用其方法进行测试。
1、创建一个外部独立的java类文件
public class Test { public void print() { System.out.println("this is Test Class"); } public String accessDex() { return "这是一段存储在独立dex文件中的字符串"; }}
2、用 javac 命令 生成 class 文件
3、用 Android sdk/build-tools/ 中的 dx 工具 ,将 class 文件生成 dex 文件。 注意 build-tools 所有版本中都带有 dx工具,这里我用的是目前最新版本的 build-tools,即 27.0.3 版本.
dx 命令的基本用法
dx --dex [--output=] [.class | .{zip,jar,apk} | ]
我们使用的命令如下
dx --dex --output=1.dex Test.class
mac 系统需要注意的是 dx的命令的执行路径。 在 Test.class 文件夹中 打开 终端, 将 sdk/build-tools/27.0.3/dx 文件 拖动到 终端中,表示要执行这个 可执行文件, 它接收三个参数,
参数1:--dex 表示要执行打包 dex动作;
参数2: --output=1.dex 表示设置生成的文件的名称;
参数3:需要转换的class文件
同理,还可以使用此命令,将一个jar包转换成 dex文件,其中 origin.jar是已经存在的、需要被转换的jar文件, target.dex 是转换后生成的 dex 文件名称
dx --dex --output=target.dex origin.jar
4、在安卓工程中加载 外部独立的dex文件。
实现思路:把外部 独立的 dex文件 拷贝到 安卓项目的 assets 目录下, app运行时 将 asstes 目录下的文件 通过 流式读取 复制到 应用的私有目录下。
为什么要复制出来?因为assets目录下的文件并不能直接通过new File(xxx_path)的形式来访问, 它只能通过 Context.getAssets().open() 来获取一个访问流。
通过 DexClassLoader 读取 复制到app私有目录 下的 dex,调用 dexClassLoader.loadClass("Test") 获取 对应的 Class<?>, 并通过构造函数创建找对象,再通过反射访问其内部的方法。
具体源码见下图
题外话:如何将多个不同包路径 的class打包到同一个dex文件中
我们先创建上图中的三个java源文件, 其中 Test.java 就是我们上面已经创建过的.
创建第二个类文件,UserInfo.java
package cn;/** * Created by meikai on 2018/08/03. */public class UserInfo { public String userNmae; @Override public String toString() { return "用户姓名:" + userNmae; }}
创建第三个类文件,Category.Java
package com.mike;public class Category { public String channel; @Override public String toString() { return "频道:" + channel; } }
用javac 命令分别 生成对应的 class 文件, 如下图
这时如果直接像前面 打包 无包路径 的class那种试会失败, 报如下错误。 这个错误意思很好理解, 就是说 "类的名称" 和 "类的class文件的路径" 不匹配。
在java中 为方便源代码的管理,不是将所有的*.java源文件都放在一个文件夹下, 类的名称实际 由 类的包路径 和 类名称 综合决定, class文件存放的位置也必须按其 包名 相同的路径。 这个应该在java基础中就有讲解。
按上面的分析,我们分别建立对应其包路径的文件夹,将*.class文件分别放到对应的文件夹中, 再来执行 dx 命, 就能成功打包成一个 dex文件
最后,我们用 dex2jar 工具,看看 对不对。 发现 这个 dex2jar 转换后的 jar 包 就有 这三个类
彩蛋:补充介绍一下如果查看class文件对应的字节码
命令: javap -c *.class
更多相关文章
- Android(安卓)源码编译加速 使用ccache
- android解析xml文件的方式之DOM解析
- android app卸载以后弹出用户反馈界面
- android 常用命令集锦 新手必知必会哦----图文并茂 版
- Android存储路径详细说明
- Android实现自定义铃音
- Windows环境下Android(安卓)NDK的开发
- 通过 WIFI 用 adb 调试 Android(安卓)设备
- Android导出与使用带资源的lib包