背景
tinker热修复应该很多人都在用,但其实还是有些BUG的。官方据称内部版本与开源版本一致。这不。。又被我碰到一个BUG,差点被坑惨了,导致了半年的热修复不能用,最近空闲下来仔细研究了下原因,终于是找到问题了。
问题
一行代码没改。每次生成出来的补丁有260KB。
原因
- 经过多次对比、排除实验,发现每次都是因为有大量的R文件的res id改变导致。
- 那么导致资源变更的原因是什么呢?
最后发现tinker基准包生成的R.txt文件与实际最后补丁包生成的R.txt文件部分ID的值变了,从而导致所有引用的地方都出现变更。
最终也是通过查看tinker源码的方式,找到了问题所在。
因为tinker生成基准包的R.txt文件里面部分的资源名字在打patch包时aapt2识别不出来导致的。
而触发这个不一致的条件居然是:好死不死我们项目里有部分res的name申明规则导致的。比如:attr.xml里name=xxx.xxx.xxx。是以点的方式命名。
解决
-
升级tinker
tinker在新版里悄咪咪提交了一个commit,解决了这个问题Fix applyResourceMapping for all types of resource names with ‘.’ -
通过aapt2(如果是启用了aapt2)实现id固定
其实看tinker的原理,他是自己通过获取所有res的name,生成了一个R.txt文件。在生成补丁时使用aapt2的–stable-ids指定这个文件,来达到基础包与补丁包资源ID一致的。bug就出在这,生成规则有问题。
而实际上aapt2也提供了输出基准包的R.txt文件的功能,也就是添加–emit-ids参数。
也就是说我们可以直接使用–emit-ids来生成R.txt,再在打基准包时–stable-ids指定这个文件。
有点不明白为什么tinker要自己去生成这个文件,而且还通过反射来设置–stable-ids,可能为了兼容? -
干掉tinker的R.txt生成,自己实现R.txt生成
还有种比较土的就是自己像tinker一样来生成R.txt
题外-tinker命令行
tinker命令行其实是没有提供指定混淆文件以及R.txt文件的接口。
所以如果要用命令行来生成补丁我们就要解决指定mapping.txt和R.txt。
- 混淆文件比较简单就不说了
- R.txt文件就可以可以通过aapt2的stable-ids和–emit-ids来指定
关于如何使用aapt2的stable-ids和–emit-ids,在app的build.gradle下添加配置即可:
aaptOptions {
//补丁包指定
additionalParameters "--stable-ids", "/xxx/public2.txt"
//基准包指定
additionalParameters "--emit-ids", "/xxx/public2.txt"
}
博主在使用Tinker热修复时遇到一个BUG,导致补丁包异常大。经过研究发现,问题源于Tinker生成的R.txt文件与aapt2识别资源名的不一致,特别是对包含点号的资源名处理不当。解决方案包括升级Tinker到修复此问题的版本,或者利用aapt2的--stable-ids和--emit-ids参数直接生成R.txt文件。此外,博客还提到Tinker命令行接口缺少指定混淆文件和R.txt的功能。

579

被折叠的 条评论
为什么被折叠?



