Laufzeitressourcen-Overlays (RROs)

Ein Runtime Resource Overlay (RRO) ist ein Paket, das die Ressourcenwerte eines Zielpakets zur Laufzeit ändert. Beispielsweise kann eine auf dem Systemabbild installierte App ihr Verhalten basierend auf dem Wert einer Ressource ändern. Anstatt den Ressourcenwert zur Buildzeit fest zu codieren, kann eine auf einer anderen Partition installierte RRO die Werte der App-Ressourcen zur Laufzeit ändern.

RROs können aktiviert oder deaktiviert werden. Sie können den Aktivierungs-/Deaktivierungsstatus programmgesteuert festlegen, um die Fähigkeit eines RROs umzuschalten, Ressourcenwerte zu ändern. RROs sind standardmäßig deaktiviert (jedoch statische RROs standardmäßig aktiviert werden).

Überlagernde Ressourcen

Overlays funktionieren, indem sie Ressourcen, die im Overlay-Paket definiert sind, Ressourcen zuordnen, 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 ist ein RRO Paket betrachtet , wenn sie eine enthält <overlay> Tag als Kind des <manifest> -Tag.

  • Der Wert der erforderlichen android:targetPackage gibt an Attribut der Name des Pakets beabsichtigt die RRO zu Overlay.

  • Der Wert der optionalen android:targetName Attribut gibt den Namen des overlayable Teilmenge der Ressourcen des Zielpaket zu überlagern die RRO beabsichtigt. Wenn das Ziel keinen überlagerbaren Ressourcensatz definiert, sollte dieses Attribut nicht vorhanden sein.

Der folgende Code zeigt ein Beispiel Overlay 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:targetName="OverlayableResources"/>
</manifest>

Overlays können keinen Code überlagern, daher können sie keine DEX-Dateien enthalten. Darüber hinaus ist das android:hasCode - <application false android:hasCode Attribut der <application > -Tag im Manifest muss eingestellt werden false .

Definieren der Ressourcenkarte

In Android 11 oder höher, ist die Overlay - Ressourcen Karte für die Definition der empfohlenen Mechanismus eine Datei im erstellen res/xml - Verzeichnis des Overlay - Paket, um die Zielressourcen aufzuzählen , die überlagerte und deren Ersatzwerte angezeigt werden sollten, um den Wert des Satzes android:resourcesMap Attribut des <overlay> manifest - Tag zu einem Verweis auf die Ressource - Zuordnungsdatei.

Der folgende Code zeigt ein Beispiel res/xml/overlays.xml Datei.

<?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 aufbauen

Android 11 oder höher unterstützt eine Soong Erstellungsregel für Overlays , dass verhindert Android Asset - Packaging Tool 2 (AAPT2) von dem Versuch zu dedupe Konfigurationen von Ressourcen mit dem gleichen Wert ( --no-resource-deduping ) und von Ressourcen ohne Standardkonfigurationen zu entfernen ( --no-resource-removal ). Der folgende Code zeigt ein Beispiel Android.bp Datei.

runtime_resource_overlay {
    name: "ExampleOverlay",
    sdk_version: "current",
}

Auflösen von Ressourcen

Wenn für eine Zielressource oder Overlay-Ressource mehrere Konfigurationen für die abgefragte Ressource definiert sind, gibt die Ressourcenlaufzeit den Wert der Konfiguration zurück, die der Konfiguration der Gerätekonfiguration am besten entspricht. Die Konfiguration ist die am besten passende Konfiguration, fusionieren die Menge der Overlay - Resource - Konfigurationen in den Satz von Ziel - Ressource - Konfigurationen und folgen Sie dann den regulären Ressourcen Auflösung Fluss zu bestimmen (Einzelheiten finden Sie unter Wie Android findet die am besten passende Ressource ).

Wenn beispielsweise eine Überlagerung einen Wert für die definiert drawable-en - Konfiguration und die Soll - Wert für definiert drawable-en-port , drawable-en-port hat eine bessere Übereinstimmung damit der Wert der Zielkonfiguration drawable-en-port ist , zur Laufzeit gewählt. Um alle Overlay drawable-en - Konfigurationen, muss die Überlagerung einen Wert für jede definieren drawable-en - Konfiguration der Zielfestlegt.

