1. 前言
當我們剛發佈一個版本後,突然發現了一個嚴重的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的接入過程。
2. Sophix介紹
Sophix 是阿里雲提供的全平臺App熱修復服務方案。產品基於阿里巴巴首創hotpatch技術,提供最細粒度熱修復能力,讓您無需等待實時修復應用線上問題。
主要解決問題
- (1)產品已有功能,出現問題,無需發版,即可發補丁,實時修復。
- (2)存量功能微調。
3. Sophix 的集成
3.1 開發工具
Android studio 3.5
在 Android studio 中已經沒有 instant run ,無需再關閉了。
3.2 gradle 中添加配置
打開項目找到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'
3.3 添加產品
在阿里的管理控制檯申請APP,獲取如下信息:
詳細信息參考:https://help.aliyun.com/document_detail/53238.html?spm=a2c4g.11186623.6.556.13005482ekgO0n
3.4 SDK 穩健接入
加入以下這個類:
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中。
3.5 修改 AndroidManifest.xml 文件
需要的權限:
<!-- 網絡權限 -->
<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"/>
在 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密鑰" />
3種信息從 3.3 中的截圖中去獲取。
3.6 混淆配置
在 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 *;
}
3.7 打包簽名生成舊版本的APP
此步驟跟 sophix 沒有什麼關係,Android studio 怎麼打包簽名問度娘吧。
3.8 修改代碼,並重新打包
這裏修復前和修復後的代碼只修改了 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);
}
}
3.9 生成補丁
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
3.10 創建版本以及上傳/發佈補丁
具體參考如下:
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
3.11 修復結果
這裏先安裝了舊版本的APP,然後按 back 鍵後,再次進入APP,發現圖片已經做了修改。
4. 總結
這裏只是簡單的講了 sophix 的集成, 後續將會梳理下熱修復的原理。如果想要更多的範例請參考 sophix 在GitHub 上面的例子:https://github.com/aliyun/alicloud-android-demo/tree/master/hotfix_android_demo?spm=a2c4g.11186623.2.23.75525482pLFpAC