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 的使用步驟非常簡單,一般來說可以參考以下幾個步驟:
- 運作 assembleRelease task 建構基準包(請在釋出前確定更新tinkerpatchSupport中的appVersion),tinkerPatch會基于你填入的autoBackupApkPath自動備份基礎包資訊到相應的檔案夾,包含:apk檔案、R.txt檔案和mapping.txt檔案 (注:mapping.txt是proguard的産物,如果你沒有開啟proguard則不會有這個檔案)
- 若想釋出更新檔包, 隻需将自動儲存下來的檔案分别填到tinkerpatchSupport中的baseApkFile、baseProguardMappingFile和baseResourceRFile 參數中;
- 運作 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" } }
加強步驟:
- 生成開啟protectedApp = true的基礎包(這裡假設此APK名為:protected.apk);
- 上傳protected.apk到相應的加強網站進行加強,并釋出應用市場(請遵循各個加強網站步驟,一般為下載下傳加強包-》重新簽名-》釋出重簽名加強包);
- 在tinkerPatch背景根據appVersion建立相應的App版本(比如這裡2個flavor,就需要建立2個App版本。App版本即為各自flavor中配置的appVersion);
- 基于各個flavor的基礎包(這裡的基礎包是第一步中生成的未加強的版本)生成相應patch包,并上傳至相應的App版本中,即完成更新檔釋出。
protectedApp=true, 這種模式僅僅可以使用在加強應用中
支援清單:
加強廠商 | 測試 |
樂加強 | Tested |
愛加密 | Tested |
梆梆加強 | Tested |
360加強 | Tested |
其他 | 請自行測試,隻要滿足下面規則的都可以支援 |
這裡是否支援加強,需要加強廠商明确以下兩點:
- 不能提前導入類;
- 在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
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL6tGVNlXVURWNsdUY2QWbihGZzwEMW1mY1RzRapnTtxkb5ckYplTeMZTTINGMShUYfRHelRHLwEzX39GZhh2css2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3Pn5GcuMTOyAjMzYTMzITMxgTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
2.再配置項目中release和debug的内容
3.進行打包
4.進行打差異包(更新檔)