天天看點

tinker-platform熱更新及android studio配置                                    tinker-platform使用簡書二.項目的編譯

                                    tinker-platform使用簡書

1.sdk下載下傳。

2.第一步 添加 gradle 插件依賴

gradle 遠端倉庫依賴 jcenter, 例如 TinkerPatch Sample 中的 build.gradle.

buildscript {

    repositories {

        jcenter()

    }

    dependencies {

        // TinkerPatch 插件

        classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.2.9"

    }

}

注意,在這裡 SDK 使用了 fat 打包的模式,我們不能再引入任何 Tinker 的相關依賴,否則會造成版本沖突。

3.內建 TinkerPatch SDK

添加 TinkerPatch SDK 庫的 denpendencies 依賴, 可參考 Sample 中的 app/build.gradle:

dependencies {

    // 若使用annotation需要單獨引用,對于tinker的其他庫都無需再引用

    provided("com.tinkerpatch.tinker:tinker-android-anno:1.9.9")

    compile("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.2.9")

}

注意,若使用 annotation 自動生成 Application, 需要單獨引入 Tinker 的 tinker-android-anno 庫。除此之外,我們無需再單獨引入 tinker 的其他庫。

為了簡單友善,我們将 TinkerPatch 相關的配置都放于 tinkerpatch.gradle 中, 我們需要将其引入:

apply from: 'tinkerpatch.gradle'

4.配置 tinkerpatchSupport 參數

打開引入的 tinkerpatch.gradle 檔案,它的具體參數如下:

tinkerpatchSupport {

    tinkerEnable = true

    reflectApplication = true

    protectedApp = false

    supportComponent = false

    autoBackupApkPath = "${bakPath}"

    appKey = "yourAppKey"

    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"

}

參數說明:

參數 預設值 描述
tinkerEnable true 是否開啟 tinkerpatchSupport 插件功能。
appKey "" 在 TinkerPatch 平台 申請的 appkey, 例如 sample 中的 'f828475486f91936'
appVersion "" 在 TinkerPatch 平台 輸入的版本号, 例如 sample 中的 '1.0.0'。 注意,我們使用 appVersion 作為 TinkerId, 我們需要保證每個釋出出去的基礎安裝包的 appVersion 都不一樣。
reflectApplication false 是否反射 Application 實作一鍵接入;一般來說,接入 Tinker 我們需要改造我們的 Application, 若這裡為 true, 即我們無需對應用做任何改造即可接入。
autoBackupApkPath "" 将每次編譯産生的 apk/mapping.txt/R.txt 歸檔存儲的位置
baseApkFile "" 基準包的檔案路徑, 對應 tinker 插件中的 oldApk 參數;編譯更新檔包時,必需指定基準版本的 apk,預設值為空,則表示不是進行更新檔包的編譯。
baseProguardMappingFile "" 基準包的 Proguard mapping.txt 檔案路徑, 對應 tinker 插件 applyMapping 參數;在編譯新的 apk 時候,我們希望通過保持基準 apk 的 proguard 混淆方式,進而減少更新檔包的大小。這是強烈推薦的,編譯更新檔包時,我們推薦輸入基準 apk 生成的 mapping.txt 檔案。
baseResourceRFile "" 基準包的資源 R.txt 檔案路徑, 對應 tinker 插件 applyResourceMapping 參數;在編譯新的apk時候,我們希望通基準 apk 的 R.txt 檔案來保持 Resource Id 的配置設定,這樣不僅可以減少更新檔包的大小,同時也避免由于 Resource Id 改變導緻 remote view 異常。
protectedApp false 是否開啟支援加強,注意:隻有在使用加強時才能開啟此開關
supportComponent false 是否開啟支援在更新檔包中動态增加Activity 注意:新增Activity的Exported屬性必須為false
backupFileNameFormat '${appName}-${variantName}' 格式化命名備份檔案 這裡請使用單引号

一般來說,我們無需修改引用 android 的編譯配置,也不用修改 tinker 插件原來的配置。針對特殊需求,具體的參數含義可參考 Tinker 文檔:Tinker 接入指南.

5.初始化 TinkerPatch SDK

最後在我們的代碼中,隻需簡單的初始化 TinkerPatch 的 SDK 即可,我們無需考慮 Tinker 是如何下載下傳/合成/應用更新檔包, 也無需引入各種各樣 Tinker 的相關類。

