Android 运行时资源替换机制RRO(Runtime Resource Overlay )

1. RRO作用

       Android开发中,遇到一个没有代码的三方apk,想要修改其某个button或view等的文字显示或背景或添加某种语言下的翻译等,此机制就能大展身手了

2.RRO介绍

     Android5.0提供RRO机制,能在 apk 运行时,自动加载需要定制的资源,而不加载原有的资源,因而可以通过overlay方式修改无代码的第三方apk的资源文件

    应用通过 getString/getDrawable去调用某个资源时,会将这个resources ID 作为参数传给 framework 层。同一名称但不同状态的 resources ID 是一样的,比如不同分辨率但名称相同的图片分别被放置在了drawable-hdpi/drawable-ldpi/drawable-mdpi下,但在编译时针对该图片生成的resources ID只有一个。framework 层 查 找 资 源 时会使用这个resources ID , 同时还要使 用 当前 系 统 的configuration(分辨率、语言、横竖屏)。通过 resources ID 和 configuration,系统会找到最匹配的资源(如果没有找到,则使用默认的 ),最后将找到的resources ID返回给 apk。

overlay机制图:

(题外话:

PackageId:是包的Id值,Android中如果是第三方应用的话,这个值默认就是0x7F,系统应用的话就是0x01,具体我们可以后面看aapt源码得知,他占用两个字节。

TypeId:是资源的类型Id值,一般Android中有这几个类型:attr,drawable,layout,dimen,string,style等,而且这些类型的值是从1开始逐渐递增的,而且顺序不能改变,attr=0x01,drawable=0x02....他占用两个字节。)

    由上图可以看出应用只是负责提供资源IDs,系统层会根据当前的语言,横竖屏,分辨率等状态去取适当的资源ID加载(题外话:系统资源最佳匹配默认资源,会严格按照配置限定符表中的顺序来进行查找匹配当前设备,可参考https://blog.csdn.net/jamikabin/article/details/50541652该文档)。这种不连续性就提供了资源欺骗的可能,RRO发生在系统层检索资源时,应用层使用资源的接口并没有改变,甚至都不知道还有一个跟它同名的资源存在,因此使用RRO更改应用的资源时无需对原来的应用做任何修改。

RRO机制的运用是依靠overlay apk实现的,与普通的apk相比它不包含代码,只有资源。一个overlay apk只能替换一个目标apk的资源,但一个目标apk的资源可以被多个overlay apk更改。在使用RRO机制的前提是必须要知道待替换目标apk中的资源名

如下以实现添加谷歌输入法中一个字段翻译为例:

1)目录结构:

 

2)res目录下根据自身需要添加资源目录,资源name 要对应需要RRO的目标资源文件name

eg:

 

3)AndroidManifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.google.android.inputmethod.latin.overlay"> //自身apk包名,随便命名

<overlay

android:targetPackage="com.google.android.inputmethod.latin" //需要RRO的目标apk包名

android:priority="1"

android:isStatic="true"/>

</manifest>

 

4)Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

# 平台签名

LOCAL_CERTIFICATE := platform

# 调用本目录res文件夹资源

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

# overlay.apk输出路径,必须在vendor目录下,否则不生效, PRODUCT_OUT=out/target/product/项目名/ TARGET_OUT=$(PRODUCT_OUT)/system

LOCAL_MODULE_PATH := $(PRODUCT_OUT)/vendor/overlay

LOCAL_SDK_VERSION = current

LOCAL_PACKAGE_NAME := LatinImeResourceOverlay

include $(BUILD_PACKAGE)

 

*强调注意项:

1. android:targetPackage 要与被RRO应用包名一直一致

2 android:priority=“1” 覆盖优先级,上面有提到一个apk可被多个overlay apk资源更改,此处优先级确认该overlay apk 之于其它overlay apk 优先等级,值越大,优先等级越高,范围是0-9999,过万就不生效了

3. android:isStatic=“true” 设置该属性,才能RRO,否则overlay不生效,应该是O增加的

注意:
把app放到vendor/overlay下面以后,还要activate,默认是disable的
activate有两种方式:
一种是overlay的app的清单文件中,overlay标签写 isStatic="true"
一种是加系统属性ro.boot.vendor.overlay.theme=overlay的app的包名,分号分割

 

4. 由于overlay替换的是资源文件,所以必须调用res目录资源文件

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

5. 生成的apk需要指定输出到vendor下才会生效,android O 之后,覆盖的资源文件要放在vendor/overlay下面,之前是在system/vendor/overlay

 

 

 

 

 

 

 

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值