本文地址:Android热修复AndFix混淆后热修复失败,无效
这几天一直在研究热修复,对比了多个框架,最终因为是Eclipse开发,所以把重心渐渐转移到AndFix上面。
AndFix地址:https://github.com/alibaba/AndFix
这里只以Eclipse为大环境。
Eclipse集成AndFix:http://blog.csdn.net/caihongdao123/article/details/52051799
按着步骤集成很简单,写个小Demo,运行修复,也成功了。
但是还没混淆,
这里说下混淆:
每次代码混淆时,都会生成一个mapping.txt文件,在发线上版本时,保存该mapping文件,然后再修复了bug的版本的混淆配置文件中,
多加一行-applymapping 来应用之前保存的mapping(之前的keepclass什么的配置也要一样),这样就能保证类名,方法名的映射与之前是一致的。
在混淆时,遇到了个坑,半天没解决。
后来通过看mapping和逆向,才发现问题所在。
---------------------------------------------------------------正确的分割线---------------------------------------------------------------------------------------------------
因为是小Demo,所以写的类和方法都少。
这是测试的输出方法:
public class BugClass {
public String message(){
return "出现BUG";
}
public String messageFixed(){
return "出现BUG,已经修复";
}
}
public void onClick(View v){
AndFixApplication ma = (AndFixApplication)getApplication();
ma.refreshPatch();
changeText();
}
private void changeText(){
//String message = new BugClass().messageFixed(); //bug修复后调用
String message = new BugClass().message(); //出现bug时调用
tvMsg.setText(message);
}
出现bug时在changeText()中调用message()方法,此时,混淆打包时,得到的mapping文件中记载:
com.example.multidexapplication.bug.BugClass -> com.example.multidexapplication.a.a:
java.lang.String message() -> a
而修复bug时,调用的是mesageFixed()方法,此时,混淆打包得到的mapping文件中记载:
com.example.multidexapplication.bug.BugClass -> com.example.multidexapplication.a.a:
java.lang.String messageFixed() -> a
注意,bug版本的mapping文件中,并没有混淆messageFixed()方法,而修复bug后的版本中,也没有混淆messge()方法,
这是为什么?
之前说了,这是个小demo,所以,只在changeText()方法中小小地调用了下message()(或messageFixed())方法,
而没有被调用的方法,是不会打包到dex中的,所以,在AndFix热修复打差分包.apatch的时候,
差分包中的方法并没有changeText()方法(因为bug版本与修复bug的版本中的changeText()调用的message()与messageFixed()方法都被混淆成了a方法,被当做了同一个方法),而只有messageFixed()方法(它被混淆成了a方法)。
之后就是从差分包中读取类中的方法的过程:
(个人猜测的过程)
从差分包中读取到要替换的是a()方法,根据mapping(注意:此为bug版本的mapping文件,想想就知道为什么是)反向映射,得到了message()方法。而实际上,a()方法
是messageFixed()方法,所以,替换不了。
(具体有待求证,希望有大神指点)
要解决这个问题,是不是只要让message()与messageFixed()方法不被混淆成同一个方法,就可以解决呢?
修改了代码,在MainActivity的onCreate()中直接分别调用一下这两个方法,
然后混淆打包,mapping文件:
com.example.multidexapplication.bug.BugClass -> com.example.multidexapplication.a.a:
java.lang.String message() -> a
java.lang.String messageFixed() -> b
这下,俩方法不会混淆成同一个字母了。
打差分包,重新跑,修复成功!
-----------------------------------------------------------------------------------------
后话,由于是小Demo,所以可能出现方法只调用了一次的情况,在实际开发中,这种情况应该比较少见,但是遇到类似修复不成功的时候,
不妨看看mapping文件,逆向一下看看,也许能发现点什么。