Ein Laufzeit-Ressourcen-Overlay (RRO) ist ein Paket, das die Ressourcenwerte eines Zielpakets zur Laufzeit ändert. So kann beispielsweise das Verhalten einer App, die auf dem System-Image installiert ist, je nach Wert einer Ressource variieren. Anstatt den Ressourcenwert zur Buildzeit hartzucodieren, kann ein auf einer anderen Partition installiertes RRO die Werte der App-Ressourcen zur Laufzeit ändern.
RROs können aktiviert oder deaktiviert werden. Sie können den Status „Aktivieren“/„Deaktivieren“ programmatisch festlegen, um die Möglichkeit eines RRO, Ressourcenwerte zu ändern, zu aktivieren oder zu deaktivieren. RROs sind standardmäßig deaktiviert. Statische RROs sind jedoch standardmäßig aktiviert.
Overlay-Ressourcen
Bei Overlays werden Ressourcen, die im Overlay-Paket definiert sind, Ressourcen im Zielpaket zugeordnet. Wenn eine App versucht, den Wert einer Ressource im Zielpaket aufzulösen, wird stattdessen der Wert der Overlay-Ressource zurückgegeben, der der Zielressource zugeordnet ist.
Manifest einrichten
Ein Paket gilt als RRO-Paket, wenn es ein <overlay>
-Tag als untergeordnetes Element des <manifest>
-Tags enthält.
Der Wert des erforderlichen Attributs
android:targetPackage
gibt den Namen des Pakets an, das das RRO überlagern soll.Der Wert des optionalen Attributs
android:targetName
gibt den Namen der überlagerbaren Teilmenge der Ressourcen des Zielpakets an, die die RRO überlagern soll. Wenn für das Ziel keine überlagerbaren Ressourcen definiert sind, sollte dieses Attribut nicht vorhanden sein.
Der folgende Code zeigt ein Beispiel für ein AndroidManifest.xml
-Overlay.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:targetName="OverlayableResources"/>
</manifest>
Overlays können keinen Code überlagern und dürfen daher keine DEX-Dateien enthalten. Außerdem muss das android:hasCode
-Attribut des <application
>-Tags im Manifest auf false
gesetzt sein.
Ressourcenkarte definieren
Unter Android 11 oder höher wird empfohlen, zum Definieren der Overlay-Ressourcenzuordnung eine Datei im Verzeichnis res/xml
des Overlay-Pakets zu erstellen, die Zielressourcen aufzulisten, die überlagert werden sollen, und ihre Ersatzwerte anzugeben. Legen Sie dann den Wert des Attributs android:resourcesMap
des Manifest-Tags <overlay>
auf eine Referenz auf die Ressourcenzuordnungsdatei fest.
Der folgende Code zeigt eine res/xml/overlays.xml
-Beispieldatei.
<?xml version="1.0" encoding="utf-8"?>
<overlay xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- Overlays string/config1 and string/config2 with the same resource. -->
<item target="string/config1" value="@string/overlay1" />
<item target="string/config2" value="@string/overlay1" />
<!-- Overlays string/config3 with the string "yes". -->
<item target="string/config3" value="@android:string/yes" />
<!-- Overlays string/config4 with the string "Hardcoded string". -->
<item target="string/config4" value="Hardcoded string" />
<!-- Overlays integer/config5 with the integer "42". -->
<item target="integer/config5" value="42" />
</overlay>
Der folgende Code zeigt ein Beispiel für ein Overlay-Manifest.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:targetName="OverlayableResources"
android:resourcesMap="@xml/overlays"/>
</manifest>
Paket erstellen
Android 11 oder höher unterstützt eine Soong-Build-Regel für Overlays, die verhindert, dass das Android Asset Packaging Tool 2 (AAPT2) versucht, Konfigurationen von Ressourcen mit demselben Wert zu entfernen (--no-resource-deduping
) und Ressourcen ohne Standardkonfigurationen zu entfernen (--no-resource-removal
). Der folgende Code zeigt eine BeispielAndroid.bp
-Datei.
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
Ressourcen auflösen
Wenn für eine Ziel- oder Overlay-Ressource mehrere Konfigurationen für die abgefragte Ressource definiert sind, gibt die Ressourcenlaufzeit den Wert der Konfiguration zurück, die am besten zur Gerätekonfiguration passt. Um zu ermitteln, welche Konfiguration am besten passt, müssen Sie die Overlay-Ressourcenkonfigurationen mit den Zielressourcenkonfigurationen zusammenführen und dann den normalen Ablauf zur Ressourcenauflösung ausführen. Weitere Informationen finden Sie unter So ermittelt Android die am besten passende Ressource.
Wenn beispielsweise ein Overlay einen Wert für die drawable-en
-Konfiguration und das Ziel einen Wert für drawable-en-port
definiert, ist drawable-en-port
besser geeignet. Daher wird zur Laufzeit der Wert der Zielkonfiguration drawable-en-port
ausgewählt. Damit alle drawable-en
-Konfigurationen überlagert werden, muss das Overlay einen Wert für jede drawable-en
-Konfiguration definieren, die das Ziel definiert.
Overlays können auf eigene Ressourcen verweisen, wobei sich das Verhalten zwischen Android-Releases unterscheiden kann.
Unter Android 11 oder höher hat jedes Overlay einen eigenen reservierten Ressourcen-ID-Bereich, der sich nicht mit dem Ziel-Ressourcen-ID-Bereich oder anderen Overlay-Ressourcen-ID-Bereichen überschneidet. Overlays, die auf ihre eigenen Ressourcen verweisen, funktionieren daher wie erwartet.
Unter Android 10 oder niedriger teilen sich Overlays und Zielpakete denselben Ressourcen-ID-Bereich. Dies kann zu Kollisionen und unerwartetem Verhalten führen, wenn versucht wird, mithilfe der
@type/name
-Syntax auf eigene Ressourcen zu verweisen.
Overlays aktivieren/deaktivieren
Overlays können manuell und programmgesteuert aktiviert oder deaktiviert werden.
Overlays manuell deaktivieren oder aktivieren
So aktivieren und prüfen Sie eine RRO manuell:
adb shell cmd overlay enable --user current com.example.carrro
adb shell cmd overlay list --user current | grep -i com.example com.example.carrro
Dadurch wird die RRO für den Systemnutzer (userId = 0
) aktiviert, der der Eigentümer der SystemUI ist.
Diese Anleitung gilt nicht für Apps, die vom Nutzer im Vordergrund (userId = 10
) gestartet werden. Wenn Sie die RRO für den Nutzer im Vordergrund aktivieren möchten, verwenden Sie den Parameter -–user 10
:
adb shell cmd overlay enable --user 10 com.example.carrro
Overlays programmatisch aktivieren oder deaktivieren
Mit der OverlayManager
API können Sie veränderbare Overlays aktivieren und deaktivieren. Rufen Sie dazu die API-Oberfläche mit Context#getSystemService(Context.OVERLAY_SERVICE)
ab. Ein Overlay kann nur vom Paket aktiviert werden, auf das es ausgerichtet ist, oder von einem Paket mit der Berechtigung android.permission.CHANGE_OVERLAY_PACKAGES
. Wenn ein Overlay aktiviert oder deaktiviert wird, werden Ereignisse zu Konfigurationsänderungen an das Zielpaket weitergegeben und die Zielaktivitäten werden neu gestartet.
Überlagerbare Ressourcen einschränken
Unter Android 10 oder höher gibt das XML-Tag <overlayable>
eine Reihe von Ressourcen an, die von RROs überlagert werden dürfen. In der folgenden Beispielres/values/overlayable.xml
-Datei sind string/foo
und integer/bar
Ressourcen, die für die Gestaltung des Erscheinungsbildes des Geräts verwendet werden. Um diese Ressourcen zu überlagern, muss ein Overlay explizit auf die Sammlung der überlagerbaren Ressourcen nach Namen ausgerichtet sein.
<!-- 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>
Ein APK kann mehrere <overlayable>
-Tags definieren. Jedes Tag muss jedoch einen eindeutigen Namen innerhalb des Pakets haben. Beispiele:
Es ist zulässig, dass
<overlayable name="foo">
in zwei verschiedenen Paketen definiert wird.Ein einzelnes APK darf nicht zwei
<overlayable name="foo">
-Blöcke enthalten.
Der folgende Code zeigt ein Beispiel für ein Overlay in der AndroidManifest.xml
-Datei.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.theme.overlay">
<application android:hasCode="false" />
<!-- This overlay will override the ThemeResources resources -->
<overlay android:targetPackage="android" android:targetName="ThemeResources">
</manifest>
Wenn eine App ein <overlayable>
-Tag definiert, gelten für Overlays, die auf diese App ausgerichtet sind, folgende Einschränkungen:
Muss
targetName
angeben.Es können nur die im
<overlayable>
-Tag aufgeführten Ressourcen überlagert werden.Es kann nur auf einen
<overlayable>
-Namen ausgerichtet werden.
Sie können kein Overlay für ein Paket aktivieren, das überlagerbare Ressourcen bereitstellt, aber nicht android:targetName
verwendet, um die Ausrichtung auf ein bestimmtes <overlayable>
-Tag vorzunehmen.
Richtlinien einschränken
Verwenden Sie das Tag <policy>
, um Einschränkungen für überlagerbare Ressourcen zu erzwingen. Mit dem Attribut type
wird angegeben, welche Richtlinien ein Overlay erfüllen muss, um die enthaltenen Ressourcen zu überschreiben. Zu den unterstützten Typen gehören:
public
. Jedes Overlay kann die Ressource überschreiben.system
. Jedes Overlay auf der Systempartition kann die Ressourcen überschreiben.vendor
. Jedes Overlay auf der Anbieterpartition kann die Ressourcen überschreiben.product
. Jedes Overlay auf der Produktpartition kann die Ressourcen überschreiben.oem
. Jedes Overlay auf der OEM-Partition kann die Ressourcen überschreiben.odm
. Jedes Overlay auf der ODM-Partition kann die Ressourcen überschreiben.signature
. Jedes Overlay, das mit derselben Signatur wie das Ziel-APK signiert ist, kann die Ressourcen überschreiben.actor
: Jedes Overlay, das mit derselben Signatur wie das Actor-APK signiert ist, kann die Ressourcen überschreiben. Der Akteur wird im Tag named-actor in der Systemkonfiguration deklariert.config_signature
. Jedes Overlay, das mit derselben Signatur wie die overlay-config-APK signiert ist, kann die Ressourcen überschreiben. Die Overlay-Konfiguration wird in der Systemkonfiguration im Tag overlay-config-signature deklariert.
Der folgende Code zeigt ein Beispiel für ein <policy>
-Tag in der Datei res/values/overlayable.xml
.
<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>
Wenn Sie mehrere Richtlinien angeben möchten, verwenden Sie vertikale Striche (|) als Trennzeichen.
Wenn mehrere Richtlinien angegeben sind, muss ein Overlay nur eine Richtlinie erfüllen, um die im <policy>
-Tag aufgeführten Ressourcen zu überschreiben.
Overlays konfigurieren
Android unterstützt je nach Android-Release-Version verschiedene Mechanismen zur Konfiguration der Mutabilität, des Standardstatus und der Priorität von Overlays.
Auf Geräten mit Android 11 oder höher kann anstelle von Manifestattributen eine
OverlayConfig
-Datei (config.xml
) verwendet werden. Die Verwendung einer Overlaydatei wird für Overlays empfohlen.Auf allen Geräten können Manifestattribute (
android:isStatic
undandroid:priority
) verwendet werden, um statische RROs zu konfigurieren.
OverlayConfig verwenden
Unter Android 11 oder höher können Sie mit OverlayConfig
die Mutabilität, den Standardstatus und die Priorität von Overlays konfigurieren. Wenn Sie ein Overlay konfigurieren möchten, erstellen oder ändern Sie die Datei unter partition/overlay/config/config.xml
. Dabei ist partition
die Partition des zu konfigurierenden Overlays. Damit ein Overlay konfiguriert werden kann, muss es sich im Verzeichnis overlay/
der Partition befinden, in der es konfiguriert ist. Der folgende Code zeigt ein Beispiel für product/overlay/config/config.xml
.
<config>
<merge path="OEM-common-rros-config.xml" />
<overlay package="com.oem.overlay.device" mutable="false" enabled="true" />
<overlay package="com.oem.green.theme" enabled="true" />
</config>"
Für das <overlay>
-Tag ist ein package
-Attribut erforderlich, das angibt, welches Overlay-Paket konfiguriert wird. Mit dem optionalen Attribut enabled
wird festgelegt, ob das Overlay standardmäßig aktiviert ist (Standardwert: false
). Mit dem optionalen Attribut mutable
wird festgelegt, ob das Overlay änderbar ist und sein aktivierter Status während der Laufzeit programmatisch geändert werden kann (Standardwert: true
). Overlays, die nicht in einer Konfigurationsdatei aufgeführt sind, sind änderbar und standardmäßig deaktiviert.
Overlay-Vorrang
Wenn mehrere Overlays dieselben Ressourcen überschreiben, ist die Reihenfolge der Overlays wichtig. Ein Overlay hat eine höhere Priorität als Overlays mit Konfigurationen, die vor seiner eigenen Konfiguration liegen. Die Prioritätsreihenfolge von Overlays in verschiedenen Partitionen (von der niedrigsten zur höchsten Priorität) ist die folgende.
system
vendor
odm
oem
product
system_ext
Dateien zusammenführen
Mithilfe von <merge>
-Tags können andere Konfigurationsdateien an der angegebenen Position in die Konfigurationsdatei zusammengeführt werden. Das Attribut path
des Tags entspricht dem Pfad der Datei, die zusammengeführt werden soll, relativ zum Verzeichnis mit den Overlay-Konfigurationsdateien.
Manifest-Attribute/statische RROs verwenden
Unter Android 10 oder niedriger werden die Unveränderlichkeit und die Priorität von Overlays mit den folgenden Manifest-Attributen konfiguriert.
android:isStatic
. Wenn der Wert dieses booleschen Attributs auftrue
gesetzt ist, ist das Overlay standardmäßig aktiviert und unveränderlich. Das verhindert, dass das Overlay deaktiviert wird.android:priority
. Mit dem Wert dieses numerischen Attributs (das sich nur auf statische Overlays auswirkt) wird die Priorität des Overlays konfiguriert, wenn mehrere statische Overlays auf denselben Ressourcenwert ausgerichtet sind. Je höher die Zahl, desto höher die Priorität.
Der folgende Code zeigt ein Beispiel für AndroidManifest.xml
.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.overlay">
<application android:hasCode="false" />
<overlay android:targetPackage="com.example.target"
android:isStatic="true"
android:priority="5"/>
</manifest>
Änderungen in Android 11
Wenn sich unter Android 11 oder höher eine Konfigurationsdatei in partition/overlay/config/config.xml
befindet, werden Overlays mit dieser Datei konfiguriert. android:isStatic
und android:priority
haben dann keine Auswirkungen auf Overlays in der Partition. Wenn Sie eine Overlay-Konfigurationsdatei in einer beliebigen Partition definieren, wird die Vorrangstellung der Overlay-Partition erzwungen.
Außerdem können unter Android 11 oder höher keine statischen Overlays mehr verwendet werden, um die Werte von Ressourcen zu beeinflussen, die während der Paketinstallation gelesen werden. Für den häufigen Anwendungsfall, bei dem mithilfe von statischen Overlays der Wert von Booleschen Werten geändert wird, die den aktivierten Status der Komponente konfigurieren, verwenden Sie das Tag <component-override>
SystemConfig
(neu in Android 11).
Debug-Overlays
Verwenden Sie den folgenden Overlay-Manager-Shell-Befehl, um Overlays manuell zu aktivieren, zu deaktivieren und zu dumpen.
adb shell cmd overlay
Wenn Sie enable
verwenden, ohne einen Nutzer anzugeben, wirkt sich das auf den aktuellen Nutzer aus, also den Systemnutzer (userId = 0
), dem die System-UI gehört. Dies hat keine Auswirkungen auf den Nutzer im Vordergrund (userId = 10
), dem die Apps gehören. Verwenden Sie den Parameter –-user 10
, um die RRO für den Nutzer im Vordergrund zu aktivieren:
adb shell cmd overlay enable --user 10 com.example.carrro
In OverlayManagerService
werden mit idmap2
Ressourcen-IDs im Zielpaket Ressourcen-IDs im Overlay-Paket zugeordnet. Die generierten ID-Zuordnungen werden in /data/resource-cache/
gespeichert. Wenn das Overlay nicht richtig funktioniert, suchen Sie in /data/resource-cache/
nach der entsprechenden idmap
-Datei für das Overlay und führen Sie dann den folgenden Befehl aus.
adb shell idmap2 dump --idmap-path [file]
Dieser Befehl gibt die Zuordnung der Ressourcen wie unten dargestellt aus.
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType