前言
Tinker简介
Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。当然,你也可以使用Tinker来更新你的插件。
Tinker已知问题
1) Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件;
2) 由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码
3) 在Android N上,补丁对应用启动时间有轻微的影响;
4) 不支持部分三星android-21机型,加载补丁时会主动抛出”TinkerRuntimeException:checkDexInstall failed”;
5) 对于资源替换,不支持修改remoteView。例如transition动画,notification icon以及桌面图标。
2. Tinker接入指南
2.1. Gradle接入
gradle是推荐的接入方式,在gradle插件tinker-patch-gradle-plugin中官方帮助完成proguard、multiDex以及Manifest处理等工作。
在项目的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'
tinker参数配置
同样是在项目的app的gradle文件app/build.gradle文件里,在文件的末尾加上如下相关配置:
/**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 = true
//for normal build
//old apk file to build patch apk 旧包名
tinkerOldApkPath = "${bakPath}/app-debug-0711-15-50-35.apk"
//proguard mapping file to build patch apk 旧包混淆文件目录
tinkerApplyMappingPath = "${bakPath}/app-debug-0711-15-50-35-mapping.txt"
//resource R.txt to build patch apk, must input if there is resource changed 旧包R文件
tinkerApplyResourcePath = "${bakPath}/app-debug-0711-15-50-35-R.txt"
//only use for build all flavor, if not, just ignore this field 多渠道
tinkerBuildFlavorDirectory = "${bakPath}/app-0711-15-50-35"
}
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 = false
/**
* 在运行过程中,我们需要验证基准apk包与补丁包的签名是否一致,我们是否需要为你签名