当我们刚发布一个版本后,突然发现了一个严重的bug。由于刚发布版本,这时候如果再紧接着发布一个版本,这时候给用户的体验肯定很差。而热修复技术可以在用户不知道的情况下修复已知的bug。目前各大厂都推出了自己的热修复方案,各个方案的差别如下(这是阿里巴巴给的对比):
平台 | 阿里云移动热修复 | Amigo(饿了吗) | Tinker(微信) | Qzone(QQ空间) | Robust(美团) |
---|---|---|---|---|---|
即时生效 | yes | yes | no | no | yes |
性能损耗 | 较小 | 较小 | 较大 | 较大 | 较小 |
侵入式打包 | 无侵入式打包 | 无侵入式打包 | 依赖侵入式打包 | 依赖侵入式打包 | 依赖侵入式打包 |
Rom体积 | 较小 | 较小 | 较大 | 较小 | 较小 |
接入复杂度 | 傻瓜式接入 | 比较简单 | 复杂 | 比较简单 | 复杂 |
补丁包大小 | 较小 | 较小 | 较小 | 较大 | 一般 |
全平台支持 | yes | yes | yes | yes | yes |
类替换 | yes | yes | yes | yes | no |
so替换 | yes | no | yes | no | no |
资源替换 | yes | no | yes | yes | no |
此篇文章并不讲述热修复的原理,只是整理了Sophix的接入过程。
Sophix 是阿里云提供的全平台App热修复服务方案。产品基于阿里巴巴首创hotpatch技术,提供最细粒度热修复能力,让您无需等待实时修复应用线上问题。
Android studio 3.5
在 Android studio 中已经没有 instant run ,无需再关闭了。
打开项目找到app的build.gradle文件,添加如下配置:
添加maven仓库地址:
repositories {
maven {
url "http://maven.aliyun.com/nexus/content/repositories/releases"
}
}
添加 sophix 版本依赖:
implementation 'com.aliyun.ams:alicloud-android-hotfix:3.2.8'
在阿里的管理控制台申请APP,获取如下信息:
详细信息参考:https://help.aliyun.com/document_detail/53238.html?spm=a2c4g.11186623.6.556.13005482ekgO0n
加入以下这个类:
package cn.zzw.sophixdemo;
import android.content.Context;
import android.util.Log;
import androidx.annotation.Keep;
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";
// 此处SophixEntry应指定真正的Application,并且保证RealApplicationStub类名不被混淆。
@Keep
@SophixEntry(MyRealApplication.class)
static class RealApplicationStub {
}
@Override
protected 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() {
@Override
public 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.");
}
}
}).initialize();
}
@Override
public void onCreate() {
super.onCreate();
SophixManager.getInstance().queryAndLoadNewPatch();
}
}
其中:MyRealApplication 是原来APP中对应的Application 类,继承于Application。
queryAndLoadNewPatch 主要用于查询服务器是否有新的可用补丁。不可放在attachBaseContext 中,否则无网络权限,建议放在后面任意时刻,如onCreate中。
参考:https://help.aliyun.com/document_detail/61082.html?spm=a2c4g.11186623.6.560.46525abdB7ZdTf#h2-1-3-sdk-3
需要的权限:
在 application 节点下添加如下配置:
3种信息从 3.3 中的截图中去获取。
在 proguard-rules.pro 中添加如下信息:这里也包含了 glide 的混淆配置
#基线包使用,生成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.**{*;}
-dontwarn com.alibaba.sdk.android.utils.**
#防止inline
-dontoptimize
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
此步骤跟 sophix 没有什么关系,Android studio 怎么打包签名问度娘吧。
这里修复前和修复后的代码只修改了 mWifePath 中的值,其他的并未修改。
package cn.zzw.sophixdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
public class MainActivity extends AppCompatActivity {
String mWifePath = "https://timgsa.baidu.com/timg?image&quali" +
"ty=80&size=b9999_10000&sec=1569899302358&di=527629cb21" +
"3ba016d1d7870c039cd7a0&imgtype=0&src=http%3A%2F%2Fimg2." +
"dzwww.com%3A8888%2Ftupian%2F20180123%2F201801230218b226c429421520.jpg";
ImageView mImg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImg = findViewById(R.id.mImg);
mImg.setVisibility(View.VISIBLE);
Glide.with(this)
.load(mWifePath)
.into(mImg);
}
}
patch补丁包生成需要使用到打补丁工具SophixPatchTool, 如还未下载打包工具,请前往下载Android打包工具。
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
调试工具地址:http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/hotfix_debug_tool-release.apk
生成补丁:
生成后补丁必须命名为:sophix-patch.jar
具体参考:https://help.aliyun.com/document_detail/93826.html?spm=a2c4g.11186623.2.10.71705b84F2jqaa
具体参考如下:
https://help.aliyun.com/document_detail/93805.html?spm=a2c4g.11186623.6.557.30c82dee8gN4kl
https://help.aliyun.com/document_detail/93806.html?spm=a2c4g.11186623.6.558.12be6f60gYn71i
https://help.aliyun.com/document_detail/93808.html?spm=a2c4g.11186623.6.559.4ad52deeJmFx2D
这里先安装了旧版本的APP,然后按 back 键后,再次进入APP,发现图片已经做了修改。
这里只是简单的讲了 sophix 的集成, 后续将会梳理下热修复的原理。如果想要更多的范例请参考 sophix 在GitHub 上面的例子:https://github.com/aliyun/alicloud-android-demo/tree/master/hotfix_android_demo?spm=a2c4g.11186623.2.23.75525482pLFpAC