为什么要做热修复
线上问题是一直以来都是困扰手机端的一块心病,一旦爆发,轻则影响用户体验,客户反馈抱怨不断,重则影响用户使用,造成用户流失。由于手机端与服务端和前端不同,没有办法热部署。修复问题后必须经过重新打版并提交到应用商店之后才可以推送到用户手,而且还需要强制App升级。热修复技术的出现完美的解决了这个问题,它让App也拥有了不发版直接解决问题的能力。随着各大团队不断开源自己的热修复技术,各自热修复的方法也略有不同,关于热修复的原理剖析的文章比比皆是。当然对于热修复这一手机端划时代的产物了解其实现原理还是很有必要的,但我相信还是有很多人更想看到的是如何将这一技术无缝应用于自己的项目,为自己的项目服务,在项目稳定应用之后再去探究其内部原理。
动手接入Tinker
闲话少叙,下面就让我来为大家展示如何一分钟接入Tinker到自己现有的项目并对项目进行bug修复。第一步下载文章末尾处的Demo源码,Copy项目app目录下的tinker-support.gradle文件到自己项目的app目录下。注意,这里要说明一个官方Demo的坑,官方给出的解释是可以自动生成tinkerId,但实际上选择自动生成tinkerId的时候发现7zip包下的im文件下的tinkerId与Demo log日志打印的tinkerId并不一致,直接导致上传服务器的时候无法识别。所以在官方Demo拷贝tinker-support.gradle的同学需要注意打开官方Demo中对设置tinkerId的注释。
第二步,为整个项目的build.gradle文件添加bugly依赖,之所以选择bugly而非直接的Tinker是因为Tinker云的后台对于免费用户只提供有限次数且更新文件小于500k的服务,作热更新实践测试还好,应用于实际生产项目就不太理想,好在bugly提供了完全免费的分发平台,而且可以定向版本定向版本的推送修复包。
第三步,修改app目录下的build.gradle文件,首先引入对tinker-support.gradle的依赖,接着是开启多Dex配置,最后是添加bugly依赖。tinker-support.gradle是tinker团队对第一版tinker的一个升级,相信看过刚开源tinker项目的人都知道,第一版tinker的app目录下的gradle文件非常复杂繁琐,现在是把tinker相关的一切都统一到tinker-support.gradle来管理,保证了build.gradle的纯净性。而后修改AndroidManifest文件,增加对bugly的配置,以及指向的Application。
第四步,配置工程的Application,设置bugly默认配置项,几个比较重要的配置有是否开启自动下载补丁,在补丁下载完成之后是否给与用户提示,这个提示框是SDK默认的,根据官方文档暂未发现自定义化定制方法,提示框提供项目重启提示并会对应用重启。Application中还需要配置bugly升级回调,因为这是一个示例,所以增加了Tost显示更新进度。这里还需要申请一个appId作为应用唯一标识,到bugly官网注册账户新建应用即可,关于appId在下一步会具体说明。当然,我们还需要一个入口,那就是在项目启动的时候设置bugly从服务器获取更新文件,推荐在启动页的OnCreat()方法中添加Beta.applyDownloadedPatch(); 开启下载bugly补丁的指令。
第五步,登录bugly管理平台,注册并使用热修复服务,注册用自己的QQ号即可,注册成功后选择立即接入,然后,选择新建产品会弹出图一界面,信息不是非必填,如果作为测试的话可以随便填,像笔者就只填了名称和平台两个信息。创建成功后会跳转到图二界面,这个时候选择右上角的应用升级会跳转到图三界面,bugly提供了强制更新与热更新服务,而且都非常的简单便捷,强制更新只需要将新的安装包上传到bugly云即可,App收到服务器上的更新提醒即可自动下载安装新的安装包。当然,我们的重点还是它的第二个功能,热更新,与强制更新类似,我们只需要将热更新文件上传到bugly云,bugly即可通过tinkerId自动比对版本进行下发,并且提供定向下发功能。
测试修复能力
至此,Tinker的热修复功能已全部完成,如果你有认真看前面的文字去接入,用时绝对不超过一分钟。下面让我们来测试一下热修复功能。首先我们在Activity中的TextView中随便写点什么,没错,有了热修复就是这么随性,我们不怕错。首先修改tinkerId为base版本 tinkerId = "1.0.3-base",然后对项目进行编译打包,生成问题版本的apk。在app目录下的bakAok目录会生成一个跟时间相关的文件夹,里面会包含一个apk,根据build的版本(debug/release)不同会生成不同版本的baseApk。复制文件名到tinker-support.gradle中修改构建生成的基准包目录,修改baseApk名称,注意debug版本对应debug版本,release版本对应release版本,例/app-debug.apk,最后修改tinkerId为path版本 tinkerId = "1.0.3-patch"。然后我们在修改之前问题版本的TextView为随便的另一个值以观测热更新能力,点击右侧gradle的tinker-support目录下的buildTinkerPathDebug Task进行补丁包生成。在build文件下会生成patch_signed_7zip.apk文件,这里需要注意,我们要取的文件是path目录下的而不是tinkerPath目录下的7zip.apk。
接下来是补丁包上传,之前提到过,bugly对于补丁的上传要求非常简单,只需要将7zip上传到服务器即可,bugly会根据已经联网的app上报的tinkerId自动识别补丁需要下发到哪个版本。因为有一个联网识别过程,补丁下发可能会有短暂延迟,不过时间不会太长,请大家耐心等待。
大退应用后,重启App,进入应用会发现下载提示,现在完成后点击重启应用,我们可以看到问题版本的App文字已经变成了我们完成修复的文字,说明热修复已经成功接入。
项目源码 Tinker Demo