大家好,今天推送的这篇文章是来自淘宝童鞋的投稿,也是本公号的第一篇投稿的文章。文章记录了他在对SDK升级时,引入AAR时遇到tools:replace冲突,在Android官网、StackOverflow寻找方案无果的情况下,自己动手落地实现了一套解决方案。好了,话不多说,直接进入正文。
0
问题
最近做一些 SDK 升级时,有些包引入后会有诸如此类的报错:
AndroidManifest.xml:22:9-40 Error:
Attribute [email protected] value=(@style/AppTheme) from AndroidManifest.xml:22:9-40
is also present at [some:libraries:version] AndroidManifest.xml:9:18-62 value=(@style/AnotherTheme).
Suggestion: add ‘tools:replace=”android:theme”‘ to element at AndroidManifest.xml:18:5-65:19 to override.
这是一个很常见的错误了,照着提示做replace就OK了。但是当我加上replace 的代码后,发现依旧报错:
Multiple entries with same key: @android:theme=REPLACE and android:theme=REPLACE.
百思不得其解,查看了一下依赖库的AndroidManifest.xml源码,发现它也设置了tools:replace="android:theme",而Manifest Merger把这个视为冲突抛了出来。
1
思考
如果只是跟着官方的Manifest Merge,这个问题恐怕无解。StackOverflow上也有人问过这个问题,但是没有更多的解法回复。
为什么依赖库会想不开去设置
replace
属性呢?很大的一个可能是:他也碰到了他的依赖库和他的Manifest有冲突的情况。那么我们能做什么?我们始终还是想要把他的某些属性给替换掉的(theme/allowBackup/…),不管他是出于什么样的目的,都不能阻止我想打出包的心!
2
解法
通过简单的观察和源码查看,我们发现merge是发生在process${variant}Manifest这个 Task。那么就得想办法在执行这个任务之前Precheck一下所有依赖的AndroidManifest.xml。
插件地址:https://github.com/2BAB/Seal
我写了一个简易的插件来做这件事,目前支持两个功能:
- 删除Application节点的某些属性,如debuggable、theme、allowBackup;
- 删除Application节点中 tools:replace属性的某些值,如android:icon、android:theme、android:allowBackup;
这个插件不仅能解决上述提到的问题,还能顺带修复诸如下面这种 Warning:
Warning:
AndroidManifest.xml already defines debuggable (in
http://schemas.android.com/apk/res/android); using existing value in
manifest.
而我们所需要做的,仅仅是指定我们不需要libraries的那些属性:
需要注意的是,如果开启了build-cache, Seal建议你把build-cache的文件夹放在工程目录内(就是上面配置里的build-cache位置)。
更多关于Seal的信息,请参考Github仓库内的说明,大家可以给他提PR和ISSUE。