微信Tinker的使用-Android熱修復(fù)方案

這類文章已經(jīng)很多了寝衫,寫這個是為了記錄下自己的使用過程和在使用中遇到過的一些問題顷扩。
看過一句話,無論學(xué)習(xí)什么技術(shù)竞端,以官方文檔為主屎即,教程文章為輔。所以認(rèn)真看文檔事富。

Tinker

介紹下Tinker技俐,其實(shí)這些官方文檔都有,寫在這里也就是為了自己再看的時(shí)候方便统台。

Tinker是什么

Tinker是微信官方的Android熱補(bǔ)丁解決方案雕擂,它支持動態(tài)下發(fā)代碼So庫以及資源贱勃,讓應(yīng)用能夠在不需要重新安裝的情況下實(shí)現(xiàn)更新井赌。也可以使用Tinker來更新插件谤逼。
主要包括以下幾個部分:

  • gradle編譯插件:tinker-patch-gradle-plugin
  • 核心sdk庫:tinker-android-lib
  • 非gradle編譯用戶的命令行版本:tinker-patch-cli.jar

與其他方案比較

阿里的AndFix、美團(tuán)的Robust以及QZone的超級補(bǔ)丁方案

Tinker QZone AndFix Robust
類替換 yes yes no no
SO替換 yes no no no
資源替換 yes yes no no
全平臺支持 yes yes yes yes
即時(shí)生效 no no yes yes
性能消耗 較小 較大 較小 較小
補(bǔ)丁包大小 較小 較大 一般 一般
開發(fā)透明 yes yes no no
復(fù)雜度 較低 較低 復(fù)雜 復(fù)雜
gradle支持 yes no no no
ROM體積 較大 較小 較小 較小
成功率 較高 較高 一般 最高
  • AndFix作為native解決方案仇穗,首先面臨的是穩(wěn)定性與兼容性問題流部,更重要的是它無法實(shí)現(xiàn)類替換,它是需要大量額外的開發(fā)成本的纹坐;
  • Robust兼容性與成功率較高枝冀,但是它與AndFix一樣,無法新增變量與類只能用做的bugFix方案耘子;
  • Qzone方案可以做到發(fā)布產(chǎn)品功能果漾,但是它主要問題是插樁帶來Dalvik的性能問題,以及為了解決Art下內(nèi)存地址問題而導(dǎo)致補(bǔ)丁包急速增大的谷誓。

特別是在Android N之后绒障,由于混合編譯的inline策略修改,對于市面上的各種方案都不太容易解決捍歪。而Tinker熱補(bǔ)丁方案不僅支持類户辱、So以及資源的替換,它還是2.X-8.X(1.9.0以上支持8.X)的全平臺支持糙臼。利用Tinker我們不僅可以用做bugfix,甚至可以替代功能的發(fā)布焕妙。

不過這些是Tinker文檔的內(nèi)容,想具體了解其他方案還是到每個的官方文檔進(jìn)行了解AndFix弓摘、Robust

已知問題

  • Tinker不支持修改AndroidManifest.xml痕届,Tinker不支持新增四大組件(1.9.0支持新增非export的Activity)韧献;
  • 由于Google Play的開發(fā)者條款限制,不建議在GP渠道動態(tài)更新代碼研叫;
  • 在Android N上锤窑,補(bǔ)丁對應(yīng)用啟動時(shí)間有輕微的影響;
  • 不支持部分三星android-21機(jī)型嚷炉,加載補(bǔ)丁時(shí)會主動拋出"TinkerRuntimeException:checkDexInstall failed"渊啰;
  • 對于資源替換,不支持修改remoteView申屹。例如transition動畫绘证,notification icon以及桌面圖標(biāo)

開始接入

官方接入文檔

gradle接入

在項(xiàng)目的build.gradle文件中,添加tinker-patch-gradle-plugin的依賴

dependencies{
      classpath "com.tencent.tinker:tinker-patch-gradle-plugin:x.x.x"
}

