Tinker熱修復集成總結

集成tinker

對于原有app集成tinker,還是比較簡單的,根據tinker上的wiki的指示操作即可。
具體步驟如下:

  1. 在項目的build.gradle中添加 tinker-patch-gradle-plugin 的依賴
buildscript {
    dependencies {
        classpath 'com.tencent.tinker:tinker-patch-gradle-plugin:1.7.9'
    }
}
  1. 然后在app的gradle文件app/build.gradle,我們需要添加tinker的庫依賴以及apply tinker的gradle插件.
dependencies {
    //可選,用于生成application類 
    provided 'com.tencent.tinker:tinker-android-anno:1.7.9'
    //tinker的核心庫
    compile 'com.tencent.tinker:tinker-android-lib:1.7.9'
}
...
...
//apply tinker插件
apply plugin: 'com.tencent.tinker.patch'
  1. 還需要配置
dexOptions {
        jumboMode = true
    }

tinker的最佳實踐,防止由于字符串增多導致force-jumbol,導致更多的變更

  1. 最后可以把tinker相關的代碼挪動到tinkerpatch.gradle
  2. 改造SampleApplication,通過SampleApplicationLike代理SampleApplication的行為。具體可以看wikiSampleApplication
    相關的改動可以參考 TinkerDemo

加固支持

從1.7.8開始,tinker又支持加固了,只需要修改tinkerpatch.gradle中的這部分

buildConfig {
            applyMapping = getApplyMappingPath()
            applyResourceMapping = getApplyResourceMappingPath()
            tinkerId = getTinkerIdValue()
            keepDexApply = false

            isProtectedApp = true //開啟加固
        }

集成patchsdk

patchsdk 使用的是 https://github.com/baidao/tinker-manager/tree/master/patchsdk
步驟如下

  1. 需要在app/build.gradle中添加
repositories {
    jcenter()
}
dependencies {
    ...
    compile 'com.dx168.patchsdk:patchsdk:1.1.3'
}
  1. 使用ApplicationLike代理原來的Application
@SuppressWarnings("unused")
@DefaultLifeCycle(application = "com.dx168.patchsdk.sample.MyApplication",
        flags = ShareConstants.TINKER_ENABLE_ALL,
        loadVerifyFlag = false)
public class MyApplicationLike extends TinkerApplicationLike {
    public MyApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
        super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        String appId = "20170112162040035-6936";
        String appSecret = "d978d00c0c1344959afa9d0a39d7dab3";
        PatchManager.getInstance().init(getApplication(), "http://xxx.xxx.xxx/hotfix-apis/", appId, appSecret, new ActualPatchManager() {
            @Override
            public void cleanPatch(Context context) {
                TinkerInstaller.cleanPatch(context);
            }

            @Override
            public void patch(Context context, String patchPath) {
                TinkerInstaller.onReceiveUpgradePatch(context, patchPath);
            }
        });
        PatchManager.getInstance().register(new Listener() {
            ...
        });
        PatchManager.getInstance().setTag("your tag");
        PatchManager.getInstance().setChannel("");
        PatchManager.getInstance().queryAndPatch();
     }
}
  1. 搭建補丁后臺管理系統
    參考Readme 搭建補丁后臺,不過這個后臺沒有push下發補丁的功能,只有后臺下發后,客戶端pull拉取補丁,進行補丁修復操作
    如果你的app用的是bugly來作為異常上報和運營統計,那么可以直接使用bugly提供的后臺,具體操作請參考這里, 小巫同學錄制了一系列相關的視頻,參考視頻教程即可學會,地址在這里 ,bugly支持push下發,比自己搭建后臺更加有優勢,同樣,也可以使用TinkerPatch補丁管理后臺,不過是收費的。

生成渠道包

