### Android多渠道热更新方案的实现(以WasuTV4.0为例)。 首先,我们来看一下Tinker是什么? ##### Tinker是什么 Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。当然,你也可以使用Tinker来更新你的插件。 它主要包括以下几个部分: gradle编译插件: tinker-patch-gradle-plugin 核心sdk库: tinker-android-lib 非gradle编译用户的命令行版本: tinker-patch-cli.jar ##### 为什么使用Tinker? 我们为什么要使用Tinker,也就是Tinker的优点。 当前市面的热补丁方案有很多,其中比较出名的有阿里的AndFix、美团的Robust以及QZone的超级补丁方案。但它们都存在无法解决的问题,这也是正是我们推出Tinker的原因。 ![](http://ou7prgp6t.bkt.clouddn.com/15110824656518.jpg) ###### 总的来说: AndFix作为native解决方案,首先面临的是稳定性与兼容性问题,更重要的是它无法实现类替换,它是需要大量额外的开发成本的; Robust兼容性与成功率较高,但是它与AndFix一样,无法新增变量与类只能用做的bugFix方案; Qzone方案可以做到发布产品功能,但是它主要问题是插桩带来Dalvik的性能问题,以及为了解决Art下内存地址问题而导致补丁包急速增大的。 特别是在Android N之后,由于混合编译的inline策略修改,对于市面上的各种方案都不太容易解决。而Tinker热补丁方案不仅支持类、So以及资源的替换,它还是2.X-8.X(1.9.0以上支持8.X)的全平台支持。利用Tinker我们不仅可以用做bugfix,甚至可以替代功能的发布。Tinker已运行在微信的数亿Android设备上,那么为什么你不使用Tinker呢? ##### Tinker的已知问题 由于原理与系统限制,Tinker有以下已知问题: 1、Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件(1.9.0支持新增非export的Activity); 2、由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码; 在Android N上,补丁对应用启动时间有轻微的影响; 3、不支持部分三星android-21机型,加载补丁时会主动抛出"TinkerRuntimeException:checkDexInstall failed"; 4、对于资源替换,不支持修改remoteView。例如transition动画,notification icon以及桌面图标。 ##### 如何使用Tinker 所以我们这边文档主要讲讲,怎么来使用Tinkker。Tinker为了实现“高可用”的目标,在接入成本上做了妥协。热补丁并不简单,在使用之前请务必先仔细阅读以下文档: 如何快速接入请参考[Tinker 接入指南](https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97); 如何自定义类请参考[Tinker 自定义扩展](https://github.com/Tencent/tinker/wiki/Tinker-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%89%A9%E5%B1%95); Tinker的API预览请[参考Tinker API预览](https://github.com/Tencent/tinker/wiki/Tinker-API%E6%A6%82%E8%A7%88); 其他常见问题,请参考[常见问题](https://github.com/Tencent/tinker/wiki/Tinker-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98); [TinkerPatch后台](http://www.tinkerpatch.com/)补丁平台的支持一键傻瓜式接入,使用请参考[TinkerPatch平台文档](http://tinkerpatch.com/Docs/intro)。 ### 命令行接入 Tinker的官网文档,对于如何接入Tinker的方案已经做了详细说明,主要是讲解gradle的接入方式。[官方Demo](https://github.com/Tencent/tinker/tree/master/tinker-sample-android)也是以gradle的方式进行讲解的。所以,下面我们就命令行接入的方式进行讲解。 ##### 一、集成Tinker 1、添加依赖、修改签名文档以及修改Application等操作,直接参见官方文档,这里不再赘述。 ``` //可选,用于生成application类 provided('com.tencent.tinker:tinker-android-anno:1.9.1') //tinker的核心库 compile('com.tencent.tinker:tinker-android-lib:1.9.1') ``` 2、添加TINKER_ID。每次发新的版本,需要更新这个TINKER_ID.用来标记补丁包是基于哪个基准APK。 ``` ``` 3、参考官方文档,改造Application.将原来TvApp里面的方法对应移植到TvAppLike的类中。 ![](http://ou7prgp6t.bkt.clouddn.com/15112463485594.jpg) 4、加载补丁逻辑。可以放在原来升级逻辑中。 ``` private void loadPatch() { Log.i(TAG, "loadPatch:" + Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk"); TinkerInstaller.onReceiveUpgradePatch(getApplication().getApplicationContext(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk"); } ``` 5、下载相关命令行工具 ##### 二、热更新升级准备 流程解析: ![](http://ou7prgp6t.bkt.clouddn.com/15113297881238.jpg) 1、打包基准APK 运行项目,打包基准APK的版本V1:WasuTV_Haier_RTD2968_V1-old.apk。也就待热更新修改的版本。这个版本存在两个问题: (1)导航栏多了一个控件,影响了正常功能。(补丁会去掉这个控件) (2)右上角提示显示不对(Haier_RTD2968 UnPatched)正常显示应该是“Haier_RTD2968 已补丁” 我们的补丁包要对这两个问题进行解决。 ![](http://ou7prgp6t.bkt.clouddn.com/15112453318443.jpg) 2、打包用于比对生成热更新patch包的版本:V2:WasuTV_Haier_RTD2968_V2.apk,也就是我们修复了Bug的版本。 ![](http://ou7prgp6t.bkt.clouddn.com/15112501699691.jpg) 3、准备命令行工具。 从Tinker的官网地址下载tool_output文件夹里面所有的文件。别忘了工程编译的签名文件也要拷进来。接下来下载命令行工具 https://github.com/Tencent/tinker/tree/master/tinker-build/tinker-patch-cli/tool_output 全部copy到同一个文件夹,放到工程目录下。 下面就是生成命令行构建工具(Jar包),然后是生成jar文件,点开build.gradle可以看到 ```// copy the jar to work directory task buildTinkerSdk(type: Copy, dependsOn: [build, jar]) { group = "tinker" from('build/libs') { include '*.jar' exclude '*-javadoc.jar' exclude '*-sources.jar' } from('./tool_output') { include '*.*' } into(rootProject.file("buildSdk/build")) } ``` 在androidStudio中Terminal 里面切换到tinker-patch-cli目录下,然后执行 `gradle buildTinkerSdk`命令,即可生成Jar包。 然后拿到了所有的工具了 ![](http://ou7prgp6t.bkt.clouddn.com/15108832614912.jpg) 4、修改Tinker_config.xml ``` ``` 至此,我们热更新的相关准备工作完成。目录如下: ![](http://ou7prgp6t.bkt.clouddn.com/15113192743120.jpg) 5、进入tool_output命令行工具目录下,执行下面的脚本: ``` java -jar tinker-patch-cli-1.9.1.jar -old ../V1/WasuTV_Haier_RTD2968_V1-old.apk -new ../V2/WasuTV_Haier_RTD2968_V2.apk -config tinker_config.xml -out ../patch ``` 生成补丁包: ![](http://ou7prgp6t.bkt.clouddn.com/15113197531120.jpg) 7、演示热更新 首先,按照打补丁之前的应用准备进行热更新。添加加载更新补丁包的测试代码,注意需要APK有读写磁盘的权限。 将补丁包push的电视中 ``` adb push /Users/frewen/02.Projects_Study/01.WorkSpace/wasutv4.0_Tinker/tool_output/output/patch_signed_7zip.apk /storage/emulated/0/ ``` 打开应用,加载补丁包。热更新之后的显示界面如下: ![](http://ou7prgp6t.bkt.clouddn.com/15112501699691.jpg) 两个Bug已经正常修复。