在app的build.gradle文件中哗讥,添加tinker的庫依賴以及apply tinker的gradle插件.

dependencies{ 
      //可選嚷那,用于生成application類 
      provided('com.tencent.tinker:tinker-android-anno:x.x.x')
      //tinker的核心庫
      compile('com.tencent.tinker:tinker-android-lib:x.x.x') 
}
...
...
//apply tinker插件
apply plugin: 'com.tencent.tinker.patch'

這三個依賴在添加的時(shí)候版本號必須保持一致。

配置gradle中的參數(shù)

我自己在build.gradle中參數(shù)的配置基本是按照demo中build.gradle配置的杆煞,或者也可以查看文檔中的參數(shù)說明魏宽,弄清楚每個參數(shù)代表什么以后腐泻,根據(jù)自己的需求進(jìn)行配置。

修改Application類

這里有兩種方法進(jìn)行修改队询,一種是將自己的Application類繼承TinkerApplication.Java派桩;第二種是使用Annotation來自動生成Application類。官方推薦是使用第二種方式蚌斩,Annotation自動生成Application類铆惑,既然已經(jīng)用了Tinker方案了,就按官方推薦的接入凳寺。文檔中自定義Application類鸭津。

要用Annotation來自動生成Application類的原因是:程序啟動時(shí)會加載默認(rèn)的Application類,這導(dǎo)致補(bǔ)丁包無法對其做修改肠缨。
具體實(shí)現(xiàn):
1逆趋、新建一個自己的ApplicationLike類,讓其繼承DefaultApplicationLike晒奕,并添加相關(guān)注釋

@DefaultLifeCycle(
        application = ".MyApplication",    //application類名
        flag = ShareConstants.TINKER_ENABLE_ALL,   //tinkerFlag
        loaderClass = "com.tencent.tinker.loader.TinkerLoader",   //loaderClassName, 我們這里使用默認(rèn)即可!
        loadVerifyFlag = false
)
public class MyApplicationLike extends DefaultApplicationLike{
      ...
}

2闻书、將原先自己的Application類以及他的繼承類的所有代碼拷貝到新建的自己的ApplicationLike中。
3脑慧、原先Application的attachBaseContext方法實(shí)現(xiàn)要單獨(dú)移到onBaseContextAttached中魄眉。
4、在現(xiàn)在自己的ApplicationLike中闷袒,所有引用到application的地方改成getApplication()坑律。
5、對其他引用原先Application或者它的靜態(tài)對象和方法的地方囊骤,改成引用現(xiàn)在自己的ApplicationLike的靜態(tài)對象和方法晃择。

通過Annotation方式生成Application類,需要將原來自己的Application類刪除也物,其他任何類都不能再引用原來自己的Application類宫屠。

修改好Application以后,在AndroidManifest.xml中滑蚯,修改application的name屬性浪蹂,與MyApplicationLike注釋中寫的保持一致。之后在自己的ApplicationLike中的onBaseContextAttached()方法中告材,通過TinkerInstaller.install()來初始化Tinker坤次。到此為止,Tinker的接入已初步完成斥赋,接下來可以實(shí)現(xiàn)補(bǔ)丁功能浙踢。

實(shí)現(xiàn)補(bǔ)丁功能

將基準(zhǔn)包安裝到手機(jī),修改需要更新的內(nèi)容后灿渴,將基準(zhǔn)包和相應(yīng)文件的路徑填寫在build.gradle中的對應(yīng)位置上洛波,調(diào)用tinkerPatch Task進(jìn)行編譯胰舆,生成補(bǔ)丁包,將補(bǔ)丁包放在手機(jī)的sdcard中蹬挤,用基準(zhǔn)包安裝在手機(jī)上的應(yīng)用加載補(bǔ)丁缚窿,加載成功后重啟,補(bǔ)丁生效焰扳,更新成功倦零。
官方demo使用方法