1. reflectApplication = true 的情況

若我們使用 reflectApplication 模式,我們無需為接入 Tinker 而改造我們的 Application 類。初始化 SDK 可參考 tinkerpatch-easy-sample 中的 SampleApplication 類.

public class SampleApplication extends Application {

    ...

    @Override

    public void onCreate() {

        super.onCreate();

        // 我們可以從這裡獲得Tinker加載過程的資訊

        tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();

        // 初始化TinkerPatch SDK, 更多配置可參照API章節中的,初始化SDK

        TinkerPatch.init(tinkerApplicationLike)

            .reflectPatchLibrary()

            .setPatchRollbackOnScreenOff(true)

            .setPatchRestartOnSrceenOff(true)

            .setFetchPatchIntervalByHours(3);

        // 每隔3個小時(通過setFetchPatchIntervalByHours設定)去通路背景時候有更新,通過handler實作輪訓的效果

        TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();

    }

    ...

我們将 Tinker 加載更新檔過程的結果存放在 TinkerPatchApplicationLike 中。

2. reflectApplication = false 的情況

若我們已經完成了應用的 Application 改造,即将 Application 的邏輯移動到 ApplicationLike類中。我們可以參考 tinkerpatch-sample 中的 SampleApplicationLike 類.

public class SampleApplicationLike extends DefaultApplicationLike {

    ...

    @Override

    public void onCreate() {

        super.onCreate();

        // 初始化TinkerPatch SDK, 更多配置可參照API章節中的,初始化 SDK

        TinkerPatch.init(this)

            .reflectPatchLibrary()

            .setPatchRollbackOnScreenOff(true)

            .setPatchRestartOnSrceenOff(true)

            .setFetchPatchIntervalByHours(3);

        // 每隔3個小時(通過setFetchPatchIntervalByHours設定)去通路背景時候有更新,通過handler實作輪訓的效果

        TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();

    }

    ...

}

注意:初始化的代碼建議緊跟 super.onCreate(),并且所有程序都需要初始化,已達到所有程序都可以被 patch 的目的

如果你确定隻想在主程序中初始化 tinkerPatch,那也請至少在 :patch 程序中初始化,否則會有造成 :patch 程序crash,無法使更新檔生效

6.使用步驟

TinkerPatch 的使用步驟非常簡單,一般來說可以參考以下幾個步驟:

