你期待已久的熱修復—Tinker熱修復集成總結

集成tinker

對於原有app集成tinker,仍是比較簡單的,根據tinker上的wiki的指示操做便可。
具體步驟以下:java

  1. 在項目的build.gradle中添加 tinker-patch-gradle-plugin 的依賴
    buildscript {
    dependencies {
      classpath 'com.tencent.tinker:tinker-patch-gradle-plugin:1.7.9'
    }
    }複製代碼
  2. 而後在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'複製代碼
  3. 還須要配置
    dexOptions {
      jumboMode = true
    }複製代碼
    tinker的最佳實踐,防止因爲字符串增多致使force-jumbol,致使更多的變動
  4. 最後能夠把tinker相關的代碼挪動到tinkerpatch.gradleandroid

  5. 改造SampleApplication,經過SampleApplicationLike代理SampleApplication的行爲。具體能夠看wikiSampleApplication相關的改動能夠參考 TinkerDemogit

加固支持

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

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

            isProtectedApp = true //開啓加固
        }複製代碼

集成patchsdk

patchsdk 使用的是 github.com/baidao/tink…步驟以下api

  1. 須要在app/build.gradle中添加
    repositories {
    jcenter()
    }
    dependencies {
    ...
    compile 'com.dx168.patchsdk:patchsdk:1.1.3'
    }複製代碼
  2. 使用ApplicationLike代理原來的Applicationbash

    @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();
    }
    }複製代碼
  3. 搭建補丁後臺管理系統
    參考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爲例app

  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會被殺死,重啓後補丁纔會生效,這個時候咱們才真正修復了問題。ide

踩過的坑

  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. 還有一些其餘的坑已經記不得了。。。

博客地址:工具

www.jianshu.com/p/194c9d89b…

相信本身,沒有作不到的,只有想不到的

若是你以爲此文對您有所幫助,歡迎入羣 QQ交流羣 :232203809
微信公衆號:終端研發部

技術+職場
技術+職場
相關文章
相關標籤/搜索