共同 Dependency 剔除
在研发过程中,经常需要第三方依赖 Library(Dependency),而当插件工程(以下简称 Plugin)和宿主工程(以下简称 Host)包含相同的 Dependency 时,就需要剔除 Plugin 中的 Dependency。
这样一方面可以避免 Class pre-verified 异常,另一方面也可以减少插件包的大小,提升插件包的下载 & 加载速度。
实现方案(以下都默认 IDE 为 Android Studio):通过 Gradle 插件,在 Plugin 的 Transform 过程中,剔除与 Host 相同 Dependency 的所有资源。
Package ID 修改
在 Android 系统中,App 对应的 Package ID 是固定的,也就是说如果我们不人为干预,Plugin 和 Host 打包生产的 APK 文件中,所有 Resource ID 中的 Package ID 都是一样的,即(0x7f)。
这时如果直接加载 Plugin APK,必然会出现 Resource 类型不匹配、显示错乱等异常,所以我们修改 Plugin 的 APK 的 Package ID。(Package ID 满足 0x01 < PID < 0x7f 即可)
实现方案:业内关于修改 Package ID 的方案有很多(如修改 aapt 源码等),APNP 采用的方案是直接修改最后生成的 APK 文件。
先看下一个简单 APK 的文件结构,如下图:
涉及 Package ID 修改的地方有 3 处:
R.class(classes.dex)
resources.arsc
xml 文件
修改 R.class 中的 Package ID
在 Gradle assemble 之后,会在 build/generated/source/r 文件下生成相应的 R.java 文件,如下图:
此时我们将 R 文件中的 0x7f 直接替换成目标 Package ID ,然后继续交给 Gradle 做后续操作。