  1. 運作 assembleRelease task 建構基準包(請在釋出前確定更新tinkerpatchSupport中的appVersion),tinkerPatch會基于你填入的autoBackupApkPath自動備份基礎包資訊到相應的檔案夾,包含:apk檔案、R.txt檔案和mapping.txt檔案 (注:mapping.txt是proguard的産物,如果你沒有開啟proguard則不會有這個檔案)
  2. 若想釋出更新檔包, 隻需将自動儲存下來的檔案分别填到tinkerpatchSupport中的baseApkFile、baseProguardMappingFile和baseResourceRFile 參數中;
  3. 運作 tinkerPatchRelease task 建構更新檔包,更新檔包将位于 build/outputs/tinkerPatch下。

其他

1. 對Flavors的支援

在TinkerPatchSupport中添加如下字段, 如果你隻是多管道的需求,建議不要使用Flavor。多flavor必須在背景建立相應的基線工程(如下例子的命名規則為:appVersion_flavorName),每次生成更新檔時也必須對應的生成多個分别上傳。

這裡增加了tinkerPatchAllFlavorsDebug 和 tinkerPatchAllFlavorsRelease 用于一次性生成所有flavors的Patch包。

具體可以參照tinkerpatch-flavors-sample。

如果隻是多管道的需求,建議不要使用flavor的方式。首先其打包很慢,其次需要維護多個基線包,後期維護成本也很大。Tinker官方推薦 [packer-ng-plugin](https://github.com/mcxiaoke/packer-ng-plugin )或者 walle 來進行多管道打包,其中walle是支援最新的SchemaV2簽名的。

productFlavors { flavor { flavorName = "flavor1" // 背景需要按照每個flavor的appVersion來建立獨立的工程,并單獨下發更新檔 appVersion = "${tinkerpatchSupport.appVersion}_${flavorName}" pathPrefix = "${bakPath}/${baseInfo}/${flavorName}${buildType}/" name = "${project.name}-${flavorName}${buildType}" baseApkFile = "${pathPrefix}/${name}.apk" baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt" baseResourceRFile = "${pathPrefix}/${name}-R.txt" } flavor { flavorName = "flavor2" // 背景需要按照每個flavor的appVersion來建立獨立的工程,并單獨下發更新檔 appVersion = "${tinkerpatchSupport.appVersion}_${flavorName}" pathPrefix = "${bakPath}/${baseInfo}/${flavorName}${buildType}/" name = "${project.name}-${flavorName}${buildType}" baseApkFile = "${pathPrefix}/${name}.apk" baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt" baseResourceRFile = "${pathPrefix}/${name}-R.txt" } }

2. 對加強的支援

這裡預設大家有同時生成加強管道與非加強管道的需求,如果隻是單一需要加強,可以直接在配置中開啟protectedApp = true即可。

可以參考tinkerpatch.gradle檔案,具體工程可以參照tinkerpatch-flavors-sample:

productFlavors { flavor { flavorName = "protect" appVersion = "${tinkerpatchSupport.appVersion}_${flavorName}" pathPrefix = "${bakPath}/${baseInfo}/${flavorName}-${variantName}/" name = "${project.name}-${flavorName}-${variantName}" baseApkFile = "${pathPrefix}/${name}.apk" baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt" baseResourceRFile = "${pathPrefix}/${name}-R.txt" protectedApp = true } flavor { flavorName = "flavor1" appVersion = "${tinkerpatchSupport.appVersion}_${flavorName}" pathPrefix = "${bakPath}/${baseInfo}/${flavorName}-${variantName}/" name = "${project.name}-${flavorName}-${variantName}" baseApkFile = "${pathPrefix}/${name}.apk" baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt" baseResourceRFile = "${pathPrefix}/${name}-R.txt" } }

加強步驟: 

  1. 生成開啟protectedApp = true的基礎包(這裡假設此APK名為:protected.apk);
  2. 上傳protected.apk到相應的加強網站進行加強,并釋出應用市場(請遵循各個加強網站步驟,一般為下載下傳加強包-》重新簽名-》釋出重簽名加強包);
  3. 在tinkerPatch背景根據appVersion建立相應的App版本(比如這裡2個flavor,就需要建立2個App版本。App版本即為各自flavor中配置的appVersion);
  4. 基于各個flavor的基礎包(這裡的基礎包是第一步中生成的未加強的版本)生成相應patch包,并上傳至相應的App版本中,即完成更新檔釋出。

protectedApp=true, 這種模式僅僅可以使用在加強應用中

支援清單: 

加強廠商 測試
樂加強 Tested
愛加密 Tested
梆梆加強 Tested
360加強 Tested
其他 請自行測試,隻要滿足下面規則的都可以支援

這裡是否支援加強,需要加強廠商明确以下兩點:

  1. 不能提前導入類;
  2. 在art平台若要編譯oat檔案,需要将内聯取消。

3. 重命名備份檔案

/** * (可選)重命名備份檔案的格式化字元串,預設為'${appName}-${variantName}' * * Available vars: * 1. projectName * 2. appName * 3. packageName * 4. buildType * 5. versionName * 6. versionCode * 7. buildTime * 8. fileSHA1 * 9. flavorName * 10. variantName * * default value: '${appName}-${variantName}' * Note: plz use single-quotation wrapping this format string ** / backupFileNameFormat = '${appName}-${variantName}'

4. 對新增Activity的支援

基礎包必須設定supportComponent=true,并且新增Activity的Exported屬性必須為false。

二.項目的編譯

1.先配置項目的singnConfig

tinker-platform熱更新及android studio配置                                    tinker-platform使用簡書二.項目的編譯

2.再配置項目中release和debug的内容

tinker-platform熱更新及android studio配置                                    tinker-platform使用簡書二.項目的編譯

3.進行打包

tinker-platform熱更新及android studio配置                                    tinker-platform使用簡書二.項目的編譯

4.進行打差異包(更新檔)

tinker-platform熱更新及android studio配置                                    tinker-platform使用簡書二.項目的編譯

繼續閱讀