技術乾貨 | 深度解構 Android 應用面臨緊急發版時的救星方案:mPaaS 熱修復 - DexPatch

方案介紹

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

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

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

基於這樣的原理,DexPatch 具有以下特徵:

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

操作說明

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

1. 觸發 patch 拉取

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

2. 代碼操作演示

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

(1)代碼改動前

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

(2)代碼改動後

重新編譯,保存構建產物,產物地址: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)

(4)查看簽名

生成 patch 需要用到項目的打包祕鑰,需要提前準備好,可以在打包腳步下找到對應的配置

(5)生成 patch

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

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

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

(6)生成 patch 產物

生成 patch 產物如下:

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

反解後可以看到修改的模塊:

(7)上傳發布

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

② 上傳後可以通過白名單進行發佈,驗證 patch 的穩定性

(8)驗證下載

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

然後去下載目錄查看,是否下載保存成功,下載目錄在:/data/user/0/包名/dexpatch/patch/[email protected]

(9)殺進程啓動

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

同時我們也可以就實際業務場景進行驗證,查看是否生效。

常見問題

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"/>

 

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

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