1. 程式人生 > >android熱修復之Robust使用

android熱修復之Robust使用

最近美團點評開源了其基於Instant Run 的熱修復方案Robust,並且官方公佈了修復率達99.9%成功率,聽起來蠻誘人的。當然,市面上還有其他兩種熱修復方案:

  • 基於multidex的熱更新方案,如企鵝的Tinker
  • 基於native hook方案,如貓廠的AndFix

只能說各有優劣吧。Robust是為每個函式都插入了一段邏輯,會增加app的體積,但是相容性好些。原理篇,美團點評之前就有介紹:
http://www.tuicool.com/articles/JjaaayV
Robust的github地址:
https://github.com/Meituan-Dianping/Robust


注意:現在最新版本是0.3.2。0.3.0版本時,只支援Linux和Mac系統!0.3.1及之後的版本是支援Windows的,看文件很重要!
首先,吐槽下美團點評的文件寫的確實不夠詳細,demo整理的有些亂。不過從issue中總能得到答案。接入的過程及過程中遇到了一些坑,現在記錄下,也是學習的過程:
1.在App的build.gradle,加入依賴

apply plugin: 'com.android.application'
//製作補丁時將這個開啟,auto-patch-plugin緊跟著com.android.application
//apply plugin: 'auto-patch-plugin'
apply plugin: 'robust' dependencies{ compile 'com.meituan.robust:robust:0.3.2' }

2在整個專案的build.gradle加入classpath

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
         classpath 'com.meituan.robust:gradle-plugin:0.3.2'
         classpath 'com.meituan.robust:auto-patch-plugin:0.3.2'
}
}

3.在app的src同級路徑下配置robust.xml
主要配置了Robust相關的內容,如是否開啟Robust,是否強制插入程式碼,需要熱補的包名或類名,是否開啟混淆,補丁的包名等。這裡主要注意下需要熱補的包名hotfixPackage和補丁的包名patchPackname。本例是將MainActivity中的TextView通過Robust熱修復將內容改變,以模擬熱修復的功能。主要配置如下:

    <packname name="hotfixPackage">
        <name>com.jarry.testrobust</name>
    </packname>
    <!--補丁的包名-->
    <patchPackname name="patchPackname">
        <name>com.jarry.testrobust.patch</name>
    </patchPackname>

這裡重點注意下patchPackname,表示補丁包的包名,需要在修復的配置類PatchManipulateImp中設定下PatchesInfoImplClassFullName,也就是最終生成的補丁類所在包名,補丁類是PatchesInfo的實現類。關鍵程式碼如下:

public class PatchManipulateImp extends PatchManipulate {
    @Override
    protected List<Patch> fetchPatchList(Context context) {
        patch.setPatchesInfoImplClassFullName(
       "com.jarry.testrobust.patch.PatchesInfoImpl");                    
        List patches = new ArrayList<Patch>();
        patches.add(patch);
        return patches;
    }
}

PatchManipulateImp 這個配置類在使用補丁的時候是需要用到的,用於開啟補丁程式碼。後面生成修復檔案patch.jar的時候會介紹到。在補丁包已經儲存到sd卡的情況下,通過執行以下程式碼讓補丁包生效。

new PatchExecutor(getApplicationContext(), new PatchManipulateImp(), new Callback()).start();

給你的project加上讀寫sdcard的許可權,別忘了親,最基本的,或許會導致最低階的錯誤!

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

4.打正式包,並生成mapping.txt檔案和methodsMap.robust檔案:

先將專案進行混淆,執行如下命令打成正式包:

gradlew clean  assembleRelease --stacktrace --no-daemon

得到mapping.txt檔案和methodsMap.robust檔案,目錄所在位置分別為:

這裡寫圖片描述

將得到的以上兩個檔案放到app/robust資料夾下,也就是和src同級的目錄
這裡寫圖片描述

5.製作patch.jar補丁包檔案
首先開啟自動補丁外掛,並sync now!
這裡寫圖片描述
修改Main2Activity中的getStr()程式碼,並將方法getStr()和onCreate()方法都加上@Modify註解,這裡注意,兩個方法都要加註解,不加你就鬱悶的打包吧= =!如下:
這裡寫圖片描述
這裡是我踩過的坑:
如果不在Main2Activity的呼叫處新增@Modify註解,會報 “patch method is empty ,please check your Modify annotation or use RobustModify.modify() to mark modified methods”異常,也就是可以理解為,你沒有修改或者新增程式碼。順便好好clean下project,以防你修改的程式碼沒生效,沒被robust先森識破。

ok,是時候打patch包了,執行打包命令:

gradlew clean  assembleRelease --stacktrace --no-daemon

會丟擲異常並看到java.lang.RuntimeException: auto patch end successfully。說明補丁包生成成功。在outputs/robust/資料夾下會看到兩個檔案,patch.dex和patch.jar。
提示:如果你看到的結果是“patch method is empty ,please check your Modify annotation…”,建議你先clean下工程再重新嘗試打包命令,如果還不成功,那就建議你檢查下是不是和我上面說的步驟有出入的地方。
將補丁包push到手機上

6.驗證補丁包
將outputs/robust/patch.jar包push到手機對應的/sdcard/robust/patch_temp.jar上。

>adb push E:\android2p2install\workspace\TestRobust\app\build\outputs\robust\patch.jar /sdcard/robust/patch_temp.jar

push成功後,開啟已經install到手機上的正式包,然後點選patch按鈕,也就是觸發如下操作:
這裡寫圖片描述
然後跳轉到Main2Activiy中,發現顯示的文字是patch包中的文字,如下所示:
這裡寫圖片描述
ok,首次使用成功。