什么是熱修復(fù)
熱修復(fù)(也稱(chēng)熱補(bǔ)丁、熱修復(fù)補(bǔ)丁,英語(yǔ):hotfix)是一種包含信息的獨(dú)立的累積更新包,通常表現(xiàn)為一個(gè)或多個(gè)文件。這被用來(lái)解決軟件產(chǎn)品的問(wèn)題(例如一個(gè)程序錯(cuò)誤)。通常情況下,熱修復(fù)是為解決特定用戶的具體問(wèn)題而制作。
正常開(kāi)發(fā)流程

熱修復(fù)開(kāi)發(fā)流程

熱修復(fù)優(yōu)勢(shì)

修復(fù)什么

熱修復(fù)框架的對(duì)比
按公司團(tuán)隊(duì)劃分:
| 類(lèi)別 | 成果 |
|---|---|
| 阿里系 | AndFix、Dexposed、阿里百川HotFix(未開(kāi)源)、Sophix(未開(kāi)源) |
| 騰訊系 | 微信的Tinker、QQ空間的超級(jí)補(bǔ)丁(未開(kāi)源)、手機(jī)QQ的QFix |
| 知名公司 | 美團(tuán)的Robust、餓了么的Amigo、美麗說(shuō)蘑菇街的Aceso |
| 其他 | 百度金融的RocooFix、大眾點(diǎn)評(píng)的Nuwa、AnoleFix |
可見(jiàn),熱修復(fù)框架很多,但核心技術(shù)只有三類(lèi):代碼修復(fù)、資源修復(fù)和動(dòng)態(tài)鏈接庫(kù)修復(fù),其中每個(gè)核心技術(shù)又有很多不同的技術(shù)方案,每個(gè)技術(shù)方案又有不同的實(shí)現(xiàn),另外這些熱修復(fù)框架仍在不斷的更新迭代中,由此可見(jiàn),熱修復(fù)框架的技術(shù)實(shí)現(xiàn)是繁多可變的。
比較出名的修復(fù)框架的對(duì)比如下:
| 特性 | AndFix | Tinker | QQ空間 | Robust |
|---|---|---|---|---|
| 即時(shí)生效 | 是 | 否 | 否 | 是 |
| 方法替換 | 是 | 是 | 是 | 是 |
| 類(lèi)替換 | 否 | 是 | 是 | 否 |
| 類(lèi)結(jié)構(gòu)修改 | 否 | 是 | 否 | 否 |
| 資源替換 | 否 | 是 | 是 | 否 |
| so替換 | 否 | 是 | 否 | 否 |
| 支持gradle | 否 | 是 | 否 | 否 |
| 支持ART | 是 | 是 | 是 | 是 |
| 性能損耗 | 較小 | 較小 | 較小 | 較小 |
| 補(bǔ)丁包大小 | 一般 | 較小 | 較大 | 一般 |
| 復(fù)雜度 | 復(fù)雜 | 較低 | 較低 | 復(fù)雜 |
| 成功率 | 一般 | 較高 | 較高 | 最高 |
| 支持 Android 版本 | 2.3-7.0 | 2.x-8.x | 2.x-7.x | 2.3-9.x |
從上表中,我們可以發(fā)現(xiàn)每個(gè)熱修復(fù)框架各有優(yōu)缺點(diǎn),其中美團(tuán)的Robust支持的 Android 版本可達(dá)到9.x,且支持方法級(jí)別的修復(fù),包括靜態(tài)方法,也支持增加方法和類(lèi),所以此次著重講解美團(tuán)的Robust的部分原理和使用。
美團(tuán)Robust -- Instant Run 熱插拔原理
原理
- Robust插件對(duì)每個(gè)產(chǎn)品代碼的每個(gè)函數(shù)都在編譯打包階段自動(dòng)的插入了一段代碼,插入過(guò)程對(duì)業(yè)務(wù)開(kāi)發(fā)是完全透明
- 編譯打包階段自動(dòng)為每個(gè)class都增加了一個(gè)類(lèi)型為ChangeQuickRedirect的靜態(tài)成員,而在每個(gè)方法前都插入了使用changeQuickRedirect相關(guān)的邏輯,當(dāng) changeQuickRedirect不為null時(shí),可能會(huì)執(zhí)行到accessDispatch從而替換掉之前老的邏輯,達(dá)到fix的目的。