Overlays können auf ihre eigenen Ressourcen verweisen, mit unterschiedlichem Verhalten zwischen Android-Versionen.

  • In Android 11 oder höher hat jedes Overlay seinen eigenen reservierten Ressourcen-ID-Bereich, der sich nicht über den Zielressourcen-ID-Bereich oder andere Overlay-Ressourcen-ID-Bereiche überschneidet, sodass Overlays, die auf ihre eigenen Ressourcen verweisen, wie erwartet funktionieren.

  • In Android 10 oder niedriger, Overlays und Zielpakete teilen sich die gleiche Ressource ID Raum, der Kollisionen und zu unerwartetem Verhalten führen kann , wenn sie versuchen , ihre eigenen Ressourcen mit der referenzieren @type/name Syntax.

Aktivieren/Deaktivieren von Overlays

Verwenden Sie die OverlayManager API zu aktivieren und deaktivieren wandelbar Overlays (rufen Sie die API - Schnittstelle Context#getSystemService(Context.OVERLAY_SERVICE) ). Ein Overlay kann es nur durch das Paket aktiviert sein , Ziele oder durch ein Paket mit der android.permission.CHANGE_OVERLAY_PACKAGES Erlaubnis. Wenn ein Overlay aktiviert oder deaktiviert wird, werden Konfigurationsänderungsereignisse an das Zielpaket weitergegeben und die Zielaktivitäten werden neu gestartet.

Einschränken von überlagerbaren Ressourcen

In Android 10 oder höher, die <overlayable> XML - Tag stellt eine Reihe von Ressourcen , die RROs zu Overlay erlaubt sind. Im folgende Beispiel res/values/overlayable.xml Datei, string/foo und integer/bar Ressourcen für die Thematisierung des Geräts Aussehen verwendet werden; Um diese Ressourcen zu überlagern, muss ein Overlay explizit auf die Sammlung überlagerbarer Ressourcen nach Namen abzielen.

<!-- 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>

Eine APK können mehrere definieren <overlayable> Tags, aber jeder Tag muss einen eindeutigen Namen innerhalb des Pakets haben. Es ist zum Beispiel:

  • OK für zwei verschiedene Pakete zu definieren beide <overlayable name="foo"> .

  • Nicht OK für eine einzelne APK zwei haben <overlayable name="foo"> Blöcke.

Der folgende Code zeigt ein Beispiel einer 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 eine definiert <overlayable> -Tag, Overlays , die App - Targeting:

  • Muss angeben targetName .

  • Kann überlagern nur die innerhalb der aufgeführten Ressourcen <overlayable> -Tag.

  • Kann nur ein Ziel <overlayable> Namen.

Sie können nicht ein Overlay - Targeting ein Paket aktivieren , die overlayable Ressourcen freigibt, aber nicht verwendet android:targetName ein bestimmtes Ziel <overlayable> -Tag.

Einschränkende Richtlinien

Verwenden Sie die <policy> -Tag zu erzwingen Beschränkungen overlayable Ressourcen. Die type - Attribut legt fest , welche Maßnahmen ein Overlay erfüllen müssen , die darin enthaltenen Ressourcen außer Kraft zu setzen. Folgende Typen werden unterstützt.

  • public . Jedes Overlay kann die Ressource überschreiben.
  • system . Jedes Overlay auf der Systempartition kann die Ressourcen überschreiben.
  • vendor . Jedes Overlay auf der Herstellerpartition kann die Ressourcen überschreiben.
  • product . Jedes Overlay auf der Produktpartition kann die Ressourcen überschreiben.
  • signature . Jedes Overlay, das mit derselben Signatur wie das Ziel-APK signiert ist, kann die Ressourcen überschreiben.

Der folgende Code zeigt ein Beispiel <policy> -Tag in der res/values/overlayable.xml Datei.

<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>

Um mehrere Richtlinien anzugeben, verwenden Sie vertikale Striche (|) als Trennzeichen. Wenn mehrere Richtlinien festgelegt sind, muss eine Überlagerung nur eine Richtlinie erfüllen , die Ressourcen innerhalb der aufgeführten außer Kraft zu setzen <policy> -Tag.

Overlays konfigurieren

Android unterstützt je nach Android-Version verschiedene Mechanismen zum Konfigurieren der Veränderlichkeit, des Standardzustands und der Priorität von Overlays.

  • Geräte mit Android 11 oder höher können eine verwenden OverlayConfig Datei ( config.xml ) anstelle von offensichtlichen Attributen. Die Verwendung einer Overlay-Datei ist die empfohlene Methode für Overlays.

  • Alle Geräte können manifestieren Attribute verwenden ( android:isStatic und android:priority ) zu konfigurieren statische RROs.

OverlayConfig verwenden

In Android 11 oder höher, können Sie OverlayConfig die Veränderlichkeit, Standardstatus und die Priorität von Overlays zu konfigurieren. Um ein Overlay zu konfigurieren, erstellen oder die Datei an sich ändern partition/overlay/config/config.xml , wo partition die Partition des Overlay ist konfiguriert werden. Um so konfiguriert werden, muss ein Overlay befindet sich in der overlay/ Verzeichnis der Partition , in dem die Überlagerung konfiguriert ist. Der folgende Code zeigt ein Beispiel 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>"

Der <overlay> Tag erfordert ein package - Attribut, das das Overlay - Paket anzeigt konfiguriert wird. Das optionale enabled Attribut steuert , ob das Overlay standardmäßig aktiviert ist (Standard ist false ). Das optionale mutable Attribut steuert , ob das Overlay wandelbar und kann seinen aktivierten Zustand programmatisch zur Laufzeit geändert hat (Standard ist true ). Overlays, die nicht in einer Konfigurationsdatei aufgeführt sind, sind änderbar und standardmäßig deaktiviert.

Überlagerungspriorität

Wenn mehrere Überlagerungen dieselben Ressourcen überschreiben, ist die Reihenfolge der Überlagerungen wichtig. Ein Overlay hat eine höhere Priorität als Overlays mit Konfigurationen, die seiner eigenen Konfiguration vorausgehen. Die Rangfolge der Überlagerungen in verschiedenen Partitionen (von der geringsten zur größten Rangfolge) ist wie folgt.

  • system
  • vendor
  • oem
  • odm
  • product
  • system_ext

Dateien zusammenführen

Mit <merge> Tags kann für andere Konfigurationsdateien an der angegebenen Position in die Konfigurationsdatei zusammengeführt werden. Das path - Attribut des Tags steht der Pfad der Datei in das Verzeichnis Datei mit Overlay - Konfiguration relativ zu verschmelzen.

Manifestattribute verwenden (statische RROs)

In Android 10 oder niedriger werden die Unveränderlichkeit und der Vorrang von Overlays mithilfe der folgenden Manifestattribute konfiguriert.

  • android:isStatic . Wenn der Wert dieses booleschen Attribut gesetzt ist true , wird die Überlagerung standardmäßig aktiviert und unveränderlich ist , die aus der Überlagerung verhindert werden deaktiviert.

  • android:priority . Der Wert dieses numerischen Attributs (das nur statische Overlays betrifft) konfiguriert die Priorität des Overlays, wenn mehrere statische Overlays denselben Ressourcenwert zum Ziel haben. Eine höhere Zahl weist auf eine höhere Priorität hin.

Der folgende Code zeigt ein Beispiel 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

In Android 11 oder höher, wenn eine Konfigurationsdatei befindet sich in partition/overlay/config/config.xml werden Overlays konfiguriert , dass die Datei und mit android:isStatic und android:priority in der Trennwand befindet sich keine Auswirkungen auf Overlays haben. Das Definieren einer Overlay-Konfigurationsdatei in einer beliebigen Partition erzwingt die Priorität der Overlay-Partition.

Darüber hinaus entfernt Android 11 oder höher die Möglichkeit, statische Overlays zu verwenden, um die Werte von Ressourcen zu beeinflussen, die während der Paketinstallation gelesen werden. Für die gemeinsame Nutzung bei statischen Overlays über den Wert von booleans zu ändern , dass configure Komponente Zustand aktiviert ist , verwenden Sie die <component-override> SystemConfig Tag (neu in Android 11).

Debugging von Overlays

Um Overlays manuell zu aktivieren, zu deaktivieren und auszugeben, verwenden Sie den folgenden Shell-Befehl des Overlay-Managers.

adb shell cmd overlay

OverlayManagerService Anwendungen idmap2 im Overlay - Paket Ressourcen - IDs in der Zielpaket Ressourcen - IDs zuordnen. Die erzeugten ID - Zuordnungen werden gespeichert in /data/resource-cache/ . Wenn Ihr Overlay nicht korrekt funktioniert, finden Sie die entsprechenden idmap Datei für Ihre Overlay in /data/resource-cache/ , dann führen Sie den folgenden Befehl ein .

adb shell idmap2 dump --idmap-path [file]

Dieser Befehl druckt die Ressourcenzuordnung wie unten gezeigt.

[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType