Tinker的配置
目前公司项目中使用Tinker作为热更新方案,由于Bugly的热更新是基于Tinker,并且提供了补丁的自动下载、合成、应用的功能以及补丁管理后台,所以集成了Bugly的热更新修复,关于Bugly热更新的集成,可以参考我之前发布的一篇文章:
Android热更新初探,Bugly热更新的集成和使用(让你的应用轻松具备热更新能力
Tinker的配置划分在tinker-support.gradle文件中,相关的配置在后面的demo中会给出。
AndResGuard的配置
关于AndResGuard的介绍和集成,可以参考我之前发布的一篇文章:
AndResGuard的配置划分在and_res_guard.gradle文件中,相关的配置在后面的demo中会给出。
Tinker与AndResGuard的结合
由于现在Tinker和AndResGuard是分开配置,还没有进行结合。此时使用Tinker生成的基准包、打出来的补丁,资源并没有进行混淆;如果使用AndResGuard生成apk,资源是混淆过的,当出现bug时,使用Tinker生成补丁,由于补丁中的资源文件没有进行过混淆,所以合成补丁的时候会失败。
所以现在的思路是:
当使用resguardRelease打包后,将生成的混淆过的apk文件、mapping文件、R文件和resouce_mapping文件拷贝到"${buildDir}/bakApk/resguard-MM-dd-HH-mm-ss" 目录下;若是待上线的新版本,则该目录为基准包备份目录,需要将其保存,当需要打补丁的时候,该目录下的文件需要用到。
当使用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的介绍就完了,依旧会提供我写的demo,如果有不清楚的地方可以参考下,如果遇到什么问题,可以在评论区留言:
[https://github.com/chaychan/TinkerAndResGuardDemo]
支持和鼓励
如果觉得我的文章对你有所帮助的话,不妨打赏一下吧!这样我会知道有多少人欣赏我的文章,会更加有动力去写更多好的文章:
共同学习,写下你的评论
评论加载中...
作者其他优质文章