And Fix
关于Android的热补丁修复技术,之前有研究过。搜索发现有这3种方式可以实现
- 1.dexposed github https://github.com/alibaba/dexposed
- 2.andfix github https://github.com/alibaba/AndFix
- 3.bsdiff http://blog.csdn.net/lazyer_dog/article/details/47173013
dexposed和andfix是alibaba的开源项目,都是apk增量更新的实现框架。之前研究过 dexposed,由于dexposed的兼容性较差,只有2.3,4.0~4.4兼容,其他Android版本不兼容或未测试。至于bsdiff需要每次重启应用,重新加载才能生效,而且不是开源项目,所以缺少更新和维护。
而andfix则兼容2.3~6.0,又有alibaba在维护,所以就选择了andfix来进行增量更新(在线热补丁修复bug)。
Andfix的实现原理
AndFix的原理就是方法的替换,把有bug的方法替换成补丁文件中的方法。
注:在Native层使用指针替换的方式替换bug方法,已达到修复bug的目的。 使用AndFix修复热修复的整体流程:
方法替换过程:
Andfix的安全性 AndFix是通过匹配签名来进行校验的,我们的线上包是old.apk,修改之后的APK是new.apk,通过old.apk和new.apk生成一个patch文件,在运行热补丁patch的时候,会进行校验apk和patch的签名是否一致,如果一致才会执行热补丁。
生成path文件的方式如下所示: 需要一个alibaba提供的一个叫apkpatch-1.0.3的文件(该文件已经包含在开源项目的目录下,下载之后直接解压就行)。然后把APK A和B都放在该目录下,再把我们应用的签名文件xxxx.keystore放在该目录下,最后用cmd命令行进入该文件目录下,执行命令
apkpatch.bat -f new.apk -t old.apk -o output1 -k xxx.keystore -p 123456 -a suning -e 123456【完整命令】 xxx.keystore 是我们的签名文化 123456是签名文件的密码 suning是签名文件的alias 只有当签名文件和密码一致才会生成一个patch文件,在apk上还会对patch文件进行多一次校验,判断patch是否跟apk的签名一致。
下面是apk和patch文件进行匹配的源码:
//签名机制的初始化过程 public SecurityChecker(Context context) { mContext = context; init(mContext); } //主要是获取当前应用的签名及其他信息,为了判断与patch文件的签名是否一致 private void init(Context context) { try { PackageManager pm = context.getPackageManager(); String packageName = context.getPackageName();
PackageInfo packageInfo = pm.getPackageInfo(packageName,
PackageManager.GET_SIGNATURES);
CertificateFactory certFactory = CertificateFactory
.getInstance("X.509");
ByteArrayInputStream stream = new ByteArrayInputStream(
packageInfo.signatures[0].toByteArray());
X509Certificate cert = (X509Certificate) certFactory
.generateCertificate(stream);
mDebuggable = cert.getSubjectX500Principal().equals(DEBUG_DN);
mPublicKey = cert.getPublicKey();
} catch (NameNotFoundException e) {
Log.e(TAG, "init", e);
} catch (CertificateException e) {
Log.e(TAG, "init", e);
} }
AndFix的客户端使用流程 1.客户端在每次启动的时候,可以请求接口,判断是否需要去获取patch文件,如果需要获取,则直接下载patch文件到sd卡,下载好之后将文件名改为我们自己定义的文件名。(防止文件没有下载成功就进行patch加载会导致客户端崩溃)当patch加载成功后,程序会删除掉已经加载成功的patch文件。在sd卡上不会留下patch文件。
2.通过启动apk的时候,对是否下载哪些patch文件进行校验,然后再下载patch。
问题:(1)这里需要验证是否已经下载过改版本的patch,如果下载过,就不进行下载 (2)还需要考虑1、2同时下载时的线程安全。(如果不通过push进行更新,则可以不需要考虑,这里考虑到后续还有很多问题,所以暂时不建议做push更新)
patch的使用方式,经过测试,得出patch文件是增量更新的,更新的方式如下: 如果有3个补丁分别为ABC,那么APK如果想进行补丁升级,要先打补丁A,再打补丁B,最后打补丁C,以此类推。所以这里不能进行跨版本升级,因为在更新补丁的时候,没办法删除之前的补丁,删除补丁需要更随APK的升级而升级补丁的版本号,比如:APK 从1.0升级到1.1,那么在1.1这个版本会删除掉之前1.0所有的补丁。
考虑到服务器拿patch的流程,这里提出2个方案去实施:
方案1、每次启动都去依次获取该版本的补丁,直至最新的补丁。比如1.0的版本,发了3个补丁包,那么用户有可能会在出现4种情况,没有补丁,已有补丁A,已有补丁AB,和已有补丁ABC。 (1)如果是没有补丁,就依次去获取补丁ABC。 (2)如果已有补丁A,就需要依次去下载补丁BC。 (3)如果已有补丁AB,就需要去下载补丁C。 (4)如果已经有补丁ABC,就不需要去下载。 在每个补丁内,都需要带版本号,每次去请求网络的时候,都带上版本号,让服务器去返回下载地址。(如果是1.0发了3个补丁,1.1发了2个补丁,那么服务器只能返回1.0的3个补丁,1.1的补丁不应该返回)
方案2、规定每个小版本都只发一个补丁,这样就不需要考虑判断版本号的问题。
AndFix使用注意事项 (1)不支持YunOS (2)无法添加新类和新的字段 (3)使用加固平台可能会使热补丁功能失效 (4)由于这里涉及到Android底层系统的替换,所以需要更多的机型进行测试,以防出现像YunOS(阿里云)这样的系统。 AndFix的Android客户端部署 Android客户端的部署可以参考,下面两个链接: (1)http://www.jianshu.com/p/479b8c7ec3e3 (2)http://blog.csdn.net/yaya_soft/article/details/50460102
测试的注意事项 (1)如果是选择方案1,那么需要关注多个patch包是否依次加载成功,是否会出现漏包的情况。 (2)需要考虑分版本加载的情况 (3)兼容性测试,看看在不同机型上,是否会出现问题(这里建议使用更多的机型进行测试) (4)需要考虑在多个patch包的情形下,已下载了前面几个,然后下载失败,当再次启动时,会不会继续下载新的patch包。