生成補(bǔ)丁包

在成功接入tinker并且build完成以后,在Android Studio的工程目錄中會生成bakApk文件夾吨悍,路徑對應(yīng)自己在gradle中的設(shè)置扫茅。


image

在bakApk文件夾下的內(nèi)容,就是每次在生成補(bǔ)丁之前育瓜,在gradle中進(jìn)行配置時(shí)所需要的XXX.apk(基準(zhǔn)包)葫隙、XXX_mapping.txt(打開混淆以后才會產(chǎn)生)、XXX_R.txt文件躏仇。

同時(shí)恋脚,會在Android Studio的Gradle工具欄中會生成tinkerPatch Task文件,直接使用task:tinkerPatchVariantName(例如tinkerPatchDebug焰手、tinkerPatchRelease)即可自動根據(jù)Variant選擇相應(yīng)的編譯類型糟描。


圖片.png

圖片.png

在編譯過程中,還幫助我們完成了以下操作:

  • 將TINKER_ID自動插入AndroidManifest的meta項(xiàng)书妻,輸出路徑為build/intermediates/tinker_intermediates/AndroidManifest.xml;

  • 如果minifyEnabled為true即打開混淆船响,將自動將Tinker的proguard規(guī)則添加到proguardFiles中,輸出路徑為build/intermediates/tinker_intermediates/tinker_proguard.pro躲履,這里不需要將它們拷貝到自己的proguard配置文件中;

  • 如果multiDexEnabled為true灿意,將自動生成Tinker需要放在主dex的keep規(guī)則。在tinker 1.7.6版本之前崇呵,你需要手動將生成規(guī)則拷貝到自己的multiDexKeepProguard文件中。例如Sample中的multiDexKeepProguard file("keep_in_main_dex.txt")馅袁。在1.7.6版本之后域慷,這里會通過腳本自動處理,無須手動填寫汗销。

  • 把dexOptions的jumboMode打開犹褒。

在進(jìn)行tinkerPatch Task編譯之前,需要將bakApk文件夾下每個文件路徑填寫在對應(yīng)的位置上弛针。多flavor打包叠骑。

//demo中的配置將相關(guān)屬性寫在一起,方便每次更改
ext {
    //demo中的這個屬性表示是否打開tinkerBuild
    tinkerEnabled = true
    //基準(zhǔn)包apk的位置
    tinkerOldApkPath = "${bakPath}/"
    //打開混淆生成的mapping.txt的路徑
    tinkerApplyMappingPath = "${bakPath}/"
    //R.txt文件的路徑
    tinkerApplyResourcePath = "${bakPath}/"
    //用了flavor以后在這里填寫編譯后的目錄路徑削茁,沒用flavor可以不填
    tinkerBuildFlavorDirectory = "${bakPath}/"
}

填寫完成以后直接使用tinkerPatch Task中相應(yīng)的操作宙枷,即自動編譯最新的安裝包掉房,并與輸入基準(zhǔn)包作差異,得到最終的補(bǔ)丁包慰丛。卓囚,編譯完成后,會在tinkerPatch輸出的目錄build/outputs/tinkerPatch中產(chǎn)生我們需要的文件诅病。

文件名 描述
patch_unsigned.apk 沒有簽名的補(bǔ)丁包
patch_signed.apk 簽名后的補(bǔ)丁包
patch_signed_7zip.apk 簽名后并使用7zip壓縮的補(bǔ)丁包哪亿,也是我們通常使用的補(bǔ)丁包。但正式發(fā)布的時(shí)候贤笆,最好不要以.apk結(jié)尾蝇棉,防止被運(yùn)營商挾持。
log.txt 在編譯補(bǔ)丁包過程的控制臺日志
dex_log.txt 在編譯補(bǔ)丁包過程關(guān)于dex的日志
so_log.txt 在編譯補(bǔ)丁包過程關(guān)于lib的日志
tinker_result 最終在補(bǔ)丁包的內(nèi)容芥永,包括diff的dex篡殷、lib以及assets下面的meta文件
resources_out.zip 最終在手機(jī)上合成的全量資源apk,你可以在這里查看是否有文件遺漏
tempPatchedDexes 在Dalvik與Art平臺恤左,最終在手機(jī)上合成的完整Dex贴唇,我們可以在這里查看dex合成的產(chǎn)物。

