Bugly热更新采用Tinker开源方案,官方文档如下:
Bugly Android热更新使用指南
Bugly Android热更新详解
接入热更新
我们的章鱼App之前就已经接入了Bugly,所以添加热更新支持,只需在gradle文件中进行如下更改即可。
/// 注释掉之前的bugly
//"bugly": 'com.tencent.bugly:crashreport:latest.release', //日志统计
// 添加支持热更新的 bugly
"bugly": 'com.tencent.bugly:crashreport_upgrade:latest.release', //日志统计(1.3.4之前含Tinker热更新,现已剥离)
"tinker": 'com.tencent.tinker:tinker-android-lib:1.9.8', //Tinker热修复
此外,我们还需要在project层级的build.gradle中添加classpath;
接下来添加tinker-support.gradle文件并在app.gradle里添加配置;
......
不一一描述,这些Bugly官方文档里都有。下面主要讲接入热更新后,章鱼App项目引起的改动。
改造Application
在 tinker-support.gradle 文件中配置
enableProxyApplication = true
可以避免Application的改动,但为了更好的兼容性,Tinker官方推荐改造Application。
我们的Application改造前如下图左半,改造后如下图右半。
配置tinker-support
一般来说,在改造好Application后,tinker-support.gradle 无需更改即可使用。但为了在章鱼项目下使用起来便捷,进行了如下修改。
修改文件路径
tinker-support默认指定的文件路径均位于build目录下,而build目录下的文件既不稳定也不会同步到git服务器。这很容易让我们发布线上包后丢失关键文件(用于生成对应补丁包的文件),即打包后在 app/build/bakApk/日期 目录下生成的如下文件:
app-release.apk (必有,预发布为app-prerelease.apk )
app-release-mapping.txt (开启混淆后会有)
app-release-R.txt (必有,预发布为app-prerelease-R.apk )
这些文件大多数时候是无用的,每次运行项目或打包都会生成。我们真正需要的是线上包对应的这些文件。
所以,让tinker-support生成文件的路径不变,将待修复apk的目录修改为 app/bakApk/app-last-release 。
这样,每次我们发布线上包后,将上述生成文件复制一份并替换到 app/bakApk/app-last-release 目录下即可。
自动修改tinkerId
每次打补丁或发布线上包,都需要修改tinkerId,并保证其唯一性。 我们采用如下格式:
"r" + generateDate()
例如 r-05301455 。
提供便利的测试(配置 tinker-support-prerelease.gradle 文件)
以上两项配置保证了线上补丁发布的便利性,但在发布线上补丁前,我们希望对事情有所掌控。这时,我们可以先测试预发布环境补丁效果。
为了方便,将 tinker-support.gradle 复制一份命名为 tinker-support-prerelease.gradle ,将其基准包目录修改为 app/bakApk/app-last-release ,并修改相应文件名。
为了使tinkerId唯一且与线上补丁保持差异,采用如下格式:
"pr" + generateDate()
例如 pr-05301455 。
最后,在 app/build.gradle 文件中做如下修改(定义isReleaseTask()方法用于判断是否为正式环境),根据任务类型自动引入相对应的tinker-support配置。
if (isReleaseTask(gradle.startParameter.taskNames))
apply from: 'tinker-support.gradle'//tinker线上配置
else
apply from: 'tinker-support-prerelease.gradle' //tinker测试预发布包补丁配置。
发包清单
- 修改gradle配置,如versionName, versionCode等(tinker-support文件切换及tinkerId修改已自动化);
- walle打包(Tinker支持walle多渠道包热修复);
- 将刚才 app/build/bakApk/日期 目录下生成的文件备份到 app/bakApk/app-last-release 目录(切记,只有确认发布的线上包才这么做);
- 打tag,并将代码提交至服务器。
发补丁清单
Tinker补丁不具有即时性,需要app收到补丁后下次启动才会生效。
Tinker补丁支持修改gradle文件与资源文件。建议补丁与基准包(待修复包)保持一致的versionName, versionCode。
此外,Tinker对Manifest的修改支持性不好,建议补丁包别动Manifest,若需要改动,请先在预发布环境下测试补丁的效果。
补丁发布步骤:
- 待发布代码测试通过;
- 生成预发布环境补丁包;
- 发布预发布环境补丁包并观察效果;
——若3顺利通过,则继续向下执行,否则break。 - 生成线上补丁包;
- 灰度发布线上补丁包并观察效果;
——若5顺利通过,则继续向下执行,否则break。 - 全量发布线上补丁包。
第2、3步是对补丁是否能生效的测试,约耗时15~30分钟。理论上这两步是可以省去的,在你确保改动代码被Tinker支持的情况下。不过,不建议如此,热修复依然存在许多问题,在预发布环境先行测试补丁效果具有必要性。
如何生成补丁
线上补丁与测试补丁生成的差异主要体现在配置上。
生成测试补丁
将代码切回至有问题的线上节点。
在此配置下使用walle打 prerelease 包,并备份刚刚在 app/build/bakApk/日期 目录下生成的基准文件。
安装刚刚生成的基准apk(即代码等同于线上包的debug包);
代码切回到待发布节点(前面几步造成的代码改动不需要保存),将第2步备份好的基准文件替换到 app/bakApk/app-last-prerelease 目录。——如果早已备份好线上对应的测试包,且已安装,则之前步骤都可以省去。
-
如下图,执行 buildTinkerPatchPreRelease/buildTinkerPatchDebug 指令生成prerelease/debug补丁。
生成线上补丁
因为在打包时已对线上补丁进行备份,所以生成线上补丁比测试补丁更为简单,步骤如下。
将代码切换至待发布补丁的节点。
保证versionName、versionCode与线上版本一致(以免后续升级有问题)。
执行 buildTinkerPatchRelease 指令生成release补丁。
如何发布补丁
生成后的补丁位于项目 app/build/outputs/patch/环境 目录下,其中, patch_signed_7zip.apk 文件即为要发布的补丁。
将 patch_signed_7zip.apk 文件上传至Bugly指定项目即可。
图文请参照bugly官方文档:上传补丁包到平台。
观察补丁情况
每个补丁都对应着特定的一个apk,比如前面提到的线上apk或调试apk,在装有该apk的手机上观察补丁的下发与生效。补丁生效需app重启。
如何验证?
为了便于验证,在 build.gradle 里添加一个字段 APK_DATE
buildConfigField "String", "APK_DATE", ""${generateDate()}""
这样,APK_DATE 即为apk的构建时间(即我们用指令生成该apk或其最新补丁的时间);
在设置页面连击版本号7次,即可观察到相关信息 "生成时:" + BuildConfig.APK_DATE。我们根据该时间信息可以很轻松地判定出当前包是否为补丁包。