今天集成测试了阿里最新的热更新技术sophix,单单就项目集成来说,阿里这次是真的下了一番苦功,相信集成过微信Tinker热更新的同学一定知道Tinker的集成是有多么的费劲!!!而且sophix采用非侵入打包,图形化的生成补丁,用阿里的原话说就是“傻瓜式接入”,点一点鼠标就能生成补丁文件,而且阿里提供了后台补丁管理系统,帮助开发者在生成补丁后直接上传至阿里的后台,无需开发者在自己的app和服务端做任何的操作。阿里的官网对于集成过程的每一个步骤已经非常详细了,只要你能“细心”的阅读应该都能成功。我只把集成时一些要注意的细节做一个总结。
1、创建应用
这里默认会创建android和ios两个版本的App,但是现在ios已经禁止了热更新技术,所以不用管他。这里有几个信息非常重要:RSA、AppId、AppSecret,在后边配置信息的时候会用到。
2、配置信息
2.1、配置app的gradle
2.2 在mainfest清单文件中添加权限
-
<! -- 网络权限 -->
-
<uses-permissionandroid:name="android.permission.INTERNET"/>
-
<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
-
<uses-permissionandroid:name="android.permission.ACCESS_WIFI_STATE"/>
-
<! -- 外部存储读权限,调试工具加载本地补丁需要 -->
-
<uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/>
2.3 在manifest清单文件的Application节点下添加信息,注意将“value”的字段替换成步骤一中系统生成的字段
-
<meta-data
-
android:name="com.taobao.android.hotfix.IDSECRET"
-
android:value="App ID"/>
-
<meta-data
-
android:name="com.taobao.android.hotfix.APPSECRET"
-
android:value="App Secret"/>
-
<meta-data
-
android:name="com.taobao.android.hotfix.RSASECRET"
-
android:value="RSA密钥"/>
2.4 添加混淆配置
-
#基线包使用,生成mapping.txt
-
-printmapping mapping.txt
-
#生成的mapping.txt在app/buidl/outputs/mapping/release路径下,移动到/app路径下
-
-
#修复后的项目使用,保证混淆结果一致
-
#-applymapping mapping.txt
-
-
#hotfix
-
-keepclass com.taobao.sophix.**{*;}
-
-keepclass com.ta.utdid2.device.**{*;}
-
#防止inline
-
-dontoptimize
3、初始化阿里热更新SDK代码
你只需要在你项目中的Application中的onCreat()方法中加入如下代码即可:
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 initialize()方法介绍
该方法主要做些必要的初始化工作以及如果本地有补丁的话会加载补丁, 但不会自动请求补丁。3.2 queryAndLoadNewPatch()方法介绍
该方法主要用于查询服务器是否有新的可用补丁. SDK内部限制连续两次queryAndLoadNewPatch()方法调用不能短于3s, 否则的话就会报code:19的错误码. 如果查询到可用的话, 首先下载补丁到本地, 然后
在SDK3.0.5版本中,新的补丁会在App重启三次后生效:
- 应用原本没有补丁, 那么如果当前应用的补丁是热补丁, 那么会立刻加载(不管是冷补丁还是热补丁). 如果当前应用的补丁是冷补丁, 那么需要重启生效.
- 应用已经存在一个补丁, 请求发现有新补丁后,本次不受影响。并且在下次启动时补丁文件删除, 下载并预加载新补丁。在下下次启动时应用新补丁。
补丁在后台发布之后, 并不会主动下行推送到客户端, 需要手动调用queryAndLoadNewPatch方法查询后台补丁是否可用.
- 只会下载补丁版本号比当前应用存在的补丁版本号高的补丁, 比如当前应用已经下载了补丁版本号为5的补丁, 那么只有后台发布的补丁版本号>5才会重新下载.
假设你现在发布了一个新补丁,此时app已经加载了一个老版本的补丁并在运行中。而其他地方没有再调用到queryAndLoadNewPatch。
第一次重启,会调用queryAndLoadNewPatch,会发现已经有新补丁,但本次要保证运行正常,所以还不能删除替换老补丁,而是会在下次重启后进行删除。
第二次重启,检测到之前请求到了新补丁,会在initialize时先删除老补丁,然后继续调用queryAndLoadNewPatch,会完成下载和补丁预加载。但由于已经initialize,不会马上加载新补丁。
第三次重启,initialize会发现刚才已经加载的新补丁,加载,新补丁生效。
因此通常就会重启三次。
所以可以在app运行过程中定期调用queryAndLoadNewPatch,以提早查询新补丁并进行预加载,这样只要重启两次就可以生效了。
所以加载新补丁的时机取决于queryAndLoadNewPatch。