Tinker再探之TinkerPatch 平臺 第一篇

距離上一次學習Tinker熱更新:使用Bugly集成的Tinker已經兩年了,現(xiàn)在復習一下Tinker。
Tinker對比阿里的 AndFix、美團的 Robust 以及 QZone 的超級補丁方案

功能/名稱 Tinker QZone AndFix Robust
類替換 yes yes no no
So替換 yes no no no
資源替換 yes yes no no
全平臺支持 yes yes no yes
即時生效 no no yes yes
性能損耗 較小 較大 較小 較小
補丁包大小 較小 較大 一般 一般
開發(fā)透明 yes yes no no
復雜度 較低 較低 復雜 復雜
gradle支持 yes no no no
Rom體積 Dalvik較大 較小 較小 較小
成功率 較高 較高 一般 最高
  • 看官方提供對比其他第三方熱修復方案,Tinker綜合性能最好。只有及時生效,Rom體積有劣勢。成功率不是最高的。及時生效就是用戶不用重啟應用就會生效,個人覺得一般用戶對于應用都會開關很多次,所以這項可以忽略。而Rom體積比較大,用戶也感知不出來,所以也可以忽略。要是成功率比Robust,就更完美了。

  • 同時,由于原理與系統(tǒng)限制,Tinker有以下已知問題:

    • 1.Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大組件(1.9.0支持新增非export的Activity);
    • 2.由于Google Play的開發(fā)者條款限制,不建議在GP渠道動態(tài)更新代碼;
    • 3.在Android N上,補丁對應用啟動時間有輕微的影響;
    • 4.不支持部分三星android-21機型,加載補丁時會主動拋出"TinkerRuntimeException:checkDexInstall failed";
    • 5.對于資源替換,不支持修改remoteView。例如transition動畫,notification icon以及桌面圖標。

那么什么是TinkerPatch呢?

Tinker 需要使用者有一個后臺可以下發(fā)和管理補丁包,并且需要處理傳輸安全等部署工作,TinkerPatch 平臺幫你做了這些工作,提供了補丁后臺托管,版本管理,保證傳輸安全等功能,讓你無需搭建一個后臺,無需關心部署操作,只需引入一個 SDK 即可立即使用 Tinker。

此外,通過深入研究 Tinker 源碼,TinkerTinkerPatch 平臺在 Tinker的基礎上加入了以下特性:

  1. 一鍵傻瓜式接入;無需理解復雜的熱修復原理,一行代碼即可接入熱修復。實現(xiàn)了自動反射 Appliction 與 Library,使用者無需對自己的項目做任何的改動;
  2. 補丁管理;實現(xiàn)了熱補丁的版本管理,補丁的自動重試與異常時自動回退等功能。同時我們可以簡單實現(xiàn)條件下發(fā)補丁,在出現(xiàn)異常情況時,我們也可以快速回滾補??;
  3. 編譯優(yōu)化;簡化了 Tinker 的編譯復雜度,實現(xiàn)了備份路徑選擇,功能開關等功能。

TinkerPatch 平臺在 Github 為大家提供了各種各樣的 Sample,大家可點擊前往 [TinkerPatch Github].

為什么使用 TinkerPatch 平臺?

市面上可能還有其他的一些熱補丁服務,為什么我們需要選擇 TinkerPatch 平臺呢?

  1. 研發(fā)實力雄厚;Tinker 在微信的數(shù)億用戶上得到驗證,它的穩(wěn)定性與性能值得信賴。TinkerPatch 平臺作為 Tinker 項目貢獻者與管理者之一,在 Tinker 基礎上開發(fā)了許多方便使用者的特性;
  2. 服務全面快速;TinkerPatch 平臺客戶關于熱修復使用過程的所有問題在工作日內一個小時內響應,提供您滿意的服務;
  3. 穩(wěn)定可靠;TinkerPatch 平臺上傳的補丁文件都會保存在七牛云存儲上,客戶端 APP 只跟七牛服務器通訊,支持高并發(fā),CDN分布全國,速度和穩(wěn)定性有保證。

TinkerPatch 平臺將與 Tinker 一起繼續(xù)優(yōu)化,四大組件代理/ABTest/安全模式等功能都將陸續(xù)推出,歡迎大家咨詢。

第一步 添加 gradle 插件依賴 - 在Project的build.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // TinkerPatch 插件
        classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.2.13"
    }
}

