熱更新: 就是在應用無需重新安裝情況下實現更新,從而實現動態修復功能。
在熱更新之前,如果線上的應用出現bug, 是需要用戶重新下載然後安裝,這樣的操作對用戶來說肯定是不能接受的,什麼軟件,時不時就重新下載安裝,用戶體驗極差, 熱更新出現之後,這樣的問題就可以得到解決,在用戶無感知的情況下就可以把bug修復。
目前比較火的熱修復的分爲阿里系、騰訊系、 其他大廠。
- 阿里系 : DeXposed 、 andfix 從底層二進制入手 (c語言)。
- 騰訊系 : tinker 、Qzone 從類加載入手 。
- 美團: Robust 從類加載入手 。
下面給出幾個大廠的框架區別
在集成熱更新之前,比較過幾個框架,最終還是選擇Tinker。 下面就介紹集成Tinker步驟。 跑通tinker中的demo
源碼 : https://github.com/Tencent/tinker
1: 在工程目錄下的build.gradle中,添加tinker-patch-gradle-plugin的依賴
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.1')
2: 然後在app的gradle文件app/build.gradle, 需要添加tinker的庫依賴以及apply tinker的gradle插件。
implementation('com.tencent.tinker:tinker-android-lib:1.9.1')
implementation("com.tencent.tinker:tinker-android-loader:1.9.1") { changing = true }
annotationProcessor("com.tencent.tinker:tinker-android-anno:1.9.1") { changing = true }
implementation "com.android.support:multidex:1.0.1"
具體的可以參考 tinker 中的demo中的build.gradle文件。
3: copy demo中的代碼到自己的工程中。
4:添加權限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
經過上面的步驟,前面的工作是差不多集成完了,但是build的時候 會出現很多問題, 在build出現錯誤時,請看下面的常見錯誤。
現在就寫代碼來測試下。
1 : 界面就兩個按鈕 和textview結果顯示 , 長這樣。
2:點擊“寫入pitch文件”執行的代碼
public void doHotFix(Context context) throws IllegalAccessException, NoSuchFieldException, ClassNotFoundException {
if (context == null) {
return;
}
mContext=context;
OkHttpClient client=new OkHttpClient();
Request request= new Request.Builder().url(url).get().build();
Call call=client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.e("TAG", "onFailure: " );
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.e("51app", "onSuccess");
FileOutputStream fos = null;
try {
String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
File apkFile = new File(sdPath, "patch_signed_7zip");
Log.e("51app", "size==" + apkFile.getTotalSpace());
if (apkFile.exists()) {
apkFile.delete();
}
apkFile.createNewFile();
fos = new FileOutputStream(apkFile);
fos.write(response.body().bytes());
}catch (Exception e) {
e.printStackTrace();
}finally {
try {
if (fos != null)
fos.close();
} catch (IOException e) {
Log.e("51app", "downloadPatch IOException:");
e.printStackTrace();
}
}
}
});
//加載補丁包
TinkerInstaller.onReceiveUpgradePatch(MainActivity.this, Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip");
}
代碼的功能就是從服務器獲取patch_signed_7zip文件,然後寫入到本地, 在調用Tinker中的方法來修復。怎麼生成這個差量文件patch_signed_7zip 下面會說到。
3: 點擊“計算獲取結果” 按鈕 執行的代碼
btn_result.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int a=12;
int b=0;
int result=a/b;
tv_result.setText(result);
}
});
點擊執行的時候 ,肯定是崩潰的。會拋ArithmeticException divide by Zero異常。
4: 在activity生命週期方法中的onPause和onResume 調用tinker中的接口。
@Override
protected void onResume() {
super.onResume();
Utils.setBackground(false);
}
@Override
protected void onPause() {
super.onPause();
Utils.setBackground(true);
}
5: 生成基準包, 雙擊這個。也可以直接運行生成 然後在build目錄下會生成,
安裝下這個基準包,然後點擊’獲取結果按鈕‘ 程序會崩潰
6:修改app的gradle文件app/build.gradle
7:修復那個基準包的異常,點擊“計算獲取結果” 按鈕 執行的代碼
btn_result.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int a=12;
int b=0;
if (b==0){
tv_result.setText("除數爲0拉");
return;
}
int result=a/b;
tv_result.setText(result);
}
});
除數爲0 時 直接return。 就不會崩潰了。
8: 生成差量包, 雙擊tinkerPatchDebug。 然後在該build下的目錄生成。
- patch_signed.apk 簽過名的
- patch_unsigned.apk 未簽過名的
- patch_signed_7zip.apk 經過壓縮的簽名過的包
然後把patch_signed_7zip.apk 這個文件放在服務器上。 就可以測試了。 (我測試時把這個名字該了), 還是運行那個基準包。
可以看到我們首先點擊’計算獲取結果‘是會崩潰的, 然後我們點擊’‘
寫入pitch文件 如果成功會有success提示 失敗的話也會又提示 現在我們看到succeed 說明已經合成成功了爲什麼還是崩潰呢。
原因是tinker不是立即生效的。
合成成功後,我們手動殺掉這個應用的進程,然後再打開 點擊“獲取計算結果” 就不會崩潰了,說明熱更新更能集成完畢。
常見問題
1 :再生成差量包時 versioncode 需要+1 不然合成的時 會失敗。
2:如果在生成差量文件時 build出現異常導致 生成失敗的話 就把這個值設置爲true
3:tinkerid 我的是設置爲 git的版本號。 也可以設置爲 版本號。 保持唯一性, 不然的話 build會失敗。
4: 關掉androidsudio 中的 install run 功能。 不然也會build失敗
感謝關注我的公衆號
參考文檔
Tinker接入指南 :https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
常見問題 : https://github.com/Tencent/tinker/wiki/Tinker-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
熱修復原理 :
https://blog.csdn.net/csdn_lqr/article/details/78534065