AndroidQ RRO(Runtime Resource Overlay)机制(1)

概述

Android5.0引入了RRO,RRO全称(Runtime Resource Overlay),它可以实现在不修改三方应用源码的情况下,替换其资源,主要依靠一个叫做overlay apk的应用实现的, overlay apk和普通的应用相比最大的区别就是overlay apk不含任何代码(java或者C++),它的一般结构仅包含一个AndroidManifest.xml和res目录,当然因为需要在源码下编译,还包含一个Android.mk或者Android.bp(也可以用AS编译,前提是AS编译出来的apk需要有平台签名)。

AndroidQ RRO(Runtime Resource Overlay)机制(1)_第1张图片

RRO替换资源的基本原理如图:
AndroidQ RRO(Runtime Resource Overlay)机制(1)_第2张图片
以替换背景颜色为例:首先我们需要给View设置背景颜色,颜色值定义在colors.xml中,假设其值为bg_color---->#FFFFFF,资源打包之后的ID为0x7f020001,接着系统资源管理框架拿到这个ID并不会立即去target资源包中找,而是先判断此应用是否有overlay,如果有就会去读取target应用与overlay应用共同生成的Idmap文件,此文件中包含了这两个应用之间同名资源的ID映射关系,假设0x7f030010就是overlay资源包中为它的bg_color所生成的ID,此时系统资源管理框架内部就将 0x7f020001替换为了0x7f030010 ,然后拿着0x7f030010去overlay资源包找对应的bg_color---->#000000,至此完成资源替换。

举个栗子

直接来个栗子,我们在frameworks/base/packages/overlays/目录下创建overlay apk,目录结构如前面的图:
AndroidQ RRO(Runtime Resource Overlay)机制(1)_第3张图片
AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.caic.car.rroresource">
    <overlay android:targetPackage="com.example.overlaydemo" android:category="com.caic.car.theme.customization.rroresource" android:priority="1"/>
    <application android:label="RROResource" android:hasCode="false"/>
manifest>

overlay标签表示这是一个资源overlay应用,targetPackage表示要overlay的目标应用,priority表示overlay包的优先级,因为一个目标应用可能存在多个overlay包,所以需要优先级来排序,值越小优先级越高。

Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_RRO_THEME := RROResource

LOCAL_PRODUCT_MODULE := true

LOCAL_SRC_FILES := $(call all-subdir-java-files)

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

LOCAL_PACKAGE_NAME := RROResource
LOCAL_SDK_VERSION := current

include $(BUILD_RRO_PACKAGE)

再来看看目标应用的目录结构:
AndroidQ RRO(Runtime Resource Overlay)机制(1)_第4张图片
需要强调的是要想实现overlay,必须满足overlay应用的资源名称与目标应用资源名称完全相同,比如这里我们要overlay的图片ic_launcher_background.png,目标应用运行之后就是这样:

AndroidQ RRO(Runtime Resource Overlay)机制(1)_第5张图片

接着编译overlay应用,编好之后将其push到设备/system/product/overlay/中,重启之后输入命令adb shell dumpsys overlay可以查询设备中overlay包的详细信息:
AndroidQ RRO(Runtime Resource Overlay)机制(1)_第6张图片
目前我这个overlay包状态是Disable的,我们输入命令adb shell cmd overlay enable com.caic.car.rroresource,此时再dump,overlay包状态已经被enable了:
AndroidQ RRO(Runtime Resource Overlay)机制(1)_第7张图片
再看我们的目标应用,资源已经被换掉了:
AndroidQ RRO(Runtime Resource Overlay)机制(1)_第8张图片

我们就这样简单的实现了在不修改三方应用源码的情况下替换它的资源,后续文章我们再来分析RRO的相关原理与细节。

你可能感兴趣的:(Android,RRO机制,android)