第二步 集成 TinkerPatch SDK

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    //若使用annotation需要單獨引用,對于tinker的其他庫都無需再引用
    annotationProcessor("com.tinkerpatch.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true }
    compileOnly("com.tinkerpatch.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true }
    implementation("com.tinkerpatch.sdk:tinkerpatch-android-sdk:${TINKERPATCH_VERSION}") { changing = true }
}
apply from: 'tinkerpatch.gradle'
  • gradle.properties
TINKER_VERSION=1.9.2
TINKERPATCH_VERSION=1.2.2

第三步 配置 tinkerpatchSupport 參數(shù)

在Module的build.gradle同級目錄下創(chuàng)建tinkerpatch.gradle:

apply plugin: 'tinkerpatch-support'

/**
 * TODO: 請按自己的需求修改為適應自己工程的參數(shù)
 */
def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-1.0.0-1112-12-49-34"
def variantName = "debug"

/**
 * 對于插件各參數(shù)的詳細解析請參考
 * http://tinkerpatch.com/Docs/SDK
 */
tinkerpatchSupport {
    /** 可以在debug的時候關閉 tinkerPatch **/
    /** 當disable tinker的時候需要添加multiDexKeepProguard和proguardFiles,
        這些配置文件本身由tinkerPatch的插件自動添加,當你disable后需要手動添加
        你可以copy本示例中的proguardRules.pro和tinkerMultidexKeep.pro,
        需要你手動修改'tinker.sample.android.app'本示例的包名為你自己的包名, com.xxx前綴的包名不用修改
     **/
    tinkerEnable = true
    reflectApplication = false
    /**
     * 是否開啟加固模式,只能在APK將要進行加固時使用,否則會patch失敗。
     * 如果只在某個渠道使用了加固,可使用多flavors配置
     **/
    protectedApp = false
    /**
     * 實驗功能
     * 補丁是否支持新增 Activity (新增Activity的exported屬性必須為false)
     **/
    supportComponent = true

    autoBackupApkPath = "${bakPath}"

    appKey = "f938475486f91936"

    /** 注意: 若發(fā)布新的全量包, appVersion一定要更新 **/
    appVersion = "1.0.0"

    def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"
    def name = "${project.name}-${variantName}"

    baseApkFile = "${pathPrefix}/${name}.apk"
    baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
    baseResourceRFile = "${pathPrefix}/${name}-R.txt"

    /**
     *  若有編譯多flavors需求, 可以參照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample
     *  注意: 除非你不同的flavor代碼是不一樣的,不然建議采用zip comment或者文件方式生成渠道信息(相關工具:walle 或者 packer-ng)
     **/
}

/**
 * 用于用戶在代碼中判斷tinkerPatch是否被使能
 */
android {
    defaultConfig {
        buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
    }
}

/**
 * 一般來說,我們無需對下面的參數(shù)做任何的修改
 * 對于各參數(shù)的詳細介紹請參考:
 * https://github.com/Tencent/tinker/wiki/Tinker-接入指南
 */
tinkerPatch {
    ignoreWarning = false
    useSign = true
    dex {
        dexMode = "jar"
        pattern = ["classes*.dex"]
        loader = []
    }
    lib {
        pattern = ["lib/*/*.so"]
    }

    res {
        pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
        ignoreChange = []
        largeModSize = 100
    }

    packageConfig {
    }
    sevenZip {
        zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
//        path = "/usr/local/bin/7za"
    }
    buildConfig {
        keepDexApply = false
    }
}

同步后,出現(xiàn)錯誤一:


方法過時,使用新方法

說明Tinker庫有的方法過時了,我們可以不理會,或者回退gradle到3.2.1,等Tinker更新這些過時的方法。

tinkerpatch.gradle中我們只需要更改appKey和對應的打包名稱baseInfo。其他的一般不需要更改,但有的確實需要更改的,可以參考gradle參數(shù)配置詳解

第四步 初始化 TinkerPatch SDK

    1. tinkerpatch.gradle中配置參數(shù)為reflectApplication = true的情況
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 我們可以從這里獲得Tinker加載過程的信息
       ApplicationLike tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
        // 初始化TinkerPatch SDK, 更多配置可參照API章節(jié)中的,初始化SDK
        TinkerPatch.init(tinkerApplicationLike)
                .reflectPatchLibrary()
                .setPatchRollbackOnScreenOff(true)
                .setPatchRestartOnSrceenOff(true)
                .setFetchPatchIntervalByHours(3);

        // 每隔3個小時(通過setFetchPatchIntervalByHours設置)去訪問后臺時候有更新,通過handler實現(xiàn)輪訓的效果
        TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
    }
}

