AndFix是阿里开源的一个Android热补丁框架,允许APP在不重新发布版本的情况下修复线上的bug。支持Android 2.3 到 7.0。
github地址:https://github.com/alibaba/AndFix
详细使用方法,官方文档已给出。
AndFix大致原理是apkpatch将两个apk做一次对比,然后找出不同的部分。可以看到生成的apatch了文件,后缀改成zip再解压开,里面有一个dex文件。通过jadx查看一下源码,里面就是被修复的代码所在的类文件,这些更改过的类都加上了一个_CF的后缀,并且变动的方法都被加上了一个叫@MethodReplace的annotation,通过clazz和method指定了需要替换的方法。
然后客户端sdk得到补丁文件后就会根据annotation来寻找需要替换的方法。最后由JNI层完成方法的替换。
多次打补丁要注意
如果本地保存了多个补丁,那么AndFix会按照补丁生成的时间顺序加载补丁。具体是根据.apatch文件中的PATCH.MF的字段Created-Time。
一般自己打补丁生成的补丁名称都是一致的,所以这里要注意。
源码
File src = new File(path); File dest = new File(mPatchDir, src.getName());
if(!src.exists()){
throw new FileNotFoundException(path);
}
if (dest.exists()) {
Log.d(TAG, "patch [" + path + "] has be loaded.");
return;
}
AndFix存在局限性
1. 无法添加新类和新的字段
2. 不支持YunOS
3. 制作补丁使用加固前的apk包,补丁是可以被反编译
案例
// 在application中初始化就行
private void initPatch() {
try {
//获取当前版本号,只要版本升级AndFix会清除所有已加载补丁
String apkVersion = VersionUtils.getVersionName(getApplicationContext());
mPatchManager = new PatchManager(this);
//文件存放路径--下载补丁文件存放的路径
String patchFilePath = Config.BASE_PATH;
File patchFile = new File(patchFilePath);
//我这里是修改了顺序,先加载补丁,后初始化,应用补丁
if (patchFile.exists()) {
File patch=new File(patchFilePath+Config.PATCH_NAME);
if(patch.exists()){
mPatchManager.addPatch(patchFilePath+Config.PATCH_NAME);
//复制且加载补丁成功后,删除下载的补丁
if (!patch.delete()) {
Log.e(TAG, patchFilePath+Config.PATCH_NAME + "删除补丁失败");
}
}else{
Log.d(TAG, "补丁文件不存在");
}
} else {
patchFile.mkdirs();
Log.d(TAG, "补丁文件夹不存在");
}
mPatchManager.init(apkVersion);
mPatchManager.loadPatch();
} catch (IOException e) {
e.printStackTrace();
}
}