一、前言
学习热修复 Tinker 的使用,主要有两个原因:
- 业务需要:项目会出现一些细小的bug,需要等到发布新版才能修复,因此一直有关注热修复这块的技术。
- 技术驱动:这是一件需要一直保持的事情,不断的学习,与时俱进,才能提高自己。
二、Tinker 接入指南
热补丁:让应用能够在无需重新安装的情况实现更新,帮助应用快速建立动态修复能力。
心理准备:Tinker 的接入相对HotFix、AndFix 等要复杂一点,参考了几篇文章,前后分别建了 TinkerDemo、官方DEMO、TinkerFixDemo、TinkerTryDemo。到最后 TinkerTryDemo 才完全弄好。
2.1、gradle接入
gradle是推荐的接入方式,在gradle插件tinker-patch-gradle-plugin中我们帮你完成proguard、multiDex以及Manifest处理等工作。
添加gradle依赖:在项目的build.gradle中,添加tinker-patch-gradle-plugin的依赖
buildscript {
dependencies {
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.7')
}
}
然后在app的gradle文件app/build.gradle,我们需要添加tinker的库依赖以及apply tinker的gradle插件.
dependencies {
//可选,用于生成application类
provided('com.tencent.tinker:tinker-android-anno:1.7.7')
//tinker的核心库
compile('com.tencent.tinker:tinker-android-lib:1.7.7')
}
...
...
//apply tinker插件
apply plugin: 'com.tencent.tinker.patch'
2.2、Tinker 参数 配置
/**Tinker 相关配置----------------开始-----------------------------------*/
def bakPath = file("${buildDir}/bakApk/")
def gitSha() {
try {
String gitRev = '11.2.3.4'
if (gitRev == null) {
throw new GradleException("can't get git rev, you should add git to system path or just input test value, such as 'testTinkerId'")
}
return gitRev
} catch (Exception e) {
throw new GradleException("can't get git rev, you should add git to system path or just input test value, such as 'testTinkerId'")
}
}
ext {
//for some reason, you may want to ignore tinkerBuild, such as instant run debug build?
//Tinker是否可用
tinkerEnabled = false
//for normal build
//old apk file to build patch apk 旧包名
tinkerOldApkPath = "${bakPath}/tinker_demo-debug-1121-17-43-24.apk"
//proguard mapping file to build patch apk 旧包混淆文件目录
tinkerApplyMappingPath = "${bakPath}/app-debug-1018-17-32-47-mapping.txt"
//resource R.txt to build patch apk, must input if there is resource changed 旧包R文件
tinkerApplyResourcePath = "${bakPath}/tinker_demo-debug-1121-17-43-24-R.txt"
//only use for build all flavor, if not, just ignore this field 多渠道
tinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
}
def getOldApkPath() {
return hasProperty("OLD_APK") ? OLD_APK : ext.tinkerOldApkPath
}
def getApplyMappingPath() {
return hasProperty("APPLY_MAPPING") ? APPLY_MAPPING : ext.tinkerApplyMappingPath
}
def getApplyResourceMappingPath() {
return hasProperty("APPLY_RESOURCE") ? APPLY_RESOURCE : ext.tinkerApplyResourcePath
}
def getTinkerIdValue() {
return hasProperty("TINKER_ID") ? TINKER_ID : gitSha()
}
def buildWithTinker() {
return hasProperty("TINKER_ENABLE") ? TINKER_ENABLE : ext.tinkerEnabled
}
def getTinkerBuildFlavorDirectory() {
return ext.tinkerBuildFlavorDirectory
}
if (buildWithTinker()) {
apply plugin: 'com.tencent.tinker.patch'
tinkerPatch {
/**
* 基准apk包路径,也就是旧包路径
* */
oldApk = getOldApkPath()
/**
* 如果出现以下的情况,并且ignoreWarning为false,我们将中断编译。因为这些情况可能会导致编译出来的patch包
* 带来风险:
* 1. minSdkVersion小于14,但是dexMode的值为"raw";
* 2. 新编译的安装包出现新增的四大组件(Activity, BroadcastReceiver...);
* 3. 定义在dex.loader用于加载补丁的类不在main dex中;
* 4. 定义在dex.loader用于加载补丁的类出现修改;
* 5. resources.arsc改变,但没有使用applyResourceMapping编译。
* */
ignoreWarning = fals