阿里Sophix热修复框架使用入门
目前的热修复框架,最强大的当属阿里的Sophix了,虽然是收费,但对于小众的APP来说,很可能不会超过免费的阀值(每月5万台设备免费,每台设备每天20次免费查询补丁),再说也不妨碍我们研究下怎么用,听说用起来很方便,对程序员几乎是傻瓜式的,对我来说这点就是极大的诱惑了。事实证明,Sophix确实非常简单易用,根本不需要关心补丁怎么下载,怎么放置,怎么替换,整个流程只需要一个接口调用,补丁制作也为开发人员准备好了工具。Sophix对比其他框架的优势在哪里,上一张官网给出的图就很直观了:
真逗,还给别人家的打了**,我替它写出来好了,Amigo,Tinker,QQZone,Robust。接下来就看下怎么用吧(可能会有人奇怪为什么都有官网了,还要多此一举,知道的都知道,很多平台的技术文档详细是挺详细,就是经常会让你点击各种链接,跳来跳去的很烦)。
1、准备工作
1、注册、登录、新建产品等
进入阿里云注册和登录等,然后进入移动研发平台新建产品,成功之后获取到appKey和appSecret和RSA等以及一个aliyun-emas-services.json的配置文件,该文件包含了appKey、appSecret以及阿里的emas服务类型、状态和版本号等信息,例如:
"services": {"httpdns_service": {"status": 0,"version":"1.2.1"},"cps_service": {"status": 0,"version":"3.1.4"},"hotfix_service": {"status": 1,"version":"3.2.6"},"man_service": {"status": 0,"version":"1.2.4"},"feedback_service": {"status": 0,"version":"3.1.8"}}
status表示是否开通此服务,0为关闭,1为开通,这里我只开通了hotfix_service,即热修复服务。将该文件放入项目的app模块根目录当中,接下来是对项目进行配置,其中会有插件对该文件进行解析。
2、项目配置
在项目根目录的build.gradle文件当中加入或合并如下内容:
buildscript {repositories {maven {url 'http://maven.aliyun.com/nexus/content/repositories/releases/'}}dependencies {// 添加emas-services插件classpath 'com.aliyun.ams:emas-services:1.0.1'}
}allprojects {repositories {maven {url 'http://maven.aliyun.com/nexus/content/repositories/releases/'}}
}
在app模块的build.gradle文件当中加入或合并如下内容:
apply plugin: 'com.aliyun.ams.emas-services'
dependencies {implementation 'com.aliyun.ams:alicloud-android-hotfix:3.2.6'
}
repositories {maven {url "http://maven.aliyun.com/nexus/content/repositories/releases"}
}
在AndroidManifest.xml文件当中加入配置:
<meta-dataandroid:name="com.taobao.android.hotfix.IDSECRET"android:value="your appkey" /><meta-dataandroid:name="com.taobao.android.hotfix.APPSECRET"android:value="your appsecret" /><meta-dataandroid:name="com.taobao.android.hotfix.RSASECRET"android:value="your rsa" />
记住替换下相应的value。
2、接口接入
1、入口及回调接口
package com.qugengting.hotfixdemo;import android.content.Context;
import android.support.annotation.Keep;
import android.util.Log;import com.taobao.sophix.PatchStatus;
import com.taobao.sophix.SophixApplication;
import com.taobao.sophix.SophixEntry;
import com.taobao.sophix.SophixManager;
import com.taobao.sophix.listener.PatchLoadStatusListener;/*** Sophix入口类,专门用于初始化Sophix,不应包含任何业务逻辑。* 此类必须继承自SophixApplication,onCreate方法不需要实现。* 此类不应与项目中的其他类有任何互相调用的逻辑,必须完全做到隔离。* AndroidManifest中设置application为此类,而SophixEntry中设为原先Application类。* 注意原先Application里不需要再重复初始化Sophix,并且需要避免混淆原先Application类。* 如有其它自定义改造,请咨询官方后妥善处理。*/
public class SophixStubApplication extends SophixApplication {private final String TAG = "SophixStubApplication";public interface MsgDisplayListener {void handle(String msg);}public static MsgDisplayListener msgDisplayListener = null;public static StringBuilder cacheMsg = new StringBuilder();// 此处SophixEntry应指定真正的Application,并且保证RealApplicationStub类名不被混淆。@Keep@SophixEntry(MyApp.class)static class RealApplicationStub {}@Overrideprotected void attachBaseContext(Context base) {super.attachBaseContext(base);
// 如果需要使用MultiDex,需要在此处调用。
// MultiDex.install(this);initSophix();}private void initSophix() {String appVersion = "0.0.0";try {appVersion = this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName;} catch (Exception e) {}final SophixManager instance = SophixManager.getInstance();instance.setContext(this).setAppVersion(appVersion).setSecretMetaData(null, null, null).setEnableDebug(true).setEnableFullLog().setPatchLoadStatusStub(new PatchLoadStatusListener() {@Overridepublic void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {if (code == PatchStatus.CODE_LOAD_SUCCESS) {Log.i(TAG, "sophix load patch success!");} else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {// 如果需要在后台重启,建议此处用SharePreference保存状态。Log.i(TAG, "sophix preload patch success. restart app to make effect.");}String msg = new StringBuilder("").append("Mode:").append(mode).append(" Code:").append(code).append(" Info:").append(info).append(" HandlePatchVersion:").append(handlePatchVersion).toString();if (msgDisplayListener != null) {msgDisplayListener.handle(msg);} else {cacheMsg.append("\n").append(msg);}}}).initialize();}
}
注释写的很详细了,再稍微描述一下,AndroidManifest.xml里面的application:name要指定该类即SophixStubApplication,原来的application类配置在这个类的@SophixEntry注解里面即可,PatchLoadStatusListener是回调接口,如果有补丁加载什么的,就会回调onLoad方法了,当然,补丁不会自动下发,需要主动去拉取。我这里参考了官方的DEMO,自定义一个接口MsgDisplayListener便于DEMO演示,当然这个接口不是必须的。
2、拉取补丁
拉取补丁是非常简单的,只有一行代码:
SophixManager.getInstance().queryAndLoadNewPatch();
如果拉取成功(PatchLoadStatusListener接口回调,code参数值符合预期),那么恭喜,补丁已经补好了!只要重启APP就可以看到补丁的效果了。
顺便放上我的MainActivity代码好了:
package com.qugengting.hotfixdemo;import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;import com.taobao.sophix.SophixManager;public class MainActivity extends AppCompatActivity {private static final int REQUEST_EXTERNAL_STORAGE_PERMISSION = 0;private TextView mStatusTv;private String mStatusStr = "";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mStatusTv = findViewById(R.id.tv_status);updateConsole(SophixStubApplication.cacheMsg.toString());if (Build.VERSION.SDK_INT >= 23) {requestExternalStoragePermission();}SophixStubApplication.msgDisplayListener = new SophixStubApplication.MsgDisplayListener() {@Overridepublic void handle(final String msg) {runOnUiThread(new Runnable() {@Overridepublic void run() {updateConsole(msg);}});}};}/*** 如果本地补丁放在了外部存储卡中, 6.0以上需要申请读外部存储卡权限才能够使用. 应用内部存储则不受影响*/private void requestExternalStoragePermission() {if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},REQUEST_EXTERNAL_STORAGE_PERMISSION);}}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {switch (requestCode) {case REQUEST_EXTERNAL_STORAGE_PERMISSION:if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {updateConsole("local external storage patch is invalid as not read external storage permission");}break;default:}}/*** 更新监控台的输出信息** @param content 更新内容*/private void updateConsole(String content) {mStatusStr += content + "\n";if (mStatusTv != null) {mStatusTv.setText(mStatusStr);}}public void onClick(View view) {SophixManager.getInstance().queryAndLoadNewPatch();}}
这里也是参考了官方的DEMO写的,不想看的可直接看第三部分,如何制作、上传和发布补丁。
3、制作、上传和发布补丁
1、制作补丁
首先,准备好数字证书,编译release版本,安装到手机上,随便修改下代码表示修复的内容(我这里是替换了下资源文件)再编译一个新的release版本,从官网下载补丁工具:
Mac版本打包工具地址:http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/SophixPatchTool_macos.zip
Windows版本打包工具地址:http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/SophixPatchTool_windows.zip
Linux版本打包工具地址:http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/SophixPatchTool_linux.zip
解压运行,弹出框:
设置界面需要设置下,然后就可以GO了!然而,我这里遇到了问题,本地JDK版本有旧版本残留,虽然在DOS执行java -version是正常的显示1.8版本,但是该工具执行就是会报错,先是报了“has value '1.8', but '1.6' is required”,后来改了改又报了could not open jvm.cfg的错误,找了半天解决办法才找到,如果有同样遇到的可以参考该文章。补丁终于生成了:
接下来就是上传到后台了。
2、上传补丁
移步控制台,选择对应产品,选择移动热修复-补丁管理-添加版本(记住,补丁的版本设置跟你当前手机安装的APP版本一致,我手机安装的版本是1.0.0,刚开始我以为补丁版本号要加1,即1.0.1,结果发布后拉取补丁并没有拉取到,所以这里的版本只需设置1.0.0即可),然后上传补丁:
3、发布补丁
点击上图的详情进入下一界面,点击新建发布即可。这样,补丁就成功发布了!手机端拉取下就可以下载补丁了!
4、其他
少不了说下混淆了:
#基线包使用,生成mapping.txt
-printmapping mapping.txt
#生成的mapping.txt在app/build/outputs/mapping/release路径下,移动到/app路径下
#修复后的项目使用,保证混淆结果一致
#-applymapping mapping.txt
#hotfix
-keep class com.taobao.sophix.**{*;}
-keep class com.ta.utdid2.device.**{*;}
#防止inline
-dontoptimize
另外记得application类,避免混淆。
最后,再看看运行效果:
加载补丁前后(图一是初始状态,图二是加载补丁成功,图三是重启后效果):
我上传了代码到github,内容有所改动不过没关系,需要的可以去copy。
最后的最后,补上回调的code官方说明吧:
//兼容老版本的code说明
int CODE_LOAD_SUCCESS = 1;//加载阶段, 成功
int CODE_ERR_INBLACKLIST = 4;//加载阶段, 失败设备不支持
int CODE_REQ_NOUPDATE = 6;//查询阶段, 没有发布新补丁
int CODE_REQ_NOTNEWEST = 7;//查询阶段, 补丁不是最新的
int CODE_DOWNLOAD_SUCCESS = 9;//查询阶段, 补丁下载成功
int CODE_DOWNLOAD_BROKEN = 10;//查询阶段, 补丁文件损坏下载失败
int CODE_UNZIP_FAIL = 11;//查询阶段, 补丁解密失败
int CODE_LOAD_RELAUNCH = 12;//预加载阶段, 需要重启
int CODE_REQ_APPIDERR = 15;//查询阶段, appid异常
int CODE_REQ_SIGNERR = 16;//查询阶段, 签名异常
int CODE_REQ_UNAVAIABLE = 17;//查询阶段, 系统无效
int CODE_REQ_SYSTEMERR = 22;//查询阶段, 系统异常
int CODE_REQ_CLEARPATCH = 18;//查询阶段, 一键清除补丁
int CODE_PATCH_INVAILD = 20;//加载阶段, 补丁格式非法
//查询阶段的code说明
int CODE_QUERY_UNDEFINED = 31;//未定义异常
int CODE_QUERY_CONNECT = 32;//连接异常
int CODE_QUERY_STREAM = 33;//流异常
int CODE_QUERY_EMPTY = 34;//请求空异常
int CODE_QUERY_BROKEN = 35;//请求完整性校验失败异常
int CODE_QUERY_PARSE = 36;//请求解析异常
int CODE_QUERY_LACK = 37;//请求缺少必要参数异常
//预加载阶段的code说明
int CODE_PRELOAD_SUCCESS = 100;//预加载成功
int CODE_PRELOAD_UNDEFINED = 101;//未定义异常
int CODE_PRELOAD_HANDLE_DEX = 102;//dex加载异常
int CODE_PRELOAD_NOT_ZIP_FORMAT = 103;//基线dex非zip格式异常
int CODE_PRELOAD_REMOVE_BASEDEX = 105;//基线dex处理异常
//加载阶段的code说明 分三部分dex加载, resource加载, lib加载
//dex加载
int CODE_LOAD_UNDEFINED = 71;//未定义异常
int CODE_LOAD_AES_DECRYPT = 72;//aes对称解密异常
int CODE_LOAD_MFITEM = 73;//补丁SOPHIX.MF文件解析异常
int CODE_LOAD_COPY_FILE = 74;//补丁拷贝异常
int CODE_LOAD_SIGNATURE = 75;//补丁签名校验异常
int CODE_LOAD_SOPHIX_VERSION = 76;//补丁和补丁工具版本不一致异常
int CODE_LOAD_NOT_ZIP_FORMAT = 77;//补丁zip解析异常
int CODE_LOAD_DELETE_OPT = 80;//删除无效odex文件异常
int CODE_LOAD_HANDLE_DEX = 81;//加载dex异常
// 反射调用异常
int CODE_LOAD_FIND_CLASS = 82;
int CODE_LOAD_FIND_CONSTRUCTOR = 83;
int CODE_LOAD_FIND_METHOD = 84;
int CODE_LOAD_FIND_FIELD = 85;
int CODE_LOAD_ILLEGAL_ACCESS = 86;
//resource加载
public static final int CODE_LOAD_RES_ADDASSERTPATH = 123;//新增资源补丁包异常
//lib加载
int CODE_LOAD_LIB_UNDEFINED = 131;//未定义异常
int CODE_LOAD_LIB_CPUABIS = 132;//获取primaryCpuAbis异常
int CODE_LOAD_LIB_JSON = 133;//json格式异常
int CODE_LOAD_LIB_LOST = 134;//lib库不完整异常
int CODE_LOAD_LIB_UNZIP = 135;//解压异常
int CODE_LOAD_LIB_INJECT = 136;//注入异常
最后的最后的最后,经过我反复测试,发现官网所说的支持热启动并不是事实,覆盖补丁之后,不仅需要重启,而且是需要杀掉进程的那种重启,补丁才能生效。(后来遇到一次不需要重启的了,我凌乱了,还没抓住规律)
阿里Sophix热修复框架使用入门相关推荐
- 阿里SopHix热修复框架
2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker(Bugly sdk也集成Tikner ...
- 阿里Sophix热修复体验
前言: 之前看了关于热修复的相关文章,想找个代码试试,奈何感觉使用起来有些麻烦,之后就不了了之.看到了阿里的Sophix,嗯,感觉不那么复杂,步骤简单,就着手自己敲了敲.主要记录下自己找了很久,费时步 ...
- 阿里移动热修复Sophix使用体验
2019独角兽企业重金招聘Python工程师标准>>> Android 热修复是个热门技术,各大公司都推出了自己的热修复框架,阿里也推出了全新的Sophix,我决定写个Demo 测试 ...
- 阿里云热修复sophix详解
现在网上有几种常用的app热修复技术,个人感觉阿里云热修复操作比较简单,主要几个步骤,创建app---下载sdk---集成(AS和eclipse)---生成补丁---发布补丁(可以本地调试).下面详细 ...
- 深入解析阿里Android热修复技术原理
前言:本文框架 什么是热修复? 热修复框架分类 技术原理及特点 Tinker框架解析 各框架对比图 总结 通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简 ...
- Android—常用热修复框架
前言 热修复即<打补丁>,当一个app上线后,如果发现重大的bug,需要紧急修复.常规的做法是修复bug,然后重新打包,再上线到各个渠道.这种方式的成本高,效率低. 于是热修复技术应运而生 ...
- Android之热修复框架Nuwa
转载请标明出处: http://blog.csdn.net/hai_qing_xu_kong/article/details/70284239 本文出自:[顾林海的博客] ##前言 当热修复框架还没出 ...
- 热修复框架Tinker的从0到集成之路(转)
转自:http://blog.csdn.net/lisdye2/article/details/54411727 热修复框架Tinker的从0到集成之路 转载请标明出处: http://blog.c ...
- 【Android 热修复】热修复原理 ( 热修复框架简介 | 将 Java 字节码文件打包到 Dex 文件 )
文章目录 一. 热修复框架简介 1.类替换 2.so 替换 3.资源替换 4.全平台支持 5.生效时间 6.性能损耗 7.总结 二. 将 Java 字节码文件打包到 Dex 文件 一. 热修复框架简介 ...
- 热修复框架AndFix【源码阅读】
前言 AndFix是阿里巴巴开源的Android热修复框架.其基本原理是利用JNI来实现方法的替换,以实现Android APP的热修复,即无需发版即可临时修复在线BUG. 热修复技术有很多种,And ...
最新文章
- 从严把控_精准把控 推动从严治党走深走实
- mysql查询语句判断日期_mysql语句查询时间检测
- Egret note
- 从“学徒”(Apprentice III)看领导力(9-17集)
- 攻防比赛_2020年度泉州市大学生网络安全攻防比赛在黎明职业大学圆满落幕
- Android系统(2)---init.rc知识
- 计算机通信与专业英语翻译,电子信息与通信工程专业英语王立琦版课文翻译
- 定时任务_定时任务Quartz入门
- linux project 软件下载,项目计划管理画甘特图工具Ganttproject安装(for linux)
- java映射的概念_Java之路:映射(Map)
- 00001__伊丽莎白福尔摩斯
- 多目标人工秃鹫优化算法(MATLAB源码分享,智能优化算法) 提出了一种多目标版本的人工秃鹫优化算法(AVOA)
- 如何快速学习flex
- MUI 调用原生方法跳转QQ添加群
- 聊聊短信接口攻击的防范方案
- php artisan migrate,PHP artisan迁移不创建新表
- WinInet编程中如何使用异步
- 帮助计算机网络犯罪活动罪司法解释,帮助信息网络犯罪活动罪司法适用研究
- 了解vue中的v-model,通俗易懂!
- 恶搞!关闭程序进程!!嘿嘿嘿~
热门文章
- OpenCV 安装配置 Jupyter Notebook
- DBSCAN聚类算法原理总结
- python 读取excel表内容:以获取高铁站点经纬度为例子
- 深度学习入门-基于python的理论与实现-深度学习
- 移动端h5原生分享到朋友圈、微博等
- 计算机找不到海信电视,海信电视到底怎么投屏,看这一篇就够了!
- 程序员课外拓展004:Photoshop CC 2018详细图文安装教程
- fgo国服登陆显示服务器错误,命运冠位指定安装失败怎么办 FGO国服安装失败解决办法...
- 基于Java内置的HttpServer实现轻量级Restful
- pdf批量添加图章_还没找到适合自己的PDF阅读器吗,它来了