最近新开了一个项目需要使用到热更新,最近也看了相关的文章,了解到阿里的Sophix使用简单且功能强大
来张表格对比:
方案对比 | Andfix开源版本 | 阿里Hotfix 1.X | 阿里Hotfix最新版 (Sophix) |
---|---|---|---|
方法替换 | 支持,除部分情况[0] | 支持,除部分情况 | 全部支持 |
方法增加减少 | 不支持 | 不支持 | 以冷启动方式支持[1] |
方法反射调用 | 只支持静态方法 | 只支持静态方法 | 以冷启动方式支持 |
即时生效 | 支持 | 支持 | 视情况支持[2] |
多DEX | 不支持 | 支持 | 支持 |
资源更新 | 不支持 | 不支持 | 支持 |
so库更新 | 不支持 | 不支持 | 支持 |
Android版本 | 支持2.3~7.0 | 支持2.3~6.0 | 全部支持包含7.0以上 |
已有机型 | 大部分支持[3] | 大部分支持 | 全部支持 |
安全机制 | 无 | 加密传输及签名校验 | 加密传输及签名校验 |
性能损耗 | 低,几乎无损耗 | 低,几乎无损耗 | 低,仅冷启动情况下有些损耗 |
生成补丁 | 繁琐,命令行操作 | 繁琐,命令行操作 | 便捷,图形化界面 |
补丁大小 | 不大,仅变动的类 | 小,仅变动的方法 | 不大,仅变动的资源和代码[4] |
服务端支持 | 无 | 支持服务端控制[5] | 支持服务端控制 |
说明:
- [0] 部分情况指的是构造方法、参数数目大于8或者参数包括long,double,float基本类型的方法。
- [1] 冷启动方式,指的是需要重启app在下次启动时才能生效。
- [2] 对于Andfix及Hotfix 1.X能够支持的代码变动情况,都能做到即时生效。而对于其他代码变动较大的情况,会走冷启动方式,此时就无法做到即时生效。
- [3] Hotfix 1.X已经支持绝大部分主流手机,只是在X86设备以及修改了虚拟机底层结构的ROM上不支持。
- [4] 由于支持了资源和库,如果有这些方面的更新,就会导致的补丁变大一些,这个是很正常的。并且由于只包含差异的部分,所以补丁已经是最大程度的小了。
- [5] 提供服务端的补丁发布和停发、版本控制和灰度功能,存储开发者上传的补丁包。
1、gradle远程仓库依赖, 打开项目找到app的build.gradle文件,添加如下配置:
添加maven仓库地址:
repositories {
maven {
url "http://maven.aliyun.com/nexus/content/repositories/releases"
}
}
添加gradle坐标版本依赖:
compile 'com.aliyun.ams:alicloud-android-hotfix:3.1.9'
2、Sophix SDK使用到以下权限
<! -- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<! -- 外部存储读权限,调试工具加载本地补丁需要 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
3、混淆配置
-
#基线包使用,生成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
4、初始化
initialize的调用应该尽可能的早,必须在Application.attachBaseContext()
或者Application.onCreate()
的最开始进行SDK初始化操作,初始化之前不能用到其他自定义类,否则极有可能导致崩溃。而查询服务器是否有可用补丁的操作可以在后面的任意地方。
public class MyApplication extends Application { public static StringBuilder cacheMsg = new StringBuilder(); @Override public void onCreate() { super.onCreate(); initHotfix(); } private void initHotfix() { String appVersion; try { appVersion = this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName; } catch (Exception e) { appVersion = "1.0"; } SophixManager.getInstance().setContext(this) .setAppVersion(appVersion) .setEnableDebug(true) .setPatchLoadStatusStub(new PatchLoadStatusListener() { @Override public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) { Log.e("code", "mode = " + mode + "info = " + info); // 补丁加载回调通知 if (code == PatchStatus.CODE_LOAD_SUCCESS) { // 表明补丁加载成功 Log.e("code", "表明补丁加载成功"); } else if (code == PatchStatus.CODE_LOAD_RELAUNCH) { // 表明新补丁生效需要重启. 开发者可提示用户或者强制重启; // 建议: 用户可以监听进入后台事件, 然后应用自杀 Log.e("code", "用户可以监听进入后台事件, 然后应用自杀"); } else if (code == PatchStatus.CODE_LOAD_FAIL) { // 内部引擎异常, 推荐此时清空本地补丁, 防止失败补丁重复加载 // SophixManager.getInstance().cleanPatches(); Log.e("code", "内部引擎异常, 推荐此时清空本地补丁, 防止失败补丁重复加载"); } else { // 其它错误信息, 查看PatchStatus类说明 Log.e("code", " 其它错误信息, 查看PatchStatus类说明"); } } }).initialize(); SophixManager.getInstance().queryAndLoadNewPatch(); } }
这几个步骤完成以后算是引入完成。然后就是测试补丁。生成补丁及测试方法查看官网:https://help.aliyun.com/document_detail/53247.html?spm=5176.doc53248.6.549.ZpQoMk