相信不少人都認識瞭解過 熱修復、熱更新、熱補丁(對於這個技術也沒有特別標準的一種叫法,下面我統一叫熱更新),以後的一年裏,各類熱更新方案如雨後春筍般出現,比較耳熟能詳的就有Nuwa、Tinker、Andfix 和 Dexposed 等等,他們之間的區別以及優缺點就不在這裏討論了,鑑於它們的實際使用和侷限性,美團的開發團隊就腦洞大開了。html
就去年 Google 高調發布了 Android Studio 2.0,其中最重要的新特性Instant Run,實現了對代碼修改的實時生效(熱插拔)。美團開發團隊在瞭解 Instant Run 原理以後,實現了一個兼容性更強的熱更新方案,這就是產品化的hotpatch框架—–Robustandroid
對於 Robust 的原理咱們後面的文章再討論,本篇只針對想快速上手的入門講解,想先了解 Robust 的原理以及技術核心的同窗請移步到git
Android熱更新方案Robustgithub
Android熱更新方案Robust開源,新增自動化補丁工具app
先介紹一下 Robust 的適用場景,與以往你們認識的熱更新同樣,對線上事故很難有即時生效的解決方式,每次發版都如臨深淵如履薄冰,畢竟就算再完善的開發測試流程也沒法保證不會將 Bug 帶到線上,特別是新 app 剛上線,一個bug不僅是影響到幾個幾十個用戶,一些創業性app的崩潰或者bug可能直接致使用戶卸載和永不使用。對於這種致命的又迫不得已的問題,Robust 就是時候該站出來摸摸你的頭,輕聲而又自信的說「別怕,你還有我」。工具
1.集成了 Robust 後,生成 apk。保存期間的混淆文件 mapping.txt,以及 Robust 生成記錄文件 methodMap.robust
2.使用註解 @Modify 或者方法 RobustModify.modify() 標註須要修復的方法
3.開啓補丁插件,執行生成 apk 命令,得到補丁包 patch.jar
4.經過推送或者接口的形式,通知 app 有補丁,須要修復
5.加載補丁文件不須要從新啓動應用測試
首先遠程依賴 Robust 的一些插件,用於輔助生成 patch.jar 的。此時咱們不須要深刻了解,只須要知道它是用來輔助的就好。在項目最外層的 build.gradle 添加兩處插件fetch
classpath ‘com.meituan.robust:gradle-plugin:0.3.3’
classpath ‘com.meituan.robust:auto-patch-plugin:0.3.3’gradle
而後在項目的 build.gradle 添加
//apply plugin: ‘auto-patch-plugin’
apply plugin: ‘robust’compile ‘com.meituan.robust:robust:0.3.3’
此時,還沒完成第一步呢,別急,須要手動 copy 一份 robust.xml 的配置文件到app的目錄下,該文件各個配置註釋的很清楚,若沒特殊要求,不須要修改
好了,準備工做完成。有了這些東西,待咱們須要修復的時候就能夠一鍵生成補丁 patch.jar 了。但別急,你還不知道怎麼加載補丁呢…
先解釋一下,如上圖標註所說了,在生成 apk 的時候使用 apply plugin:’robust’,該插件會生成打補丁時須要的方法記錄文件 methodMap.robust,該文件在打補丁的時候用來區別到底哪些方法須要被修復,因此有它才能打補丁。而上文所說的還有 mapping.txt 文件,該文件列出了原始的類,方法和字段名與混淆後代碼間的映射。這個文件很重要,能夠用它來翻譯被混淆的代碼。但也不是必須的,若是不須要混淆,能夠不保留。這兩個文件在生成apk後,分別在
build/outputs/robust/methodsMap.robust,build/outputs/mapping/mapping.txt(須要開啓混淆後纔會出現),咱們須要本身分別拷貝到 app/robust 下,在 app 目錄新建個叫 robust 的文件夾,把這兩個文件放進去就 ok 了。
此時,完成了第二步了。咱們獲得了 apk ,mapping.txt,methodMap.robust ,有了它們咱們再繼續生成補丁 patch.jar。然而我踩到過的坑是,沒有簽名文件同樣能夠完成上述步驟,但在安裝apk的時候會被告知該 apk 已損壞,因此按普通簽名那樣加上簽名文件就好了。
咱們新建的工程很簡單,只有2個button,一個用來加載補丁,一個用來跳轉。如圖,首頁和沒加載補丁時跳轉的頁面。剛纔咱們說,要怎麼使用補丁文件,看下面加載補丁的按鈕事件裏面,看到了沒,就那麼一句話就能實現加載補丁了。
new PatchExecutor(上下文我懂,xxx,callback我也懂).start()
中間的xxx是個什麼東西啊,還須要本身寫?帶着這個疑問去思考一下,就不難發現,要加載補丁確定得知道 patch.jar 放在哪啊是吧,打開看一眼(不要懼怕只有不多代碼),爲了方便展現,就把不過重要的三個方法縮起來了,copy 方法是普通文件拷貝的IO流,verifyPatch 方法原本是驗證補丁有效性的,後來發現對普通使用者沒有那麼高要求,就改爲了備份補丁的回調了,ensurePatchExist 方法就檢測補丁存在與否,好了大概知道其它的方法就詳細介紹下主要方法 fetchPatchList,回顧一下上面的xxx再聯想到這裏吧,既然咱們要加載補丁,那麼咱們得知道補丁在哪啊,這個方法就是把補丁找出來給上面那個誰用的。因此說,補丁的位置你能夠根據拉取下來保存的位置來找出來,把路徑給 setLocalPath 就好。再有就 setPatchesInfoImplClassFullName 的包名須要和 robust.xml 配置的同樣
咱們所須要作的跳轉後效果是修改一下textview顯示內容而已,那麼在被修改的頁面須要怎麼標註被修改的方法呢,就像這樣,先科普一下,在 robust 的注意事項裏面已經提到過,修改方法和字段會有一些侷限性,那是由於 android 自己ProGuard的內聯、優化致使的。因此要繞過這個自己的問題,要必須遵循一些規律了…之後再介紹這個。修改完這些,咱們再去 build.gradle 修改一下,開啓打補丁那個,關閉生成apk那個。以後再在終端執行一遍生成apk的命令行。直到終端那裏出現 auto patch end successfully(最後 build failed 是正常的,別緊張孩子)。再而後就是要把patch.jar push 到手機目錄路徑下啦。那些本身推送下載的請自行調試更正,確保路徑正確。還有記得給應用讀寫內存卡的權限
既然到了這裏,咱們好像全部條件都具有了啊,那麼就點 LOAD PATCH 按鈕看看發生什麼事吧,若是看到 apply result true 那麼就大功告成了。
最後來個效果圖
謝謝美團開發團隊的開源和貢獻,還要特別感謝Robust做者之一的張夢同窗,爲 Robust 挖下的坑(開玩笑哈哈哈),咱們努力排坑只但願能讓你們更簡便的使用,之後的路還很長…你們有什麼建議或意見,請到 github 上面去留言。