深度解構 Android 應用面臨緊急發版時的救星方案:mPaaS 熱修復——DexPatch

 

 

方案介紹

爲了解決 Native 模塊上線後的問題,mPaaS 提供了熱修復功能,實現不發佈客戶端 apk 場景下的熱修復。目前 Android 端熱修復主要包括 andfix 和 dexpatch,考慮到 andfix 的版本兼容性,目前主要推薦使用 DexPatchandroid

DexPatch 修復原理比較簡單,就是在啓動後經過 RPC 拉取當前須要下發的 jar 包地址,而後經過獨立進程去下載 jar 包文件,下載完成後保存。在二次啓動的時候 hook 系統的 classLoader,修改 DexPathList,在其數組的最前面加入一個有修改過的 class 的 dex 文件,使其攔截住數組後面的 dex 文件中同名的 class 的加載。apache

以下圖所示,classloader 就會優先加載 Patch.dex 中的 Ding.class,而忽略 Classes.dex 中的 Ding.class,達到了替換的效果。  數組

1.png

 

基於這樣的原理,DexPatch 具備如下特徵:框架

  1. 1. 支持範圍上:是基於類級別的替換,因此只支持 Java 模塊的 patch,不支持非 Java 模塊的 patch,好比 so 模塊;
  2. 2. 兼容性上:因爲是代理了系統的 ClassLoader,使用的黑科技較少,因此總體方案兼容性較好;
  3. 3. 生效時效性上:只能在下載 patch 後重啓後才能生效,不支持實時生效;
  4. 4. 成功率上:因爲下載是使用的獨立進程,減小了啓動階段主進程閃退對 patch 下載的影響,提高了下載的成功比例。

 

 

操做說明

如下是關於在 mPaaS 下使用 DexPatch 模塊的主要步驟以及問題排查思路,方便開發者平常開發。less

1. 觸發 patch 拉取

啓動階段調用 MPHotpatch.init(),主要觸發 Patch 信息的 RPC 請求,若是命中發佈 Patch 發佈規則,RPC 會返回 Patch 的 jar 包下載地址,客戶端去觸發下載,下載後保存在客戶端私有目錄/data/user/0/包名/dexpatch/patch/下。ide

2.png

 

2. 代碼操做演示

以組件化模式接入爲例,介紹下 Patch 發佈的主要流程。工具

(1)代碼改動前組件化

3.png

須要保存改動前的構建產物,方便後續作 Patch 生成,地址在:build/intermediates/bundle/xxxx-raw.jargradle

 

(2)代碼改動後ui

4.png

從新編譯,保存構建產物,產物地址:build/intermediates/bundle/xxxx-raw.jar

 

(3)生成白名單配置

主要用於熱修復包時用於指定修復的類,配置文件爲 .txt 格式,該配置文件應包含並按順序包含如下信息:
須要 Patch 的類。以 L 開頭,後跟以混淆後真實類名。若是多個類,每行只可寫一個。示例:Lxxx.xxx.clazzX設置 Patch 類型爲 dexpatch。示例:PatchType: dexpatch

設置是不是靜態 Bundle。默認爲 false,若是是靜態連接的 Bundle,須要顯式設置爲 true。示例:HostDex: true(*目前 mPaaS 客戶端的模塊通常都在靜態連接裏,通常寫 true)

5.png

 

(4)查看簽名

生成 patch 須要用到項目的打包祕鑰,須要提早準備好,能夠在打包腳步下找到對應的配置

6.png

 

(5)生成 patch

① 經過 mPaaS 自帶的 IDE 工具,點擊熱修復,進入修復頁面。

7.png

 

② 按照頁面提示,填入以前準備的修復前和修復後的 jar 包地址,還有白名單配置文件,勾選 dexPatch,進入到下一步

8.png

 

③ 下一步主要選擇打包的配置文件,最近點擊完成生成 patch 文件

9.png

 

(6)生成 patch 產物

生成 patch 產物以下:

10.png

 

查看產物,可使用 dex2jar 工具反解 diff.dex 文件,用 jd-gui 文件查看反解產物是否符合預期

11.png

 

反解後能夠看到修改的模塊:

12.png

 

(7)上傳發布

① 選擇上一步的產物 jar 包進行上傳

13.png

 

② 上傳後能夠經過白名單進行發佈,驗證 patch 的穩定性

14.png

 

(8)驗證下載

白名單發佈後,啓動客戶端,搜索關鍵字:DynamicRelease,能夠看到在 tool 進程有觸發下載的日誌打出。
這裏須要說明的是,這裏觸發 patch 的下載是在 tool 進程,不在主進程的主要緣由是怕因爲主進程因爲啓動致使重複閃退,致使 patch 不能下載成功,單獨在 tool 進程實現下載,儘可能提升 patch 的下載成功比例。

15.png

 

而後去下載目錄查看,是否下載保存成功,下載目錄在:/data/user/0/包名/dexpatch/patch/20201023110012@20201023110012.jar

16.png

 

(9)殺進程啓動

確認下載保存成功後,殺掉 App,重啓查看是否生效,重啓能夠搜索關鍵字:DexPatchManager,查看 patch 生效的日誌,日誌會打印當前是否存在 patch 以及 patch 是否加載的日誌。

17.png

 

同時咱們也能夠就實際業務場景進行驗證,查看是否生效。

 

 

常見問題

1. aar 模式集成後 patch 沒生效

aar 模式集成的時候,須要繼承框架的 QuinoxlessApplication,指定 Application 爲框架的實現類才能實現 dexpatch 的加載。QuinoxlessApplication 內主要封裝了 dexpatch 模塊的初始化和加載。


2. 使用加固後不生效

須要使用加固前的 apk 生成 patch,不能用加固後的包生成 patch。而後還須要驗證在不一樣加固廠商下的兼容表現。


3. 使用熱修復後,和 RPC 有關的調用發生 apache http 相關的 crash。

請使用 Android 官網上的方式引入 apache http client,禁止使用導入 jar 包或者 gradle implementation/compile 的方式導入 http client。不然會引發 classloader 加載類混亂。

建議方式:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>


E · N · D

做者名片-榮陽.jpg


底部banner.png

相關文章
相關標籤/搜索