当使用tinkerPatchRelease生成补丁前,加入resguardTask任务,这样生成补丁时,使用到的新旧Apk都是资源混淆过的,生成的补丁的资源也是混淆过的,此时,合成补丁的时候,就可以成功了。
主要的配置:
def bakPath(){ return file("${buildDir}/bakApk/")
}/**
* 此处填写每次构建生成的基准包目录
*/def baseApkDir(){ return "resguard-0119-11-29-43" }def detailedBuildTime() { return new Date().format("MMdd-HH-mm-ss", TimeZone.getTimeZone("GMT+8"))
}def appName(){ return "${project.getName()}"}
android {
... //省略
/**
* bak apk and mapping
*/
android.applicationVariants.all { variant -> /**
* task type, you want to bak
*/
def taskName = variant.name
tasks.all { if (variant.buildType.name == 'release') {
def andResDir = "${buildDir}/outputs/apk/${taskName}/AndResGuard_${project.getName()}-${taskName}"; if ("tinkerPatch${taskName.capitalize()}".equalsIgnoreCase(it.name)) { // find resguard task
def resguardTask
tasks.all { if (it.name.startsWith("resguard${taskName.capitalize()}")) {
resguardTask = it
}
}
it.doFirst({ // change build apk path
it.buildApkPath = "${andResDir}/${project.getName()}-${taskName}_aligned_signed.apk"
}) // change task dependence to resguard task
it.dependsOn resguardTask
} if ("resguard${taskName.capitalize()}".equalsIgnoreCase(it.name)) {
it.doLast {
copy {
def outDir = file("${bakPath()}/resguard-${detailedBuildTime()}")
from "${andResDir}/${project.getName()}-${taskName}_aligned_signed.apk"
into outDir
rename { String fileName ->
fileName.replace("${project.getName()}-${taskName}_aligned_signed.apk", "${appName()}.apk")
}
from "${buildDir}/outputs/mapping/${taskName}/mapping.txt"
into outDir
rename { String fileName ->
fileName.replace("mapping.txt", "${appName()}-mapping.txt")
}
from "${buildDir}/intermediates/symbols/${taskName}/R.txt"
into outDir
rename { String fileName ->
fileName.replace("R.txt", "${appName()}-R.txt")
}
from "${andResDir}/resource_mapping_${project.getName()}-release.txt"
into outDir
rename { String fileName ->
fileName.replace("resource_mapping_${project.getName()}-release.txt", "${appName()}-resource_mapping.txt")
}
}
}
}
}
}
}
}
主要是tasks.all { }中的代码,判断如果执行的是release类型的指令,则需要进行处理。
if (variant.buildType.name == 'release') { //是release指令,进行相关处理}
如果是执行tinkerPatchRelease任务,即打补丁,在打补丁之前,需要先调用reguardTask,代码中有" it.dependsOn resguardTask",即该命令依赖于resguardTask,需要先执行resguardTask任务。
if (variant.buildType.name == 'release') {
def andResDir = "${buildDir}/outputs/apk/${taskName}/AndResGuard_${project.getName()}-${taskName}"; if ("tinkerPatch${taskName.capitalize()}".equalsIgnoreCase(it.name)) { // find resguard task
def resguardTask
tasks.all { if (it.name.startsWith("resguard${taskName.capitalize()}")) {
resguardTask = it
}
}
it.doFirst({ // change build apk path
it.buildApkPath = "${andResDir}/${project.getName()}-${taskName}_aligned_signed.apk"
}) // change task dependence to resguard task
it.dependsOn resguardTask
}
}
如果是执行reguardRelease任务,则需要执行备份操作,将混淆过的apk、mapping.txt、R.txt、resource_mapping.txt备份到app目录下的/build/bakApk/reguard-MMdd-HH-mm-ss/目录下:
if ("resguard${taskName.capitalize()}".equalsIgnoreCase(it.name)) {
it.doLast { copy {
def outDir = file("${bakPath()}/resguard-${detailedBuildTime()}")
from "${andResDir}/${project.getName()}-${taskName}_aligned_signed.apk"
into outDir
rename { String fileName ->
fileName.replace("${project.getName()}-${taskName}_aligned_signed.apk", "${appName()}.apk")
}
...
}
}
}
即将下图四个文件复制:


存放在/bakApk/reguard-MMdd-HH-mm-ss/目录下

总结
一、打包
上线前,先执行reguardRelease任务,打出资源混淆过的Apk,生成在备份目录/bakApk/reguard-MM-dd-HH-mm-ss/目录中,同时,需要将该文件夹备份,作为下次热更新的基准包;

二、打补丁
上线后,若出现bug,需要打补丁:
1.在修复完bug的时候,先执行reguardRelease任务,生成新的进行过资源混淆的apk;
2.将备份好的基准包放置在app模块下的/build/bakApk/目录下,修改app模块下build.gradle中基准包目录,如下:
/**
* 此处填写每次构建生成的基准包目录
*/def baseApkDir(){ return "resguard-0119-11-29-43" }
然后执行tinkerPatchRelease任务,生成补丁:

3.找到patch目录下的补丁包,登录bugly后台,上传补丁

到这里结合Tinker和AndResGuard的介绍就完了,
原文链接:http://www.apkbus.com/blog-917385-76906.html