您的位置:首页 > 移动开发 > Android开发

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息