先看一下比较热门的各大厂商热修复框架对比:
Hotfix最新版本spofix是首款非侵入式框架:下面是百度内容
假设大家都想要把用户代码塞到一个框架里。侵入式的做法就是要求用户代码“知道”框架的代码,表现为用户代码需要继承框 架提供的类。非侵入式则不需要用户代码引入框架代码的信息,从类的编写者角度来看,察觉不到框架的存在。
废话不多说直接看代码实现效果:
1.直接在项目跟modle添加远程库:
maven {
url "http://maven.aliyun.com/nexus/content/repositories/releases"
}
整个截图:
2.然后在app的build.gradle里面添加坐标版本依赖:
-
compile'com.aliyun.ams:alicloud-android-hotfix:3.1.3'
import android.app.Application; import com.taobao.sophix.PatchStatus; import com.taobao.sophix.SophixManager; import com.taobao.sophix.listener.PatchLoadStatusListener; /** * Created by Administrator on 2017/10/23. * code: 1 补丁加载成功 code: 6 服务端没有最新可用的补丁 code: 11 RSASECRET错误,官网中的密钥是否正确请检查 code: 12 当前应用已经存在一个旧补丁, 应用重启尝试加载新补丁 code: 13 补丁加载失败, 导致的原因很多种, 比如UnsatisfiedLinkError等异常, 此时应该严格检查logcat异常日志 code: 16 APPSECRET错误,官网中的密钥是否正确请检查 code: 18 一键清除补丁 code: 19 连续两次queryAndLoadNewPatch()方法调用不能短于3s */ public class A extends Application { @Override public void onCreate() { SophixManager.getInstance().setContext(this) .setAppVersion("1.0.0")//你的后台版本 .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) { // 表明新补丁生效需要重启. 开发者可提示用户或者强制重启; // 建议: 用户可以监听进入后台事件, 然后调用killProcessSafely自杀,以此加快应用补丁,详见1.3.2.3 } else { // 其它错误信息, 查看PatchStatus类说明 } } }).initialize(); // queryAndLoadNewPatch不可放在attachBaseContext 中,否则无网络权限,建议放在后面任意时刻,如onCreate中 super.onCreate(); SophixManager.getInstance().queryAndLoadNewPatch(); } }
<! -- 网络权限 -->
<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"/>
READ_EXTERNAL_STORAGE
权限属于Dangerous Permissions,仅调试工具获取外部补丁需要,不影响线上发布的补丁加载,调试时请自行做好 android6.0以上的运行时权限获取。
在AndroidManifest.xml
中间的application
节点下添加如下配置:
<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密钥" />
将上述value中的值分别改为通过平台HotFix服务申请得到的App Secret和RSA密钥
混淆配置
#基线包使用,生成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
以上便是spofix的集成步骤,是不是挺简单啊!!!!!!!
测试部分:
MianActivity中只写了一个战狼2的吐司
注意一定是正式的打包签名完成后生成的apk文件哦!
效果图:
现在将战狼2更改为杀破狼.贪狼并将Helloworld背景颜色更改
更改完毕后生成新的release apk文件
两个apk文件不要弄混了
然后下载补丁生成工具:https://help.aliyun.com/document_detail/53247.html?spm=5176.2020520107.0.0.e0fc1a1tRrvPT
解压后得到一个SophixPatchTool.exe文件 注意要JDK7以上版本支持
双击打开选择刚才生成的基准版本与更新版本apk,如下图:
注意设置按钮里面的设置:
完事后:
然后将生成的补丁文件上传到阿里的开发后台:
上传完毕后查看详情直接选择灰度下发:官方提示说要本地扫码验证后在灰度下发 我 试了几下没成功就直接跳过了
看运行效果:
调试:
在applation中打个Log看PatchStatus的状态码分析问题
这里列举几个常见的code码说明,
- code: 1 补丁加载成功
- code: 6 服务端没有最新可用的补丁
- code: 11 RSASECRET错误,官网中的密钥是否正确请检查
- code: 12 当前应用已经存在一个旧补丁, 应用重启尝试加载新补丁
- code: 13 补丁加载失败, 导致的原因很多种, 比如UnsatisfiedLinkError等异常, 此时应该严格检查logcat异常日志
- code: 16 APPSECRET错误,官网中的密钥是否正确请检查
- code: 18 一键清除补丁
- code: 19 连续两次queryAndLoadNewPatch()方法调用不能短于3s
详情查看SDK中PatchStatus类的代码,有具体说明:
package com.taobao.sophix;
public class PatchStatus {
public final static int CODE_REQ_START = 0;
public final static String INFO_REQ_START = "ready to start.";
public final static int CODE_LOAD_SUCCESS = 1;
public final static String INFO_LOAD_SUCCESS = "load new patch success.";
public final static int CODE_ERR_NOTINIT = 2;
public final static String INFO_ERR_NOTINIT = "didn't initialize hotfix sdk or initialize fail.";
public final static int CODE_ERR_NOTMAIN = 3;
public final static String INFO_ERR_NOTMAIN = "only allow query in main process.";
public final static int CODE_ERR_INBLACKLIST = 4;
public final static String INFO_ERR_INBLACKLIST = "current device does't support hotfix.";
public final static int CODE_REQ_ERR = 5;
public final static String INFO_REQ_ERR = "pull patch info detail fail, please check log.";
public final static int CODE_REQ_NOUPDATE = 6;
public final static String INFO_REQ_NOUPDATE = "there is not update.";
public final static int CODE_REQ_NOTNEWEST = 7;
public final static String INFO_REQ_NOTNEWEST = "the query patchversion equals or less than current patchversion, stop download.";
public final static int CODE_DOWNLOAD_FAIL = 8;
public final static int CODE_DOWNLOAD_SUCCESS = 9;
public final static String INFO_DOWNLOAD_SUCCESS = "patch download success.";
public final static int CODE_DOWNLOAD_BROKEN = 10;
public final static String INFO_DOWNLOAD_BROKEN = "patch file is broken.";
public final static int CODE_UNZIP_FAIL = 11;
public final static String INFO_UNZIP_FAIL = "unzip patch file error, please check value of AndroidMenifest.xml RSASECRET or initialize param aesKey.";
public final static int CODE_LOAD_RELAUNCH = 12;
public final static String INFO_LOAD_RELAUNCH = "please relaunch app to load new patch.";
public final static int CODE_LOAD_FAIL = 13;
public final static String INFO_LOAD_FAIL = "load patch fail, please check stack trace of an exception: ";
public final static int CODE_LOAD_NOPATCH = 14;
public final static String INFO_LOAD_NOPATCH = "do not found any patch file to load.";
public final static int CODE_REQ_APPIDERR = 15;
public final static String INFO_REQ_APPIDERR = "appid is not found.";
public final static int CODE_REQ_SIGNERR = 16;
public final static String INFO_REQ_SIGNERR = "token is invaild, please check APPSECRET.";
public final static int CODE_REQ_UNAVAIABLE = 17;
public final static String INFO_REQ_UNAVAIABLE = "req is unavailable as has already been in arrearage.";
public final static int CODE_REQ_CLEARPATCH = 18;
public final static String INFO_REQ_CLEARPATCH = "clean client patch as server publish clear cmd.";
public final static int CODE_REQ_TOOFAST = 19;
public final static String INFO_REQ_TOOFAST = "two consecutive request should not short then 3s.";
public final static int CODE_PATCH_INVAILD = 20;
public static final String INFO_PATCH_INVAILD = "patch invaild, as patch not exist or is dir or not a jar compress file.";
public final static int CODE_LOAD_FORBIDDEN = 21;
public static final String INFO_LOAD_FORBIDDEN = "debuggable is false! forbid loading local patch for secure reason!";
}