- github地址:https://github.com/Tencent/tinker
- wiki地址(使用文档):https://github.com/Tencent/tinker/wiki
- 补丁管理平台tinkerpatch(官方推荐):
- 补丁管理平台bugly(腾讯):https://bugly.qq.com/v2/
- Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件;
- 由于Google Play的开发者条款限制,不建议在GP渠道动态更新代码;
- 在Android N上,补丁对应用启动时间有轻微的影响;
- 不支持部分三星android-21机型,加载补丁时会主动抛出"TinkerRuntimeException:checkDexInstall failed";
- tinker的一般模式并不支持加固,需要使用usePreGeneratedPatchDex模式,即提前生成补丁模式。某些加固工具可能会将非exported的四大组件类名替换,这些类将无法修改。对于Android N之后的设备,本模式可能会因为内联而出现问题,建议过滤N之后的设备;
- 对于资源替换,不支持修改remoteView。例如transition动画,notification icon以及桌面图标。
- 如果手机版本为api23,gradle中配置的targetsdk版本也是23,补丁打不上(我的华为p9手机和genymotion模拟器是这样的)
- 补丁需要重启才能生效
tinkerId = getTinkerIdValue()
并将其替换成tinkerId = "tinkerId"
,其中后面的值可以随意设置,比如可以设置为版本号或版本名,这个用于补丁校验的,如果补丁id和基准apk的tinkerid不一致,就打不上去
ignoreWarning = false
为ignoreWarning = true
.编译运行原版apk
使用assembleDebug 任务(如下图)编译并生成debug apk,如果是release,就运行assembleRelease
这里注意 android studio run 按钮生成的apk可能不会加入签名,使用tinker插件生成补丁包时候回导致签名不一致问题,建议使用assembleXXX 任务生成基准包,而且直接run 还会导致:
对照基准apk包和补丁apk发现补丁apk比基准apk大了1M多,查看log.text发现居然多了很多莫名其妙的图片,详见wiki issue:https://github.com/Tencent/tinker/issues/103
各种配置详见官方wiki:
https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
此时Tinker会在工程的app/build/bakApk/目录下保存这个时间点打包好的apk文件(这里就是基准包---所谓基准包 就是未启用热修复的包),找到刚才生成的apk文件(记住,一定要配置对基准包,基准包就是现在在运行,将来要打补丁的app对应的当时生成的apk),复制其完整文件名,在app的build.gradle文件找到tinkerOldApkPath这一项设置,并将其设置为tinkerOldApkPath = "${bakPath}/<刚才生成的apk文件名>"(见图2)
图2
在build.gradle文件找到tinkerApplyResourcePath这一项设置,并将其设置为tinkerApplyResourcePath = "${bakPath}/<刚才生成的apk文件名下面的txt文件>"
apk,R.txt,mapping.txt等其他几个backApk目录下面生成的东西和gradle中ext各项对应
形如
tinkerOldApkPath = "${bakPath}/app-debug-1018-17-32-47.apk"
//proguard mapping file to build patch apk
tinkerApplyMappingPath = "${bakPath}/app-debug-1018-17-32-47-mapping.txt"
//resource R.txt to build patch apk, must input if there is resource changed
tinkerApplyResourcePath = "${bakPath}/app-debug-1018-17-32-47-R.txt"
//only use for build all flavor, if not, just ignore this field
tinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
修改源码 生成新版apk 补丁
运行完毕后,补丁apk文件所在位置见图5
将patch_signed_7zip.apk这个文件拷贝到Android设备的ExternalStorageDirectory()路径下(即SD卡目录下).文件的路径和文件名可以随意设定,只需在MainActivity中指明补丁Apk路径即可(见图6),正式使用时,上传补丁到管理后台,后缀最好不要apk,以免被运营商挟持
安装热修复补丁 观察程序变化
点击APP主界面中的LOAD PATCH加载补丁,提示成功后,点击KILL SELF结束当前进程(Tinker必须重启才能热修复成功),重新启动后,即可发现变化.
常见问题:
网络情况不佳时,tinker插件所依赖的库或者插件缺失(如 com.tencent.mm:SevenZip 缺失)
1.1 原因:下载地址是https开头,导致下载不下来
1.2 解决办法:找到C盘用户目录下.gradle目录下的cache目录(形如 C:\Users\hasee.gradle\caches)
删除该文件夹下所有文件以及文件夹然后将 根目录(Project:)build.gradle中把
把jcenter()
更改为
jcenter(){ url 'http://jcenter.bintray.com/' }
再重新编译。(相当于再次重新下载依赖)
Error:Execution failed for task ':app:transformClassesWithJarMergingForDebug'. BSDiff$1.class
解决办法: clean project
Error:(9, 0) Your project path contains non-ASCII characters编译失败
原因:工程目录处于中文路径下
解决办法:不处于中文路径下就好了
加载补丁时补丁加载失败
补丁加载失败的原因很多,具体原因可以在logcat中查看,但是需要确保logcat的设置如下,否则tinker合成补丁日志输出获取不到
常见加载失败有签名校验的问题
解决办法:注意不要搞混 tinkerPatchDebug gradle任务 和 tinkerPatchReleas gradle任务 对应生成的
patch_signed_7zip,debug签名就用 tinkerPatchDebug gradle任务 生成的 patch_signed_7zip
1.多个补丁,只会更新最新上传的那个补丁(自动生成的那个序号最大的)
2.只会更新对应版本配置下的补丁
3.如果当前版本为base,相对base生成了第一个补丁patch1,相对base生成了第二个补丁patch2,手机上安装的base版本可以更新patch1,也可以直接更新patch2
如果patch2是相对base+patch1代码生成的apk生成的补丁,当前安装的是base,无法更新,当前即使先更新到patch1,也没法更新patch2补丁
当前原始安装的app必须作为基准去生成patch,才能在当前原始安装的app上更新这个patch
4.如果patch1增加一个功能1,app成功打上patch1,patch2中删除了patch1的功能1,增加了功能2,app成功打上patch2,结果功能1消失,功能2出来,app应该只加载最新的一个patch,并不是多个patch功能叠加
5. 如果服务器有多个补丁都没有更新,只会更新最新的补丁(补丁版本号最大的),如果当前的补丁版本号比服务器上最大补丁版本号的大或者相等,不会更新补丁