在 Android 10 及更高版本中,您可以使用 Android 资源打包工具 2 (AAPT2) 定义 APK 允许运行时资源叠加层 (RRO) 在运行时叠加哪些资源。
实现 RRO
Android 10 引入了一个新的 <overlayable> XML 标记,用于收集应该在一个共同的名称下叠加在一起的资源。在下面的示例中,string/foo
和 integer/bar
是用于为设备的外观设置主题背景的资源。如需叠加这些资源,叠加层必须根据名称明确定位到可叠加资源的集合。
一个 APK 可以定义多个 <overlayable> 标记,但每个标记必须在该软件包中具有唯一的名称。例如:
两个不同的软件包可以同时定义 <overlayable name="foo">。
一个 APK 不能具有两个 <overlayable name="foo"> 块。
res/values/overlayable.xml
文件示例:
<!-- The collection of resources for theming the appearance of the device -->
<overlayable name=”ThemeResources”>
<policy type=”public”>
<item type=”string” name=”foo/” />
<item type=”integer” name=”bar/” />
</policy>
...
</overlayable>
AndroidManifest.xml
文件中的叠加层示例:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.theme.overlay">
<!-- This overlay will override the ThemeResources resources -->
<overlay android:targetPackage="android" android:targetName="ThemeResources">
</manifest>
当应用定义 <overlayable> 标记时,定位到该应用的叠加层需满足以下条件:
必须指定“targetName”。
只能叠加该标记中列出的资源。
只能定位到一个 <overlayable> 名称。
如果某个叠加层定位到的软件包提供可叠加资源但不使用 android:targetName
定位到特定的 <overlayable> 标记,则无法启用该叠加层。
限制政策
<policy> 标记可以对可叠加资源施加限制。type
属性指定叠加层必须满足哪些政策的要求才能替换包含的资源。支持的类型包括:
public
- 任何叠加层均可替换相应资源system
- 系统分区上的任何叠加层均可替换相应资源vendor
- 供应商分区上的任何叠加层均可替换相应资源product
- 产品分区上的任何叠加层均可替换相应资源signature
- 与目标 APK 使用同一签名进行签名的任何叠加层均可替换相应资源
res/values/overlayable.xml
文件中的 <policy> 标记示例:
<overlayable name=”ThemeResources”>
<policy type=“product” >
<item type=”string” name=”foo” />
</policy>
<policy type=“system|signature” >
<item type=”string” name=”bar” />
<item type=”string” name=”baz” />
</policy>
</overlayable>
如需指定多个政策,请使用竖线 (|) 作为分隔符。 如果指定了多个政策,叠加层只需满足一个政策的要求即可替换 <policy> 标记中列出的资源。
管理 RRO
如需启用、停用叠加层或对其重新排序,您必须具有
CHANGE_OVERLAY_PACKAGES
权限。如需为当前用户以外的用户启用叠加层,您必须具有
INTERACT_ACROSS_USERS
权限。
合规性
对于给定的 SDK 级别,框架中资源的可叠加声明必须在所有 Android 设备之间保持一致。所有添加、移除、政策更改以及会影响框架资源的可叠加定义的其他任何更改都必须合并到 AOSP 中,才能在所有 Android 设备之间实现一致性。CTS 测试强制要求 Android 框架的可叠加 API 不得偏离在 AOSP 中定义的可叠加定义。
安装 RRO
在 Android 9 及更低版本中,叠加层必须预安装或使用平台签名进行签名,才能由 PackageManagerService
安装。Android 9 设备上的 Android 9 叠加层在设备升级到 Android 10 后将继续正常运行。
在 Android 10 及更高版本中,可以将未使用平台签名进行签名的叠加层安装到数据分区。如果某个叠加层定位到的软件包未声明可叠加资源,则必须使用与目标软件包相同的签名为该叠加层签名或预安装该叠加层,才能将其启用。
调试
您可以使用以下命令将叠加层和目标应用安装到设备上:
adb install
如需手动启用、停用和转储叠加层,请使用叠加层管理器 shell 命令:
adb shell cmd overlay
OverlayManagerService
使用 idmap
2 将目标软件包中的资源 ID 映射到叠加层软件包中的资源 ID。生成的 ID 映射存储在 /data/resource-cache/
中。
如果叠加层无法正常运行,请在 /data/resource-cache/
中查找叠加层的相应 idmap
文件,然后运行以下命令:
adb shell idmap2 dump --idmap-path [file]
此命令会输出资源的映射:
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType
...
可叠加 XML 架构
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="overlayable">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="policy"/>
</xs:sequence>
<xs:attribute name="actor" type="xs:anyURI"/>
<xs:attribute name="name" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
<xs:element name="policy">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="item"/>
</xs:sequence>
<xs:attribute name="type" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="item">
<xs:complexType>
<xs:attribute name="name" use="required"/>
<xs:attribute name="type" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
</xs:schema>