热修复方案概述:
- QQ空间热修复方案
- native hook的方案
- 微信热修复方案
- Tinker_imitator(微信热更新方案实践)
- tinker(微信官方)
- 手机QQ热修复方案
- QFix:推荐文章QFix探索之路——手Q热补丁轻量级方案
此次我们了解下微信热修复方案-Tencent/tinker(以下内容来自tinker的Github),相关使用请参考WIKI
Tinker -- 微信Android热补丁方案
Tinker是什么
Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。当然,你也可以使用Tinker来更新你的插件。
它主要包括以下几个部分:
- gradle编译插件: tinker-patch-gradle-plugin
- 核心sdk库: tinker-android-lib
- 非gradle编译用户的命令行版本: tinker-patch-cli.jar
为什么使用Tinker
当前市面的热补丁方案有很多,其中比较出名的有阿里的AndFix、美团的Robust以及QZone的超级补丁方案。但它们都存在无法解决的问题,这也是正是我们推出Tinker的原因。
总的来说:
AndFix作为native解决方案,首先面临的是稳定性与兼容性问题,更重要的是它无法实现类替换,它是需要大量额外的开发成本的; Robust兼容性与成功率较高,但是它与AndFix一样,无法新增变量与类只能用做的bugFix方案; Qzone方案可以做到发布产品功能,但是它主要问题是插桩带来Dalvik的性能问题,以及为了解决Art下内存地址问题而导致补丁包急速增大的。
特别是在Android N之后,由于混合编译的inline策略修改,对于市面上的各种方案都不太容易解决。而Tinker热补丁方案不仅支持类、So以及资源的替换,它还是2.X-7.X的全平台支持。利用Tinker我们不仅可以用做bugfix,甚至可以替代功能的发布。Tinker已运行在微信的数亿Android设备上,那么为什么你不使用Tinker呢?
Tinker的已知问题
由于原理与系统限制,Tinker有以下已知问题:
- Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件;
- 由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码;
- 在Android N上,补丁对应用启动时间有轻微的影响;
- 不支持部分三星android-21机型,加载补丁时会主动抛出"TinkerRuntimeException:checkDexInstall failed";
- 由于各个厂商的加固实现并不一致,在1.7.6以及之后的版本,tinker不再支持加固的动态更新;
- 对于资源替换,不支持修改remoteView。例如transition动画,notification icon以及桌面图标。
如何使用Tinker
Tinker为了实现“高可用”的目标,在接入成本上做了妥协。热补丁并不简单,在使用之前请务必先仔细阅读以下文档:
- 如何快速接入请参考Tinker 接入指南;
- 如何自定义类请参考Tinker 自定义扩展;
- Tinker的API预览请参考Tinker API预览;
- 其他常见问题,请参考常见问题;
- TinkerPatch后台补丁平台的支持一键傻瓜式接入,使用请参考TinkerPatch平台文档。
Tinker 接入指南
gradle接入
gradle是推荐的接入方式,在gradle插件tinker-patch-gradle-plugin中我们帮你完成proguard、multiDex以及Manifest处理等工作。 添加gradle依赖
在项目的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'
gradle参数详解
我们将原apk包称为基准apk包,tinkerPatch直接使用基准apk包与新编译出来的apk包做差异,得到最终的补丁包。
这个地方,对比官方文档和官方提供的demo来学习时,很明显感觉到比较繁琐,但为了严谨和后面维护少出问题,还是请大家仔细阅读和详细分析官方demo的配置步骤;
tinkerPatch task详解
直接使用task:tinkerPatchVariantName(例如tinkerPatchDebug、tinkerPatchRelease)即可自动根据Variant选择相应的编译类型,同时它还贴心的为我们完成以下几个操作:
-
将TINKER_ID自动插入AndroidManifest的meta项,输出路径为build/intermediates/tinker_intermediates/AndroidManifest.xml;
-
如果minifyEnabled为true,将自动将Tinker的proguard规则添加到proguardFiles中,输出路径为build/intermediates/tinker_intermediates/tinker_proguard.pro,这里你不需要将它们拷贝到自己的proguard配置文件中;
-
如果multiDexEnabled为true,将自动生成Tinker需要放在主dex的keep规则。在tinker 1.7.6版本之前,你需要手动将生成规则拷贝到自己的multiDexKeepProguard文件中。例如Sample中的multiDexKeepProguard file("keep_in_main_dex.txt")。在1.7.6版本之后,这里会通过脚本自动处理,无须手动填写。
-
把dexOptions的jumboMode打开。
输出路径为:build/intermediates/tinker_intermediates/tinker_multidexkeep.pro。 后你可以在build/outputs/tinkerPatch中找到输出的文件。
多Flavor打包
有的时候我们希望通过flavor方式打包,在sample中提供了简单的用法事例:
1.通过flavor编译,这个时候我们可以看到bakApk路径是一个按照flavor名称区分的目录;
2.将编译目录路径填写到sample中tinkerBuildFlavorDirectory,其他的几个字段不需要填写,这里会自动根据路径拼接;
ext {
tinkerBuildFlavorDirectory = "${bakPath}/app-1014-13-35-12"
}
3.运行tinkerPatchAllFlavorDebug或者tinkerPatchAllFlavorRelease即可得到所有flavor的补丁包。 输出文件详解
在tinkerPatch输出目录build/outputs/tinkerPatch中,我们关心的文件有: 文件名 描述 patch_unsigned.apk 没有签名的补丁包 patch_signed.apk 签名后的补丁包 patch_signed_7zip.apk 签名后并使用7zip压缩的补丁包,也是我们通常使用的补丁包。但正式发布的时候,最好不要以.apk结尾,防止被运营商挟持。 log.txt 在编译补丁包过程的控制台日志 dex_log.txt 在编译补丁包过程关于dex的日志 so_log.txt 在编译补丁包过程关于lib的日志 tinker_result 最终在补丁包的内容,包括diff的dex、lib以及assets下面的meta文件 resources_out.zip 最终在手机上合成的全量资源apk,你可以在这里查看是否有文件遗漏 resources_out_7z.zip 根据7zip最终在手机上合成的全量资源apk tempPatchedDexes 在Dalvik与Art平台,最终在手机上合成的完整Dex,我们可以在这里查看dex合成的产物。
每次编译结束,我们都应该查看相关日志,清楚最终在补丁包中的文件。尤其是dex的补丁文件,即使是1k的dex补丁文件,也会带来合成时的时间损耗以及合成完整dex文件ROM空间体积这两部分影响!
TinkerPatch补丁管理后台
www.tinkerpatch.com 是第三方开发基于CDN分发的补丁管理后台。它提供了脚本后台托管,版本管理,保证传输安全等功能,让你无需搭建一个后台,无需关心部署操作,只需引入一个 SDK 即可立即使用 Tinker。
此外,TinkerPatch 平台增加了一键傻瓜式接入/编译管理优化等功能,它的Github地址为TinkerPatch。
总的来说,我们更推荐使用gradle作为接入方式。
Sample的使用方法
Demo请参考tinker-sample-android
动手能力强的同学,可以自己按照wiki中的步骤一点一滴的逐步学习; 需要提醒大家的是:如果遇到问题,提issue前一定先参考下这个Tinker-常见问题,否则,issue都不会被关注而是直接关闭的; 懒得动手的话,可直接接入tinker的第三方平台,参考接入文档,有免费版和收费版两种可供选择。
坚持原创技术分享,您的支持将鼓励我继续创作!