Android 运行时资源替换----Runtime Resource Overlay实践

本文介绍了Android的RuntimeResourceOverlay(RRO)机制,用于实现应用的动态换肤。通过创建资源包,配置AndroidManifest.xml,定义资源映射,以及启用/停用RRO的步骤,详细阐述了如何利用RRO替换目标应用的颜色值等资源,实现主题切换。此外,提到了在不同Android版本中的实践差异和限制策略。
摘要由CSDN通过智能技术生成

转载自 【车载 Android】应用换肤方案(一) - Runtime Resource Overlay

Android从M开始加入了动态资源overlay机制 runtime resource overlay(RRO),这个是sony贡献的,实现机制如下图,就是在框架中建立一套资源ID映射表,通过这个映射表动态切换不同的主题。
在这里插入图片描述

RRO 换肤实践

首先准备一个需要被换肤的应用,这里我们随便新建一个APP为例,下面我们将新建的Target App工程称为『目标应用』,目标是利用RRO机制替换目标应用中颜色值。

在这里插入图片描述

第 1 步:创建资源包,配置 AndroidManifest.xml

首先我们要新建一个独立的 app 工程,这个应用存在的意义就是放置『目标应用』的资源文件,下面我们将其称为『资源包』。它虽然是一个应用工程,但是不包含逻辑代码,只能用于存放资源文件。

注意到这一步,我们实际上新建了两个app工程,一个是目标应用,一个是资源包。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.target.overlay.ten">

    <overlay
        android:targetName="ThemeResources"
        android:priority="20"
        android:targetPackage="com.android.target" />

    <application android:hasCode="false"/>

</manifest>

如果某个APK 的AndroidManifest.xml中包含 <overlay> 标记作为 <manifest> 标记的子项,该APK将被视为『资源包』 。

  • 【必需设定】android:targetPackage 用于指明 RRO 想要替换的『目标应用』。
  • 【必需设定】android:hasCode必须设定为 false。由于无法替换代码,因此 RRO 无法使用 DEX 文件。
  • 【非必需设定】android:targetName 用于指明 RRO 『目标应用』的可替换资源子集的名称。如果『目标应用』没有定义可替换资源集,此属性就不需要设定。
可替换资源集

在 Android 10 或更高版本中,『目标应用』可以使用<overlayable> 标签公开一组允许 RRO 替换的资源,未被公开的资源,则不允许 RRO 替换。

<resources>
    <overlayable name="ThemeResources">
        <policy type="public">
            <item type="color" name="purple_200" />
            <item type="color" name="purple_500" />
        </policy>
    </overlayable>
</resources>

一个 APK 可以定义多个 标记,但每个标记必须在该软件包中具有唯一的名称。例如:

  • 两个不同的资源包可以同时定义 。
  • 一个 APK 不能具有两个 块。

然后需要在资源包的AndroidManifest.xml中使用targetName指定ThemeResources。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.target.overlay.ten">

    <overlay
        android:targetName="ThemeResources"
        android:targetPackage="com.android.target" />

    <application android:hasCode="false"/>

</manifest>

当目标应用定义 <overlayable> 标记时,资源包的<overlay>需满足以下条件:

  • 必须指定 targetName。

  • 只能替换 <overlayable> 标记中列出的资源。

  • 只能定位到一个 <overlayable> 名称。

限制策略

使用<policy>标记可以在目标应用中对可替换资源施加限制。type属性指定叠加层必须满足哪些政策的要求才能替换包含的资源。支持以下类型:

  • public:任何叠加层均可替换相应资源。
  • system:系统分区上的任何叠加层均可替换相应资源。
  • vendor:vendor 分区上的任何叠加层均可替换相应资源。
  • product:product 分区上的任何叠加层均可替换相应资源。
  • signature:使用与目标 APK 相同的签名进行签名的任何叠加层均可替换相应资源。
<overlayable name="ThemeResources">
   <policy type="vendor" >
       <item type="string" name="foo" />
   </policy>
   <policy type="product|signature"  >
       <item type="string" name="bar" />
       <item type="string" name="baz" />
   </policy>
</overlayable>

如需指定多个政策,请使用竖线 (|) 作为分隔符。 如果指定了多个政策,叠加层只需满足一个政策的要求即可替换 <policy> 标记中列出的资源。

第 2 步:定义资源映射

  • Android 10或以下版本
    在 Android 10 或更低版本中,系统是根据资源的名称进行资源替换,所以我们只需要在资源包中将需要替换的资源定义好即可。

在这里插入图片描述

  • Android 11或以上版本
    在 Android 11 或更高版本中,Google推荐在『资源包』的res/xml 目录中创建一个文件overlays.xml,枚举出应覆盖的『目标应用』的资源值及其替换值。
<?xml version="1.0" encoding="utf-8"?>
<overlay xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 更换颜色 -->
    <item target="color/purple_200" value="#000000"/>
    <item target="color/purple_500" value="#000000"/>
    <item target="color/purple_700" value="#000000"/>
    <item target="color/teal_200" value="#000000"/>
    <item target="color/teal_700" value="#000000"/>
    <item target="color/black" value="#000000"/>
    <item target="color/white" value="#000000"/>
</overlay>

注意,target标签中的color并没有带上@标记,他实际上仅仅是一个字符串而不是引用

然后在资源包的AndroidManifest.xml 中将android:resourcesMap 属性的值设置为资源映射文件。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.target.overlay.eleven">

    <overlay
        android:targetName="ThemeResources"
        android:targetPackage="com.android.target"
        android:resourcesMap="@xml/overlays"/>

    <application
        android:hasCode="false"/>

</manifest>

第 3 步:构建资源包

构建出的资源包,我们在调试时,可以使用Android Studio直接安装,如下所示。

  1. 运行目标应用和资源包
  2. 在data/app 目录上右键,选择 “Synchronize” 选项

以上两步之后data/app目录下会多出两个路径,分别代表目标应用和资源包的apk。

正式发布时,『资源包』可以发布到vendor/overlay目录下,『目标应用』则可以根据需要可以灵活放置。之后重启Android系统即可。

第 4 步:启用/停用 RRO

使用OverlayManager提供的API可以启用、停用RRO。OverlayManager在公开的Android SDK中并没有提供,如果是使用Gradle构建工程,需要额外使用AOSP源码编译一个framework.jar并引入才可以使用,同时应用签名也需要使用Android系统签名,让应用成为系统级应用。

OverlayManager manager = MainActivity.this.getSystemService(OverlayManager.class);
OverlayInfo overlayInfo = manager.getOverlayInfo("com.android.target.overlay.ten", UserHandle.CURRENT_OR_SELF);
manager.setEnabled("com.android.target.overlay.ten", !overlayInfo.isEnabled(), UserHandle.CURRENT_OR_SELF);

在启用或停用RRO后,配置更改事件会传播到目标应用,并且目标应用的 activity 会重新启动。

如果要在手机端测试,可以使用adb命令来开启、关闭RRO

adb shell cmd overlay enable [com.android.target.overlay.ten] // 开启
adb shell cmd overlay disable [com.android.target.overlay.ten] // 关闭

Demo

官方文档

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值