什么是运行时资源覆盖
无需修改原app的代码,无需重新编译,就能覆盖app内的部分资源,从而实现修改app的部分UI,后面简称RRO。
RRO原理
应用通过 getString/getDrawable去调用某个资源时,会将这个resources ID 作为参数传给 framework 层。同一名称但不同状态的 resources ID 是一样的,比如不同分辨率但名称相同的图片分别被放置在了drawable-hdpi/drawable-ldpi/drawable-mdpi下,但在编译时针对该图片生成的resources ID只有一个。
为了快速查找到指定的资源,Apk编译的时候会把Java文件里面的R.String.app_name替换成ox7f123456这种格式的值
每个apk里面都有一个文件(resources.arsc)记录着指定的resource_id对应的资源类型,如果是string类型,则记录的这个资源名称对应的所有语言的翻译,如果是drawable类型,则记录着哪些分辨率底下有这个资源。
Resources.arsc的结构 string


Resources.arsc的结构 drawable

RRO实现方法
- 建立一个新的overlay apk项目,apk项目底下有 res文件夹,Android.mk、AndroidManifest.xml
- 修改AndroidManifest.xml 配置apk的包名、要覆盖的apk的包名
- 修改Android.mk 使得apk能集成到system/vendor/overlay/目录下
- 找到需要覆盖的资源名,在overlay apk的res指定目录下定义同名的资源
AndroidManifest.xml的写法
1 |
|
Android.mk的写法及自动生成版本号的实现
1 | ifeq ($(strip $(MYOS_APE_GALLERY31_SUPPORT)), yes) |
自动生成版本号的意义
- 出现问题以后反查问题原因,是代码问题,还是集成问题
- 这里为什么要使用自动版本号:
- 不用每次改版本号的麻烦
- 版本号有序自增,没有出错的风险
- 每一个编译出来的apk,都能定位到当时的最后一个提交
- 由于是随系统编译,可能你没来得及改版本号就编译了,所以手工改版本号可能只能定位到大致的位置
- 注意事项:
- 仓库提交9999次以后,版本会溢出,此时可以脚本向前进位
注意事项
- 不能覆盖layout、AndroidManifest.xml、asset目录
- 建议只覆盖字符资源、覆盖图片要谨慎
- Overlay apk中不要添加其它的东西,比方说style.xml 可能会导致被覆盖的apk打开就报错
- Overlay apk 必须要签名,否则不生效
- 为了安全起见,Overylay的apk必须放到system/vendor/overlay/目录下才会生效
- 由于是把源码放在基线里面编译,所以提交代码需要特别小心,不要造成项目编译不过
RRO对我们目前来说使用的意义
- 对于字符翻译需求,快速输出版本
- DCC以后,只有翻译需求,无需更新主apk版本