前言:在接入Tinker前先简单了解下Tinker原理

TinkerPatch 接入
很多接入指南和教程都是以接入Tinker为例,但实际情况一个产品不可能只有开发人员自己使用,需要能够管理和下发补丁的平台,结合实际情况选择TinkerPatch平台接入是最合适的。
Tinker 需要使用者有一个后台可以下发和管理补丁包,并且需要处理传输安全等部署工作,TinkerPatch 平台帮你做了这些工作,提供了补丁后台托管,版本管理,保证传输安全等功能,让你无需搭建一个后台,无需关心部署操作,只需引入一个 SDK 即可立即使用 Tinker
① 添加gradle依赖
在项目的build.gradle中添加tinkerpatch-gradle-plugin的依赖
1 2 3 4 5 6 7 8 9 10 11 12
| buildscript { repositories { jcenter() } dependencies { classpath 'com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.1.4' } }
|
注意,在这里 SDK 使用了 fat 打包的模式,我们不能再引入任何 Tinker 的相关依赖,否则会造成版本冲突
然后在app的gradle文件app/build.gradle,我们可选择添加需要的库依赖以及apply tinker和tinkerpatch的gradle插件.
1 2 3 4 5 6 7 8 9 10 11 12 13
| dependencies { compile ’com.android.support:multidex:1.0.1‘ provided('com.tencent.tinker:tinker-android-anno:1.7.7') compile('com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.1.4') }
··· ··· apply plugin: 'com.tencent.tinker.patch' apply plugin: 'tinkerpatch-support'
|
② 配置 tinkerpatchSupport参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| def bakPath = file("${buildDir}/bakApk/") def baseInfo = "app-1.0.0-0407-22-42-41" def variantName = "release"
tinkerpatchSupport { tinkerpatchSupport { tinkerEnable = true
reflectApplication = true
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" }
|
上述是需要自行配置的代码模块,其他引入参考:tinkerpatch.gradle
针对特殊需求,具体的参数含义可参考 Tinker 文档:Tinker接入指南.
③ 初始化 TinkerPatch SDK
1.reflectApplication = true 的情况
若我们使用 reflectApplication 模式,我们无需为接入 Tinker 而改造我们的 Application 类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class SampleApplication extends Application {
...
@Override public void onCreate() { super.onCreate(); tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
TinkerPatch.init(tinkerApplicationLike) .reflectPatchLibrary() .setPatchRollbackOnScreenOff(true) .setPatchRestartOnSrceenOff(true);
new FetchPatchHandler().fetchPatchWithInterval(3); }
...
|
2.reflectApplication = false 的情况
若我们已经完成了应用的 Application 改造,即将 Application 的逻辑移动到 ApplicationLike类中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class SampleApplicationLike extends DefaultApplicationLike {
...
@Override public void onCreate() { super.onCreate(); TinkerPatch.init(this) .reflectPatchLibrary() .setPatchRollbackOnScreenOff(true) .setPatchRestartOnSrceenOff(true);
new FetchPatchHandler().fetchPatchWithInterval(3); }
...
}
|
④ 使用步骤(Release为例)
使用gradle 进行apk签名打包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| android {
<!-- signingConfigs { releaseConfig { keyAlias 'stone' keyPassword 'mypwd' storeFile file('/Users/stone/Documents/project_AS/myapplication/stone.keystore') storePassword 'mypwd' } } -->
android { signingConfigs { releaseConfig { storeFile file("stone.keystore") storePassword System.console() != null ? System.console().readLine("\nKeystore password: ") : "" keyAlias "stone" keyPassword System.console() != null ? System.console().readLine("\nKey password: ") : "" } }
buildTypes { release { ... signingConfig signingConfigs.release } } }
|
- 0. 运行
./gradlew assembleRelease 构建基准包
For some reason, running gradle in daemon mode causes a null console object.
Cannot invoke method readLine() on null object
解决方法
./gradlew assembleRelease —no-daemon
因为之前路径已经配置好,所以只需要把release.apk填写入baseInfo

- 3. 修改源代码,运行./gradlew tinkerPatchRelease —no-daemon构建补丁包,补丁包将位于 build/outputs/tinkerPatch 中

- 4. 将patch_signed _7zip.apk加入管理平台
FAQ
1.关于Application的改造
Tinker自定义扩展:自定义Application类
2.如何做多次修复?
Tinker支持对同一基准版本做多次补丁修复,每次生成补丁包后,tinker会生成加上补丁包的新包,这时需要将基准包替换为最新的,即补丁版本二的oldApk不能是补丁版本一。
参考