针对APP产品的在线修复实现,已经有N多的程序大牛论述了各种奇药异方。主要包括Dexposed、AndFix、ClassLoader(来源是原QZone,现淘宝的工程师陈钟,在15年年初就已经开始实现)三种。前两个都是阿里巴巴内部的不同团队做的(淘宝和支付宝),后者则来自腾讯的QQ空间团队。本次小编仅针对AndFix做下使用笔记,如果想对其实现原理或者其他实现方式有更深理解的,可转到文章底部参考相应的资料进行了解。
1.添加依赖
compile 'com.alipay.euler:andfix:0.3.1@aar'
2.设置权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.INTERNET" />
3.在Application.onCreate() 中添加以下代码
patchManager = new PatchManager(context);
//current version 可通过getPackageInfo(context).versionName;获取
patchManager.init(appversion);
patchManager.loadPatch();
4.在补丁加载完成后加载新补丁/.apatch
patchManager.addPatch(path);// path指补丁文件存储位置
5.通过官方提供的工具apkpatch打补丁
这里我们启动cmd命令可以启动该工具的使用,请注意每个子命令所的使用。
apkpatch.bat -f new.apk -t old.apk -o document -k app.keystore -p android -a androidApp -e android
子命令 | 全称 | 含义 |
---|---|---|
-f | new.apk | 新版本 |
-t | old.apk | 旧版本 |
-o | output | 输出目录 |
-k | keystore | 打包所用的keystore |
-p | password | keystore的密码 |
-a | alias | keystore 用户别名 |
-e | alias password | keystore 用户别名密码 |
6.源码混淆
-printmapping proguard.map
#首先需要生成mapping文件记录混淆规则,之后可以把printmapping 这句话注释掉,每次只使用applymapping。
-applymapping proguard.map
#然后在下面加上
-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
native <methods>;
}
-keep class com.alipay.euler.andfix.** { *; }
7.常见问题
(1) 补丁命名各补丁的命名不能一致,这样才能加载,否则仅有第一次的补丁才会生效;
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;
}
(2) 加载新补丁之后,无需重启APP既可激活clazz修复(如果是在需要被修复的clazz当中加载完补丁,则需要重新启动该clazz文件才能生效);
(3) 被成功加载的补丁可接受删除(由于是线上APK与最新一次修复BUG的APK打下的补丁,故过时的补丁所修复的内容将会被新的补丁覆盖);
(4) 开发过程中请勿启动PatchManager的addPath();方法。如果当下已经有.apatch文件在本地,那么很有可能因为逻辑判断不严谨而重复add。导致部分被修改的源码无法找到,而使应用程序在调试过程中报错(如下草图图解)。
8.本文参考
AndFix使用说明,感谢简书的作者讲解得很入味很好上手。小编也只是在此基础实现上提笔一点自己的经验。