前段时间公司准备在项目里面引入热修复技术,自己以前也看过关于热修复的文章,比如qq空间团队关于热修复技术的,安卓App热补丁动态修复技术介绍 。在了解热修复之前,首先要明白安卓里面的ClassLoader这个类,这个类下面有两个子类:pathClassLoader和DexClassLoader;对于这两个同样是继承BaseClassLoader的这两个类有不同的用法。

pathClassLoader:只能加载已安装到系统中的apk文件。

DexClassLoader:可以加载apk文件和dex文件及jar。

关于classLoader就是通过遍历每一个dex文件的内部Element数组,加载需要的class类。这个就是热更新要解决的第一个问题,如何把我们打成的补丁插入到这个Element数组的内部的class前面。替换成我们需要使用的修复补丁文件,通过看QQ空间团队对于热更新技术的事件,可以发现为了修复有bug的类需要防止引用的类被打上CLASS_ISPREVERIFIED标志。QQ空间实现的方案是将被引用的类单独作为一个dex文件,这样class.dex加载类的时候会应用一个不在同一个dex文件内的类,这样就防止了这样就防止了类被打上CLASS_ISPREVERIFIED的标志了。

如何去做呢?

1.如何生成一个补丁文件

2.如何防止类被打上CLASS_ISPREVERIFIED标志。

打补丁的工具:apkpatch

android 更新动态库 安卓动态系统更新_android 更新动态库


通过该命令:a apkpatch.bat -f new.apk -t old.apk -o dir -k testfixappkey.jks -p pas -a testfixappkey.jks -e password

  1. new.apk :是修改之后的新包
  2. old.apk :是我有bug的bug
  3. dir: 定义补丁输出的目录
  4. testfixappkey.jks: 是keystore
  5. pas 是keystore的密码
  6. testfixappkey.jks 是 alias keystore的用户别名
  7. password:是我的alias的密码。

我使用的是阿里的andfix框架,对于如何引入查看阿里团队的andfix的源码andfix源码

首先在我的application里面进行初始化。

android 更新动态库 安卓动态系统更新_classloader_02


然后会在检查我的/data/data/包名/files目录下检查这个补丁文件

android 更新动态库 安卓动态系统更新_qq空间_03


我是把补丁直接放在了手机的data/data/..这个目录下的。在生产环境中肯定是要放在服务器上,传输到客户端的目录下的。

初始化之后,来实践一下:首先在mainActivity中写一段代码

android 更新动态库 安卓动态系统更新_热修复-andfix_04

然后打出一个签名的包,然后将吐司的内容修改一下,再打出一个有签名的包。然后通过补丁工具生成一个补丁后缀为“.apkpatch”的文件

android 更新动态库 安卓动态系统更新_android 更新动态库_05

将生成的补丁放入data/data/..目录下,这样当我们再次启动应用的时候便会将之前吐司的内容修改掉:

下面是我两张修改前和修改后的两张GIF图:

补丁打入前:

android 更新动态库 安卓动态系统更新_classloader_06


补丁打入后:

android 更新动态库 安卓动态系统更新_android 更新动态库_07