優(yōu)點(diǎn)
- 支持Android2.3-9.x版本
- 高兼容性、高穩(wěn)定性,修復(fù)成功率高達(dá)99.9%
- 補(bǔ)丁實(shí)時(shí)生效,不需要重新啟動(dòng)
- 支持方法級(jí)別的修復(fù),包括靜態(tài)方法
- 支持增加方法和類(lèi)
- 支持ProGuard的混淆、內(nèi)聯(lián)、優(yōu)化等操作
缺點(diǎn)
- 代碼是侵入式的,會(huì)在原有的類(lèi)中加入相關(guān)代碼
- 會(huì)增大apk的體積,平均一個(gè)函數(shù)會(huì)比原來(lái)增加17.47個(gè)字節(jié),10萬(wàn)個(gè)函數(shù)會(huì)增加1.67M
- 會(huì)增加少量方法數(shù)
實(shí)戰(zhàn)
新建項(xiàng)目并導(dǎo)入相應(yīng)的包
- 在 App 的 build.gradle,加入如下依賴
apply plugin: 'com.android.application'
//制作補(bǔ)丁時(shí)將這個(gè)打開(kāi),auto-patch-plugin緊跟著com.android.application
//apply plugin: 'auto-patch-plugin'
apply plugin: 'robust'
compile 'com.meituan.robust:robust:0.4.90'
- 在整個(gè)項(xiàng)目的build.gradle加入classpath
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.meituan.robust:gradle-plugin:0.4.90'
classpath 'com.meituan.robust:auto-patch-plugin:0.4.90'
}
}
注:要開(kāi)啟資源壓縮,開(kāi)啟混淆,后面需要 mapping.txt 文件。
- 開(kāi)啟資源壓縮,開(kāi)啟混淆
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
//為方便調(diào)試,debug也開(kāi)啟
debug {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
創(chuàng)建相應(yīng)文件夾及 robust.xml 文件
最終文件大概圖:

- robust 文件夾:存放 methodsMap.robust[build/outputs/robust/methodsMap.robust] 和 mapping.txt[build/outputs/mapping/mapping.txt] 文件;
- robust.xml 文件:一些配置信息,一般直接從官方網(wǎng)站上 copy 一份即可。
如何生成補(bǔ)丁
- 將打出的正式包的 methodsMap.robust 和 mapping.txt 文件存放到 robust 文件夾中,如下:

- 將 App 的 build.gradle 中 auto-patch-plugin 注釋打開(kāi),如下:
apply plugin: 'com.android.application'
//制作補(bǔ)丁時(shí)將這個(gè)打開(kāi),auto-patch-plugin緊跟著com.android.application
apply plugin: 'auto-patch-plugin'
//apply plugin: 'robust'
- 修改需要修改或增加的文件,添加相關(guān)注釋(@Modify / @Add);
- 像正常打包一樣打包,會(huì)出現(xiàn)如下提示:

- 生成的補(bǔ)丁包在 app/build/outputs/robust/patch.jar 位置,如下:

注:生成正式包與補(bǔ)丁,都需要秘鑰。
補(bǔ)丁包的引入
- 可手動(dòng)復(fù)制進(jìn)相應(yīng)的目錄;
- 可通過(guò) adb 導(dǎo)入相應(yīng)的目錄;
- 可下載補(bǔ)丁包至指定的目錄。
目前筆者采用的是下載補(bǔ)丁包至指定目錄,放置位置可自由設(shè)定,筆者設(shè)置的目錄為:/storage/emulated/0/robust/patch/
注意點(diǎn)
- 需要開(kāi)啟資源壓縮,開(kāi)啟混淆;
- 打正式包或補(bǔ)丁,需要秘鑰;
- 打補(bǔ)丁需要之前打正式包的 methodsMap.robust 和 mapping.txt 文件;
- robust.xml 中需要在 hotfixPackage 中設(shè)置自己的包名;
- 調(diào)試的時(shí)候,debug需要開(kāi)啟資源壓縮和混淆。