0%

Tinker接入指南

前言:在接入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 {
// TinkerPatch 插件
classpath 'com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.1.4'

//不需要再引入任何Tinker依赖
// classpath 'com.tencent.tinker:tinker-patch-gradle-plugin:1.7.7'
}
}

注意,在这里 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

// 若使用annotation需要单独引用,对于tinker的其他库都无需再引用
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 {
/** 可以在debug的时候关闭 tinkerPatch **/
tinkerEnable = true

/** 是否使用一键接入功能 **/
reflectApplication = true

autoBackupApkPath = "${bakPath}"

/** 在tinkerpatch.com得到的appKey **/
appKey = "yourAppKey"
/** 注意: 若发布新的全量包, 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"
}

上述是需要自行配置的代码模块,其他引入参考: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();
// 我们可以从这里获得Tinker加载过程的信息
tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();

// 初始化TinkerPatch SDK, 更多配置可参照API章节中的,初始化SDK
TinkerPatch.init(tinkerApplicationLike)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true);

// 每隔3个小时去访问后台时候有更新,通过handler实现轮训的效果
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 SDK, 更多配置可参照API章节中的,初始化 SDK
TinkerPatch.init(this)
.reflectPatchLibrary()
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true);

// 每隔3个小时去访问后台时候有更新,通过handler实现轮训的效果
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'
}
} -->

//但是签名密码写在gradle中不安全
//这样在命令执行时,就会被要求输入密码

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

  • 1. 运行./gradlew assembleRelease —no-daemon构建基准包

  • 2. 将步骤一中保存下来的文件手动填到baseInfo/中

因为之前路径已经配置好,所以只需要把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不能是补丁版本一。


参考