第五步 使用步驟

  • 1.運行 assembleRelease 構建基準包(請在發(fā)布前確保更新tinkerpatch.gradle中的appVersion),tinkerPatch會基于你填入的autoBackupApkPath自動備份基礎包信息到相應的文件夾,包含:apk文件、R.txt文件和mapping.txt文件 (注:mapping.txt是proguard的產物,如果你沒有開啟proguard則不會有這個文件)
    雙擊assembleRelease命令打包

    文件夾名稱相當于版本名稱appVersion
  • 2.若想發(fā)布補丁包, 只需將自動保存下來的文件分別填到tinkerpatch.gradle中的baseApkFile、baseProguardMappingFile和baseResourceRFile 參數(shù)中;
  • 3.運行 tinkerPatchRelease task 構建補丁包,補丁包將位于 build/outputs/tinkerPatch下。


    image.png

    image.png

配置差不多完成了,那么配置中的appkey和如何發(fā)布可以參考:平臺使用說明

運行項目:

  • 錯誤一:applicationLike must not be null.

原因:是因為配置的tinkerpatch.gradle中的reflectApplication = flase,改為reflectApplication = true

  • 錯誤二:> old apk F:\project\MLVBSDK-master\Android\TinkerPatchDemo\app\build\bakApk/app-1.0.0-0715-15-35-51/release//app-release.apk is not exist, you must set the correct old apk value!

原因:是因為配置的tinkerpatch.gradle中的baseInfo不正確,改為def baseInfo = app-1.0.0-0715-16-20-04,也就是打的基準包的文件名稱

image.png

  • 錯誤三 we build app apk with apply resource mapping file F:\project\MLVBSDK-master\Android\TinkerPatchDemo\app\build\bakApk/app-1.0.0-0715-16-20-04/release//app-release-R.txt
    原因:原來是我們mapping.txt是proguard的產物,如果你沒有開啟proguard則不會有這個文件,所以我們注釋調映射一行

  • 錯誤四 can't the get signConfig for this build
    原因:沒有配置簽名文件,那么配置簽名文件吧

    配置簽名

  • 錯誤五:Execution failed for task ':app:tinkerProcessReleaseResourceId'. java.io.FileNotFoundException: F:\project\MLVBSDK-master\Android\TinkerPatchDemo\app\build\intermediates\tinker_intermediates\values_backup
    原因:說是values_backup沒找到,解決方案一

經過5連跪,終于出現(xiàn)了官方說的第三步,運行 tinkerPatchRelease task 構建補丁包。所謂的補丁包對應的文件夾。補丁包將位于 build/outputs/tinkerPatch下:

tinkerPatch

我估計patch_signed.apk應該就是補丁包,去TinkerPatch后臺把這個包以開發(fā)預覽的方式發(fā)布上去
開發(fā)預覽

  • 實驗一:重啟一下應用,沒有反應。界面還是只有一個Hello World!,哦,忘記說了,我修改的內容其實就是在布局文件中加了一段話-- 我是補丁包1.0.
  • 實驗二:哦,記得要官方下載的DebugTool工具的開關,才能用開發(fā)預覽模式,打開了,還是無效。


    打開開發(fā)模式
  • 實驗三:哦,突然想起Application中默認設置的3小時更新補丁,改為立即拉取補丁
 TinkerPatch.with().fetchPatchUpdate(true);
  • 實驗四:重啟N次,依然無反應,后臺去看說是下載補丁包失敗,日志中看說是簽名不對,這個時候才想起自己是debug包,而打的基礎包和補丁包是針對relase包的,所以把這個基礎包app-relase.apk傳到手機上進行安裝,安裝后打開第一次還是Hello World~!重啟后生效。

經過4連跪,重啟應用,總算多了幾個字:我是補丁包1.0

我是補丁包1.0

后臺看看,確實成功下發(fā)了:


實時監(jiān)控

沒錯,這就是Tinker的精髓,不重新下載apk,即可實現(xiàn)修改文字的效果。

下一篇Tinker再探之TinkerPatch 平臺 第二篇我們將學習1.在線參數(shù)獲取,2.實時監(jiān)控,3.圖片補丁,4.新增Activity的相關功能

文檔參考:TinkerPatch 平臺介紹
Demo參考:TinkerPatch相關Demo

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容