對于渠道包,如果不是需要使用熱修復,那么怎么生成渠道包都可以的。
對于flavor編譯渠道包,會導致不同的渠道包由于BuildConfig變化導致classes.dex差異,這種方案是不可取的。
將渠道信息寫在apk文件的zip comment中,是非常推薦的,例如可以使用項目packer-ng-plugin或者可使用V2 Scheme的walle, 也包括最新出來的多渠道打包神器ApkChannelPackage,說一下區別,如果要使用熱修復的話,對于不需要加固的app,那么生成渠道包,這三種方案都可以采用;對于要加固的app,只能采用ApkChannelPackage這種方案中的根據已有APK生成渠道包(如果有其他的方案,請記得告訴我)。這篇文章對多渠道打包工具對比做了詳細的區分。目前采用的也是ApkChannelPackage方案。

生成補丁

以TinkerDemo為例

  1. 執行./gradlew assembleRelease 生成apk
  2. 使用梆梆加固工具加固apk,并簽名,得到加固并且重簽名的app_protected_signed.apk
  3. 使用./gradlew reBuildChannel 生成渠道包
  4. 修改TinkerDemo中的若干代碼
  5. ./gradlew tinkerPatchRelease 生成patch補丁apk(需要保證補丁包tinkerId跟基線版本tinkerId一致)(也就是說,打補丁的時候不要commit代碼,tinkerId是根據git commit生成的)
  6. 如果搭建了補丁管理后臺的話,使用后臺上傳補丁包,進行修復,根據log,可以觀察到結果
  7. 如果沒有搭建補丁管理后臺的話,使用adb push app/build/outputs/tinkerPatch/release/patch_signed_7zip.apk /storage/sdcard0/(參考tinker的sample工程,以及tinker接入文檔

測試補丁包

根據生成補丁的若干步驟,來測試補丁包是否有效,在第三步生成渠道包后,安裝其中的一個渠道apk到手機上,然后呢,我這邊是通過補丁管理后臺上傳的補丁,然后客戶端pull補丁,根據log,可以清晰的看到補丁是否下載完成,是否有效。下載完補丁后,會進行dex合成。然后在后臺或者屏幕關閉后app會被殺死,重啟后補丁才會生效,這個時候我們才真正修復了問題。

踩過的坑

  1. gradle打release包需要開啟簽名(./gradlew assembleRelease),不然的話,打patch包的時候,提示出錯(./gradlew tinkerPatchRelease)
  2. 打補丁包的時候,得保證基線版本是上一次發版本的apk,而且如果用的是tinker的默認形式的話,tinkerId得跟上一次發版本的apk的tinkerId一致,也就是基于上一次發版本的tag開bugfix分支,但是記得不要commit代碼,這樣就保證了tinkerId一致(可以考慮是用app的版本號VERSION_NAME來作為tinkerId,每一次的發版,肯定是會修改版本號的),如果是bugly集成的tinker,請參考bugly官方文檔
  3. 加固包跟渠道包如何相容的問題,一開始不太懂,如果有加固的需求如何做?。 我們需要搞明白的是,加固包不是基線版本,使用tinker打補丁包,用的是基線版本,得到基線版本后,我們會選擇梆梆加固,樂固,愛加密這樣的平臺對基線版本進行加固,得到加固包后,還需要注意的是,不能夠用普通的渠道包生成方案來打渠道包。舉例來說吧,我司的app,采用的是梆梆加固,加固后,工具自動幫你做了生成渠道包的操作,但是這種生成的渠道包實際上是有問題的,會導致無法打補丁,無法修復,tinker熱修復不生效。這種生成的渠道包,不同渠道對應的dex的CRC都不一樣,我們得保證打出來的渠道包的dex都是一樣的,通過apksigner可以知道梆梆加固的簽名工具采用的是v1簽名方案,那么我們可以考慮在APK文件的注釋字段,添加渠道信息。這樣就能保證不同渠道的dex是一致的。
  4. ApkChannelPackage 存在一點小問題,還需要作者修復,v1簽名的判斷邏輯有問題,加固后的apk,會改變META-INF/XXX.SF的名稱,這塊需要修改,不然./gradle reBuildChannel執行后,無法生成渠道包,對于開發者而言可以自己搭建本地localMaven,來測試修改這個repo 作者已經修復若干問題
  5. 還有一些其他的坑已經記不得了。。。

參考資料

Tinker常見問題
Android新一代多渠道打包神器
微信tinker補丁管理
TinkerDemo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容