其实现在市场上已经有平台帮我们集成了Tinker热更新,还有提供补丁包管理后台,图形界面操作等等,比如bugly平台,TinkerPatch 平台TinkerPatchSDK集成,只要集成他们提供的SDK就可以,集成也相对比较方便。本文就不讲解这种平台的集成方式了,因为平台上都有详细的官方文档说明。本篇文章主要基于Tinker官方给出的文档,进行热更新的接入,因为Tinker官方文档给的比较复杂。可参照Tinker 官方接入指南。且本文主要采用Gradle方式接入。
一、在Project/build.gradle中添加依赖
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.1')
}
二、在app/build.gradle中添加依赖
// 多dex 打包的类库
implementation "androidx.multidex:multidex:2.0.1"
//可选,用于生成application类
provided('com.tencent.tinker:tinker-android-anno:1.9.1')
//tinker的核心库
implementation('com.tencent.tinker:tinker-android-lib:1.9.1')
三、配置tinker相关信息
在app/build.gradle文件defaultConfig闭包中添加
//由于报annotation错误才引入这一句,可不用
javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } }
// tinker 基本配置
multiDexEnabled true
buildConfigField "String", "MESSAGE", "\"I am the base apk\""
buildConfigField "String", "TINKER_ID", "\"${getTinkerIdValue()}\""
buildConfigField "String", "PLATFORM", "\"all\""
在android闭包添加
// Tinker 推荐设置
dexOptions {
jumboMode = true
}
configurations.all {
resolutionStrategy.force 'com.android.support:support-annotations:27.1.1'
}
定义一个目录,用来存放打包后本地apk,R.txt,mapping.txt文件的存放路径
def bakPath = file("${buildDir}/bakApk/")
定义一些常量,用来保存基准apk包的相关信息(apk,R.txt,mapping.txt),每次要打补丁包时,都需要替换这里的路径,所以在每一次发布新包的同时,要将新包的apk,R.txt,mapping.txt这三个文件保存一份,以便打补丁包时需要用到。
ext {
//for some reason, you may want to ignore tinkerBuild, such as instant run debug build?
tinkerEnabled = true
//for normal build
//old apk file to build patch apk
//每次要打补丁包的时候,都需要替换这边的基准apk路径
tinkerOldApkPath = "${bakPath}/tinkerfixapp-release-0330-17-30-49.apk"
//proguard mapping file to build patch apk
//每次要打补丁包的时候,都需要替换这边的基准apk中的mapping文件路径
tinkerApplyMappingPath = "${bakPath}/tinkerfixapp-release-0330-17-30-49-mapping.txt"
//resource R.txt to build patch apk, must input if there is resource changed
//每次要打补丁包的时候,都需要替换这边的基准apk中的R文件路径
tinkerApplyResourcePath = "${bakPath}/tinkerfixapp-release-0330-17-30-49-R.txt"
//only use for build all flavor, if not, just ignore this field
tinkerBuildFlavorDirectory = "${bakPath}/app-0421-17-11-26"
}
以下是提供一些方法,用来获取具体的值
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 100
}
def buildWithTinker() {
return hasProperty("TINKER_ENABLE") ? TINKER_ENABLE : ext.tinkerEnabled
}
def getTinkerBuildFlavorDirectory() {
return ext.tinkerBuildFlavorDirectory
}
其中getTinkerIdValue()这个方法用来获取tinkerid,我们只要保证每一次打补丁包时,这个id不一样即可,可以直接使用versionCode的值。这样每一次发布一个新包时,这个值都会变化。
下面附上一个完整的build.gradle文件的配置信息,底部的那些是Tinker的配置,一般无需修改
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.tinkerfixapp"
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunne