在一篇文章中,我们讨论了   安卓类加载机制分析  的理论知识, 这篇文章用一篇具体的实例来演示 插件化功能的 雏形。

类加载机制  是 研究插件化 和 热修复 的基础。 加载外部 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 



 

更多相关文章

  1. Android(安卓)源码编译加速 使用ccache
  2. android解析xml文件的方式之DOM解析
  3. android app卸载以后弹出用户反馈界面
  4. android 常用命令集锦 新手必知必会哦----图文并茂 版
  5. Android存储路径详细说明
  6. Android实现自定义铃音
  7. Windows环境下Android(安卓)NDK的开发
  8. 通过 WIFI 用 adb 调试 Android(安卓)设备
  9. Android导出与使用带资源的lib包

随机推荐

  1. Android(安卓)P Launcher显示ALL APP ICO
  2. 解决:Failed to fetch URL https://dl-ssl
  3. Run native executable in Android(安卓)
  4. android listview onItemClick不执行
  5. Android定制出厂默认输入法(其他设置类似
  6. Android_嵌入chrome浏览器
  7. android 调用 react-native方法
  8. android中清空一个表。类似truncate tabl
  9. Android(安卓)MAT
  10. Android(安卓)知识图谱