Android 热修复思路整理
2016-12-19 16:09
246 查看
Android 热修复思路整理
问题提出
什么是热修复热修复的优点
流行的热修复方式
本文采用的热修复
方式
相关知识点
思路
解决方案
热修复:Android端修复bug,通常方案是,修改bug所在的类->打包整个代码apk->重新上线->用户下载apk重新安装使用;
热修复的方式,修改bug所在的类->用户在已有app的情况下下载修复好的fixbug.class。
热修复的优点:很明显开发人员不需要重新打包整个apk重新上传apk,用户不需要重新下载整个apk,在用户使用已有app的时候,偷偷的将bug就修复了,用户甚至不知道发生过什么,提高用户体验。
流行的热修复方式(按技术特点划分)
通过底层二进制(C/C++)方式,阿里:DeXposed。andfix。
通过JAVA层加载机制, 腾讯:tinker
本文采用的热修复
比较容易理解的Java类加载机制实现的。
主要用到的技术:JAVA反射,热修复的热字就体现在这里,运行时fix bug...
思路
以前搞过反编译的小伙伴已经反编译过classes.dex文件,classes文件是如何生成的呢?这就好办了找到生成dex文件的地方就可以了。。。
其实JAVA类的加载机制是从:dalvik.system.BaseDexClassLoader开始的,查看源码我们发现里面使用了DexPathList这个类,这个类里面的是通过dexElements数组,来处理我们反编译出来的classes.dex, classes2.dex文件
如果在细看代码你会发现,已经加载过的.class文件就不会再被加载了,也就是说同一时刻ClassLoder只会加载一次同一个.class文件一次,那我们是不是可以在有问题的.class文件加在之前,先加载我们的修复好的.class文件是不是就可以了。
那剩下的问题就剩下如何获取到dexElements数组,将修复好的dex合并到dexElements数组里面,重新让系统使用即可。
那我们先来确认dex文件位于app那个位置呢,答案就是在当前app的getDir()目录下(data\data...),我们只要将修改好的java文件生成.class文件在编译成classes.dex文件再将该文件存入到该目录下,通过反射获取我们的classes.dex进行数组合并工作,就可以达到目的,下面着重说一下反射思路。(生成classes.dex文件可用:你的SDK目录\build-tools\24.0.3\dx.bat工具)
- 反射思路:
//加载应用程序的ClassLoder ClassLoader classLoader = context.getClassLoader(); for (File file : loadedDex) { //因为系统通过DexClassLoder来加载dex,所以需要将新加入的修复dex伪装成系统能够识别的ClassLoder DexClassLoader dexClassLoder = new DexClassLoader( file.getAbsolutePath(),// String dexPath, optFile.getAbsolutePath(),// String optimizedDirectory, null,//String libraryPath, classLoader// ClassLoader parent ); //分别通过系统和Fix Dex反射获取DexClassLoader对象的DexPathList对象 // 进一步获取DexPathList对象的dexElements数组对象 //将两个数组利用已经loaderd的类不会呗再次加载的特点,将fix数组放在dexElements数组下标0处,合并两个数组 //通过放射将修改后的dexElements数组重新写入到app加载类的目录下,达到修复的目的,此时错误的class文件还是存在与数组内部的,但是已经不会再被加载了
可能遇到的坑
需要将AS的Instant Run功能暂时关闭,不然修复的内容有可能无法写入到classes.dex看不到效果
需要配置APP的gradle里的mutidex
相关文章推荐