1、前言
前段时间在微信的一个公众号看到了一篇文章
阿里震撼业界—推出首个非侵入式热修复方案Sophix,颠覆移动端传统发版更新流程!
对此非常感兴趣,因为一直以来自己也想要在项目中加入热更新的功能,曾经试过了微信的Tinker,Gradle配置起来也有点点麻烦,构建的过程时间也比较长,当时项目比较赶,也就没有继续往下实践了。
看到了阿里的Sophix方案引入确实比较方便,简单到只需要两句代码,当然,实践起来还是有很多需要注意的地方,如有不慎,恐怕会引起崩溃。
阿里云移动热修复Sophix官网:https://www.aliyun.com/product/hotfix
2、非侵入性(原话)
我们的打包过程不会侵入到apk的build流程中。我们所需要的,只有已经生成完毕的新旧apk,而至于apk是如何生成的——是Android Studio打包出来的、还是Eclipse打包出来的、或者是自定义的打包流程,我们一律不关心。在生成补丁的过程中间既不会改变任何打包组件,也不插入任何AOP代码,我们极力做到了——不添加任何超出开发者预期的代码,以避免多余的热修复代码给开发者带来困扰。
3、实践中的一些问题
接入步骤可查看官方文档,比较简单,下面是写入Application的两句代码
// initialize最好放在attachBaseContext最前面
SophixManager.getInstance().setContext(this)
.setAppVersion(appVersion)
.setAesKey(null)
.setEnableDebug(true)
.setPatchLoadStatusStub(new PatchLoadStatusListener() {
@Override
public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
// 补丁加载回调通知
if (code == PatchStatus.CODE_LOAD_SUCCESS) {
// 表明补丁加载成功
} else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
// 表明新补丁生效需要重启. 开发者可提示用户或者强制重启;
// 建议: 用户可以监听进入后台事件, 然后应用自杀
} else if (code == PatchStatus.CODE_LOAD_FAIL) {
// 内部引擎异常, 推荐此时清空本地补丁, 防止失败补丁重复加载
// SophixManager.getInstance().cleanPatches();
} else {
// 其它错误信息, 查看PatchStatus类说明
}
}
}).initialize();
// queryAndLoadNewPatch不可放在attachBaseContext 中,否则无网络权限,建议放在后面任意时刻,如onCreate中
SophixManager.getInstance().queryAndLoadNewPatch();
3.1、多次补丁的情况,基线包需要多次修复补丁
已经修复了V.1版本,当需要更新V.2版本的补丁,应该是以哪个为基线包?应该是使用哪个补丁?这里V版本是基线包,patch3是补丁。
3.2、项目在Android4.4版本会遇到崩溃现象,应该如何避免?
Sophix的初始化代码要在Application的最前面,而且尽量使用系统的类,不要使用log等,最好就是什么代码都不写,回调方法也不写代码,确保不会发生崩溃现象。Sophix在修复的时候回整包dex修复,如果有其他代码可能会影响到修复过程。
3.3、Android5.0多dex分包的处理
实践的过程中遇到,项目方法数大于64k,已经采用dex分包技术,最小支持的API版本如果大于21,即Android5.0的时候,编译出来的apk包解压后可能会有好几十个dex分包(如下图所示,正常来说应该是1、2个),该问题会导致在差分包打补丁的时候会出错,因此只需要修改最小支持的API版本在5.0以下即可。
3.4、项目使用360加固,能否支持?
测试过了,是支持的。但我个人的测试范围比较小,在阿里钉钉群里面有人反映,360加固后会出现崩溃现象,且再也无法启动,只能卸载重装。这里我没遇到过,但官方客服并没有说支持,也就是说,出现问题并不会快速响应帮忙解决。
3.5、采用代码混淆 + 不加固的方式来发布应用,对于混淆文件mapping.txt的处理
应用在上线打包APK时,往往会进行混淆操作,但是由于修复前后两个APK混淆结果不同会导致patch无效,无法修复bug。所以,需要注意的是:应用打包APK的时候修复前后两个APK必须使用同一份mapping.txt,以保证两个APK混淆结果一致。
如果app应用了混淆配置,那么需要做如下处理。打包之前,将mapping.txt文件移动到了当前模块的目录下,再将混淆文件proguard-rules.pro进行如下操作。
#基线包使用,生成mapping.txt
-printmapping mapping.txt
#生成的mapping.txt在app/buidl/outputs/mapping/release路径下,移动到/app路径下
#修复后的项目使用,保证混淆结果一致
#-applymapping mapping.txt
#hotfix
-keep class com.taobao.sophix.**{*;}
-keep class com.ta.utdid2.device.**{*;}
#防止inline
-dontoptimize
3.6、项目中多版本、Debug、Release版本的热修复控制
建议不需要热更新的版本在
initialize()
queryAndLoadNewPatch()
方法之前加入判断,不然会报错。
3.7、对比腾讯微信Tinker热修复方案
腾讯微信Tinker方案也非常强大,也有一个完善的补丁后台管理,不需要我们的后台接入就能够轻松实现热修复的功能。
但有个问题,Tinker需要在Gradle配置里面做比较多的配置脚本,导致编译的时候也会非常占用时间,接入成本相对Sophix来说更大一些。
3.8、更多问题
官方FQ Android接入问题