官方提示:每次編譯結(jié)束飞袋,我們都應(yīng)該查看相關(guān)日志戳气,清楚最終在補(bǔ)丁包中的文件。尤其是dex的補(bǔ)丁文件巧鸭,即使是1k的dex補(bǔ)丁文件瓶您,也會帶來合成時(shí)的時(shí)間損耗以及合成完整dex文件ROM空間體積這兩部分影響!

加載補(bǔ)丁包

將基準(zhǔn)包安裝到手機(jī)纲仍,再將生成好的patch_signed_7zip.apk補(bǔ)丁包放到手機(jī)的sdcard中呀袱,正式使用時(shí)從服務(wù)器下載補(bǔ)丁包。然后在需要加載補(bǔ)丁包的位置調(diào)用TinkerInstaller.onReceiveUpgradePatch加載對應(yīng)路徑補(bǔ)丁包郑叠。

需要注意:在Tinker的更新使用中夜赵,默認(rèn)在DefaultTinkerResultService會殺掉:patch進(jìn)程,假設(shè)當(dāng)前是補(bǔ)丁升級并且成功了乡革,我們會殺掉當(dāng)前進(jìn)程寇僧,讓補(bǔ)丁包更快的生效(這就是為什么有的人接好Tinker,實(shí)現(xiàn)了更新功能沸版,但是每次加載完補(bǔ)丁會Crash的原因)嘁傀。若是修復(fù)類型的補(bǔ)丁包并且失敗了,我們會卸載補(bǔ)丁包视粮。

擴(kuò)展

Tinker中還有很多可選自定義類细办。可以通過繼承默認(rèn)的類蕾殴,實(shí)現(xiàn)自己感興趣的事件回調(diào)笑撞,比如在上面提到的岛啸,tinker在DefaultTinkerResultService中默認(rèn)在加載補(bǔ)丁成功后殺死當(dāng)前進(jìn)程,這在正式的使用中會很降低用戶體驗(yàn)娃殖,所以我們需要繼承這個類值戳,實(shí)現(xiàn)自己的回調(diào)。具體實(shí)現(xiàn)可以參考官方說明配合demo炉爆。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堕虹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子芬首,更是在濱河造成了極大的恐慌赴捞,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郁稍,死亡現(xiàn)場離奇詭異赦政,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)耀怜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門恢着,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人财破,你說我怎么就攤上這事掰派。” “怎么了左痢?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵靡羡,是天一觀的道長。 經(jīng)常有香客問我俊性,道長略步,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任定页,我火速辦了婚禮趟薄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘典徊。我一直安慰自己杭煎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布宫峦。 她就那樣靜靜地躺著,像睡著了一般玫鸟。 火紅的嫁衣襯著肌膚如雪导绷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天屎飘,我揣著相機(jī)與錄音妥曲,去河邊找鬼贾费。 笑死,一個胖子當(dāng)著我的面吹牛檐盟,可吹牛的內(nèi)容都是我干的褂萧。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼葵萎,長吁一口氣:“原來是場噩夢啊……” “哼导犹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起羡忘,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤谎痢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后卷雕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體节猿,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年漫雕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滨嘱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡浸间,死狀恐怖太雨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情发框,我是刑警寧澤躺彬,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站梅惯,受9級特大地震影響宪拥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铣减,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一她君、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧葫哗,春花似錦缔刹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捺典,卻和暖如春鸟廓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工引谜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牍陌,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓员咽,卻偏偏與公主長得像毒涧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贝室,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容