Ein Runtime Resource Overlay (RRO) ist ein Paket, das die Ressourcenwerte eines Zielpakets zur Laufzeit ändert. Eine im Systemimage installierte App kann beispielsweise ihr Verhalten basierend auf dem Wert einer Ressource ändern. Anstatt den Ressourcenwert zur Build-Zeit fest zu codieren, kann ein RRO, das auf einer anderen Partition installiert ist, die Werte der App-Ressourcen zur Laufzeit ändern.
RROs können aktiviert oder deaktiviert werden. Sie können den Aktivierungs-/Deaktivierungsstatus programmatisch festlegen, um die Möglichkeit eines RRO zum Ändern von Ressourcenwerten zu aktivieren oder zu deaktivieren. RROs sind standardmäßig deaktiviert (statische RROs sind jedoch standardmäßig aktiviert).
Overlay-Ressourcen
Overlays funktionieren, indem Ressourcen, die im Overlay-Paket definiert sind, Ressourcen zugeordnet werden, die im Zielpaket definiert sind. Wenn eine App versucht, den Wert einer Ressource im Zielpaket aufzulösen, wird stattdessen der Wert der Overlay-Ressource zurückgegeben, der die 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 vom RRO überschrieben werden soll.Der Wert des optionalen Attributs
android:targetName
gibt den Namen der überschreibbaren Teilmenge von Ressourcen des Zielpakets an, die das RRO überschreiben soll. Wenn im 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 Attribut android:hasCode
des Tags <application
> im Manifest auf false
gesetzt sein.
Ressourcenübersicht definieren
In Android 11 oder höher wird empfohlen, die Ressourcenübersicht für Overlays zu definieren, indem Sie eine Datei im Verzeichnis res/xml
des Overlay-Pakets erstellen, die Zielressourcen und ihre Ersatzwerte auflistet, und dann den Wert des Attributs android:resourcesMap
des Manifest-Tags <overlay>
auf eine Referenz zur Ressourcenübersichtsdatei festlegen.
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 und 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 (--no-resource-deduping
) zu deduplizieren und Ressourcen ohne Standardkonfigurationen (--no-resource-removal
) zu entfernen. Der folgende Code zeigt ein Beispiel für eine Android.bp
-Datei.
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
Ressourcen auflösen
Wenn für eine Zielressource oder eine Overlay-Ressource mehrere Konfigurationen für die abgefragte Ressource definiert sind, gibt die Ressourcenlaufzeit den Wert der Konfiguration zurück, die am besten mit der Konfiguration der Gerätekonfiguration übereinstimmt. Um zu ermitteln, welche Konfiguration die am besten passende ist, führen Sie die Overlay-Ressourcenkonfigurationen mit den Zielressourcenkonfigurationen zusammen und folgen Sie dann dem regulären Ressourcenauflösungsprozess (weitere Informationen finden Sie unter So findet Android die am besten passende Ressource).
Wenn in einem Overlay beispielsweise ein Wert für die Konfiguration drawable-en
und im Ziel ein Wert für drawable-en-port
definiert ist, ist drawable-en-port
eine bessere Übereinstimmung. Daher wird zur Laufzeit der Wert der Zielkonfiguration drawable-en-port
ausgewählt. Wenn alle drawable-en
-Konfigurationen überlagert werden sollen, muss im Overlay ein Wert für jede drawable-en
-Konfiguration definiert werden, die im Ziel definiert ist.
Overlays können auf eigene Ressourcen verweisen. Das Verhalten kann sich jedoch zwischen Android-Versionen unterscheiden.
In Android 11 oder höher hat jedes Overlay einen eigenen reservierten Ressourcen-ID-Bereich, der sich nicht mit dem Zielressourcen-ID-Bereich oder anderen Overlay-Ressourcen-ID-Bereichen überschneidet. Overlays, die auf eigene Ressourcen verweisen, funktionieren also wie erwartet.
In Android 10 oder niedriger teilen sich Overlays und Zielpakete denselben Ressourcen-ID-Bereich. Dies kann zu Konflikten und unerwartetem Verhalten führen, wenn sie versuchen, mit der
@type/name
-Syntax auf eigene Ressourcen zu verweisen.
Overlays aktivieren/deaktivieren
Overlays können manuell und programmatisch aktiviert/deaktiviert werden.
Overlays manuell deaktivieren oder aktivieren
So aktivieren und prüfen Sie ein 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 das RRO für den Systemnutzer (userId = 0
) aktiviert, der SystemUI gehört.
Diese Anleitung wirkt sich nicht auf Apps aus, die vom Vordergrundnutzer (userId = 10
) gestartet werden. Wenn Sie das RRO für den Vordergrundnutzer aktivieren möchten, verwenden Sie den Parameter -–user 10
:
adb shell cmd overlay enable --user 10 com.example.carrro
Overlays programmatisch aktivieren oder deaktivieren
Verwenden Sie die OverlayManager
API, um veränderbare Overlays zu aktivieren und zu deaktivieren (rufen Sie die API-Schnittstelle mit Context#getSystemService(Context.OVERLAY_SERVICE)
ab). Ein Overlay kann nur von dem 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 Konfigurationsänderungsereignisse an das Zielpaket weitergegeben und die Zielaktivitäten werden neu gestartet.
Überlagerbare Ressourcen einschränken
In Android 10 oder höher macht das XML-Tag <overlayable>
eine Reihe von Ressourcen verfügbar, die von RROs überschrieben werden dürfen. In der folgenden Beispieldatei res/values/overlayable.xml
sind string/foo
und integer/bar
Ressourcen, die zum Anpassen des Erscheinungsbilds 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>
In einem APK können mehrere <overlayable>
-Tags definiert werden, aber jedes Tag muss innerhalb des Pakets einen eindeutigen Namen haben. Beispiel:
Es ist in Ordnung, wenn
<overlayable name="foo">
in zwei verschiedenen Paketen definiert wird.Es ist nicht zulässig, dass ein einzelnes APK zwei
<overlayable name="foo">
-Blöcke enthält.
Der folgende Code zeigt ein Beispiel für ein Overlay in der Datei AndroidManifest.xml
.
<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 in einer App ein <overlayable>
-Tag definiert ist, werden Overlays, die auf diese App ausgerichtet sind:
targetName
muss angegeben werden.Es können nur die Ressourcen überlagert werden, die im
<overlayable>
-Tag aufgeführt sind.Kann nur auf einen
<overlayable>
-Namen ausgerichtet werden.
Sie können kein Overlay aktivieren, das auf ein Paket ausgerichtet ist, in dem überlagerbare Ressourcen verfügbar sind, aber nicht android:targetName
verwendet wird, um auf ein bestimmtes <overlayable>
-Tag auszurichten.
Einschränkungsrichtlinien
Verwenden Sie das Tag <policy>
, um Einschränkungen für Ressourcen zu erzwingen, die überlagert werden können. Mit dem Attribut type
wird angegeben, welche Richtlinien ein Overlay erfüllen muss, um die enthaltenen Ressourcen zu überschreiben. Folgende Typen werden unterstützt.
public
. Jedes Overlay kann die Ressource überschreiben.system
. Alle Overlays auf der Systempartition können die Ressourcen überschreiben.vendor
. Alle Overlays in der Anbieterpartition können die Ressourcen überschreiben.product
. Jedes Overlay für die Produktpartition kann die Ressourcen überschreiben.oem
. Alle Overlays in der OEM-Partition können die Ressourcen überschreiben.odm
. Alle Overlays auf der ODM-Partition können die Ressourcen überschreiben.signature
. Alle Overlays, die mit derselben Signatur wie das Ziel-APK signiert sind, können die Ressourcen überschreiben.actor
. Alle Overlays, die mit derselben Signatur wie das Actor-APK signiert sind, können die Ressourcen überschreiben. Der Akteur wird im Tag named-actor in der Systemkonfiguration deklariert.config_signature
. Alle Overlays, die mit derselben Signatur wie das APK overlay-config signiert sind, können die Ressourcen überschreiben. Die Overlay-Konfiguration wird im Tag overlay-config-signature in der Systemkonfiguration 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 senkrechte 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-Version verschiedene Mechanismen zum Konfigurieren der Unveränderlichkeit, 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 Overlay-Datei ist die empfohlene Methode für Overlays.Alle Geräte können Manifestattribute (
android:isStatic
undandroid:priority
) verwenden, um statische RROs zu konfigurieren.
„OverlayConfig“ verwenden
In Android 11 oder höher können Sie OverlayConfig
verwenden, um die Unveränderlichkeit, den Standardstatus und die Priorität von Overlays zu konfigurieren. Um ein Overlay zu konfigurieren, erstellen oder ändern Sie die Datei unter partition/overlay/config/config.xml
, wobei partition
die Partition des zu konfigurierenden Overlays ist. Damit ein Overlay konfiguriert werden kann, muss es sich im Verzeichnis overlay/
der Partition befinden, in der das Overlay konfiguriert wird. 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 gesteuert, ob das Overlay standardmäßig aktiviert ist (Standardwert ist false
). Mit dem optionalen Attribut mutable
wird gesteuert, ob das Overlay geändert werden kann und sein aktivierter Status zur Laufzeit programmatisch geändert werden kann (Standardwert ist true
). Overlays, die nicht in einer Konfigurationsdatei aufgeführt sind, sind standardmäßig änderbar und 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 seiner eigenen Konfiguration vorangehen. Die Prioritätsreihenfolge von Overlays in verschiedenen Partitionen (von der niedrigsten zur höchsten Priorität) ist wie folgt:
system
vendor
odm
oem
product
system_ext
Dateien zusammenführen
Mit <merge>
-Tags können andere Konfigurationsdateien an der angegebenen Position in die Konfigurationsdatei eingefügt werden. Das Attribut path
des Tags stellt den Pfad der Datei dar, die relativ zum Verzeichnis mit den Overlay-Konfigurationsdateien zusammengeführt werden soll.
Manifestattribute/statische RROs verwenden
In Android 10 oder niedriger werden die Unveränderlichkeit und die Priorität von Overlays mit den folgenden Manifestattributen konfiguriert.
android:isStatic
: Wenn der Wert dieses booleschen Attributs auftrue
gesetzt ist, wird das Overlay standardmäßig aktiviert und ist unveränderlich. Das Deaktivieren des Overlays ist dann nicht möglich.android:priority
: Der Wert dieses numerischen Attributs (das sich nur auf statische Overlays auswirkt) konfiguriert die Priorität des Overlays, wenn mehrere statische Overlays auf denselben Ressourcenwert ausgerichtet sind. Eine höhere Zahl bedeutet eine höhere 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 in 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 keine Auswirkungen auf Overlays, die sich in der Partition befinden. Wenn Sie eine Overlay-Konfigurationsdatei in einer Partition definieren, wird die Priorität der Overlay-Partition erzwungen.
Außerdem wird in Android 11 und höher die Möglichkeit entfernt, statische Overlays zu verwenden, um die Werte von Ressourcen zu beeinflussen, die während der Paketinstallation gelesen werden. Für den häufigen Anwendungsfall, bei dem statische Overlays verwendet werden, um den Wert von booleschen Werten zu ändern, die den aktivierten Status von Komponenten konfigurieren, verwenden Sie das Tag <component-override>
SystemConfig
(neu in Android 11).
Fehlerbehebungs-Overlays
Verwenden Sie den folgenden Shell-Befehl für den Overlay-Manager, um Overlays manuell zu aktivieren, zu deaktivieren und zu sichern.
adb shell cmd overlay
Wenn Sie enable
verwenden, ohne einen Nutzer anzugeben, wirkt sich das auf den aktuellen Nutzer aus, d. h. auf den Systemnutzer (userId = 0
), der die System-UI besitzt. Dies hat keine Auswirkungen auf den Vordergrundnutzer (userId = 10
), dem die Apps gehören. Verwenden Sie den Parameter –-user 10
, um die RRO für den Vordergrundnutzer zu aktivieren:
adb shell cmd overlay enable --user 10 com.example.carrro
OverlayManagerService
verwendet idmap2
, um Ressourcen-IDs im Zielpaket Ressourcen-IDs im Overlay-Paket zuzuordnen. Die generierten ID-Zuweisungen werden in /data/resource-cache/
gespeichert. Wenn Ihr Overlay nicht richtig funktioniert, suchen Sie in /data/resource-cache/
nach der entsprechenden idmap
-Datei für Ihr Overlay und führen Sie dann den folgenden Befehl aus.
adb shell idmap2 dump --idmap-path [file]
Mit diesem Befehl wird die Zuordnung von Ressourcen wie unten dargestellt ausgegeben.
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType