手把手教你集成熱修復Tinker。

熱更新: 就是在應用無需重新安裝情況下實現更新,從而實現動態修復功能。

在熱更新之前,如果線上的應用出現bug, 是需要用戶重新下載然後安裝,這樣的操作對用戶來說肯定是不能接受的,什麼軟件,時不時就重新下載安裝,用戶體驗極差, 熱更新出現之後,這樣的問題就可以得到解決,在用戶無感知的情況下就可以把bug修復。

目前比較火的熱修復的分爲阿里系、騰訊系、 其他大廠。

  1. 阿里系 : DeXposed 、 andfix 從底層二進制入手 (c語言)。
  2. 騰訊系 : tinker 、Qzone 從類加載入手 。
  3. 美團: 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下的目錄生成。

在這裏插入圖片描述
在這裏插入圖片描述

  1. patch_signed.apk 簽過名的
  2. patch_unsigned.apk 未簽過名的
  3. 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

https://blog.csdn.net/itermeng/article/details/79350945

https://blog.csdn.net/itermeng/article/details/79362042

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章