前段时间公司准备在项目里面引入热修复技术,自己以前也看过关于热修复的文章,比如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
通过该命令:a apkpatch.bat -f new.apk -t old.apk -o dir -k testfixappkey.jks -p pas -a testfixappkey.jks -e password
- new.apk :是修改之后的新包
- old.apk :是我有bug的bug
- dir: 定义补丁输出的目录
- testfixappkey.jks: 是keystore
- pas 是keystore的密码
- testfixappkey.jks 是 alias keystore的用户别名
- password:是我的alias的密码。
我使用的是阿里的andfix框架,对于如何引入查看阿里团队的andfix的源码andfix源码 。
首先在我的application里面进行初始化。
然后会在检查我的/data/data/包名/files目录下检查这个补丁文件
我是把补丁直接放在了手机的data/data/..这个目录下的。在生产环境中肯定是要放在服务器上,传输到客户端的目录下的。
初始化之后,来实践一下:首先在mainActivity中写一段代码然后打出一个签名的包,然后将吐司的内容修改一下,再打出一个有签名的包。然后通过补丁工具生成一个补丁后缀为“.apkpatch”的文件
将生成的补丁放入data/data/..目录下,这样当我们再次启动应用的时候便会将之前吐司的内容修改掉:
下面是我两张修改前和修改后的两张GIF图:
补丁打入前:
补丁打入后: