Une superposition de ressources d'exécution (RRO) est un package qui modifie les valeurs de ressources d'un package cible au moment de l'exécution. Par exemple, une application installée sur l'image système peut modifier son comportement en fonction de la valeur d'une ressource. Plutôt que de coder en dur la valeur de la ressource au moment de la compilation, une RRO installée sur une autre partition peut modifier les valeurs des ressources de l'application au moment de l'exécution.
Les RRO peuvent être activées ou désactivées. Vous pouvez définir l'état d'activation/de désactivation par programmation pour activer ou désactiver la possibilité d'une RRO de modifier les valeurs de ressources. Les RRO sont désactivées par défaut (toutefois, les RRO statiques sont activées par défaut).
Superposer des ressources
Les superpositions fonctionnent en mappant les ressources définies dans le package de superposition aux ressources définies dans le package cible. Lorsqu'une application tente de résoudre la valeur d'une ressource dans le package cible, la valeur de la ressource de superposition à laquelle la ressource cible est mappée est renvoyée à la place.
Configurer le fichier manifeste
Un package est considéré comme un package RRO s'il contient une balise <overlay> en tant qu'
enfant de la balise <manifest>.
La valeur de l'attribut
android:targetPackageobligatoire spécifie le nom du package que la RRO doit superposer.La valeur de l'attribut
android:targetNamefacultatif spécifie le nom du sous-ensemble de ressources superposables du package cible que la RRO doit superposer. Si la cible ne définit pas d'ensemble de ressources superposables, cet attribut ne doit pas être présent.
Le code suivant présente un exemple de superposition 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>
Les superpositions ne peuvent pas superposer de code. Elles ne peuvent donc pas contenir de fichiers DEX. De plus, l'attribut
android:hasCode de la balise <application> dans le fichier manifeste doit être
défini sur false.
Définir la carte des ressources
Dans Android 11 ou version ultérieure, le mécanisme recommandé pour
définir la carte des ressources de superposition consiste à créer un fichier dans le res/xml
répertoire du package de superposition, à énumérer les ressources cibles à
superposer et leurs valeurs de remplacement, puis à définir la valeur de l'
android:resourcesMap attribut de la balise de fichier manifeste <overlay> sur une référence
au fichier de mappage des ressources.
Le code suivant présente un exemple de fichier res/xml/overlays.xml.
<?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>
Le code suivant présente un exemple de fichier manifeste de superposition.
<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>
Créer le package
Android 11 ou version ultérieure est compatible avec une règle de compilation Soong pour les superpositions qui empêche Android Asset Packaging Tool 2 (AAPT2) de tenter de dédupliquer les configurations de ressources ayant la même valeur (--no-resource-deduping) et de supprimer les ressources sans configurations par défaut (--no-resource-removal). Le code suivant présente un exemple de fichier Android.bp.
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
Résoudre les ressources
Si une ressource cible ou une ressource de superposition comporte plusieurs configurations définies pour la ressource interrogée, l'exécution des ressources renvoie la valeur de la configuration qui correspond le mieux à la configuration de l'appareil. Pour déterminer quelle configuration est la plus adaptée, fusionnez l' ensemble des configurations de ressources de superposition dans l'ensemble des configurations de ressources cibles , puis suivez le flux de résolution de ressources normal (pour en savoir plus, consultez Comment Android détermine-t-il la ressource la plus pertinente ?).
Par exemple, si une superposition définit une valeur pour la configuration drawable-en
et que la cible définit une valeur pour drawable-en-port, drawable-en-port
correspond mieux. La valeur de la configuration cible drawable-en-port
est donc choisie au moment de l'exécution. Pour superposer toutes les configurations drawable-en, la superposition doit définir une valeur pour chaque configuration drawable-en définie par la cible.
Les superpositions peuvent référencer leurs propres ressources, avec des comportements différents selon les versions d'Android.
Dans Android 11 ou version ultérieure, chaque superposition possède son propre espace d'ID de ressource réservé qui ne chevauche pas l'espace d'ID de ressource cible ni les autres espaces d'ID de ressource de superposition. Les superpositions référençant leurs propres ressources fonctionnent donc comme prévu.
Dans Android 10 ou version antérieure, les superpositions et les packages cibles partagent le même espace d'ID de ressource, ce qui peut entraîner des conflits et un comportement inattendu lorsqu'ils tentent de référencer leurs propres ressources à l'aide de la syntaxe
@type/name.
Activer/Désactiver les superpositions
Les superpositions peuvent être activées/désactivées manuellement et par programmation.
Désactiver ou activer manuellement les superpositions
Pour activer et vérifier manuellement une RRO, exécutez la commande suivante :
adb shell cmd overlay enable --user current com.example.carrro
adb shell cmd overlay list --user current | grep -i com.example com.example.carrroCela active la RRO pour l'utilisateur système (userId = 0) qui possède l'interface utilisateur du système.
Cette instruction n'affecte pas les applications démarrées par l'utilisateur au premier plan (userId = 10). Pour activer la RRO pour l'utilisateur au premier plan, utilisez le paramètre -–user 10 :
adb shell cmd overlay enable --user 10 com.example.carrroActiver ou désactiver les superpositions par programmation
Utilisez l'API OverlayManager pour activer et désactiver les superpositions mutables (récupérez l'interface de l'API à l'aide de Context#getSystemService(Context.OVERLAY_SERVICE)). Une superposition ne peut être activée que par le package qu'elle cible ou par un package disposant de l'autorisation android.permission.CHANGE_OVERLAY_PACKAGES. Lorsqu'une superposition est activée ou désactivée, les événements de modification de configuration sont propagés au package cible et les activités cibles sont relancées.
Limiter les ressources superposables
Dans Android 10 ou version ultérieure, la balise XML <overlayable> expose un ensemble de ressources
que les RRO sont autorisées à superposer. Dans l'exemple de fichier res/values/overlayable.xml suivant, string/foo et integer/bar sont des ressources utilisées pour personnaliser l'apparence de l'appareil. Pour superposer ces ressources, une superposition doit cibler explicitement la collection de ressources superposables par nom.
<!-- 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>
Un APK peut définir plusieurs balises <overlayable>, mais chaque balise doit avoir un
nom unique dans le package. Par exemple :
Il est possible que deux packages différents définissent
<overlayable name="foo">.Il n'est pas possible qu'un seul APK comporte deux blocs
<overlayable name="foo">.
Le code suivant présente un exemple de superposition dans le fichier 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>
Lorsqu'une application définit une balise <overlayable>, les superpositions ciblant cette application :
doivent spécifier
targetName;ne peuvent superposer que les ressources listées dans la balise
<overlayable>;ne peuvent cibler qu'un seul nom
<overlayable>.
Vous ne pouvez pas activer une superposition ciblant un package qui expose des ressources superposables
mais qui n'utilise pas android:targetName pour cibler une balise
<overlayable> spécifique.
Limiter les règles
Utilisez la balise <policy> pour appliquer des restrictions aux ressources superposables. L'attribut type spécifie les règles qu'une superposition doit respecter pour remplacer les ressources incluses. Les types compatibles sont les suivants.
public. N'importe quelle superposition peut remplacer la ressource.system. N'importe quelle superposition sur la partition système peut remplacer les ressources.vendor. N'importe quelle superposition sur la partition du fournisseur peut remplacer les ressources.product. N'importe quelle superposition sur la partition du produit peut remplacer les ressources.oem. N'importe quelle superposition sur la partition OEM peut remplacer les ressources.odm. N'importe quelle superposition sur la partition ODM peut remplacer les ressources.signature. N'importe quelle superposition signée avec la même signature que l'APK cible peut remplacer les ressources.actor. N'importe quelle superposition signée avec la même signature que l'APK acteur peut remplacer les ressources. L'acteur est déclaré dans la balise named-actor de la configuration système.config_signature. N'importe quelle superposition signée avec la même signature que l'APK overlay-config peut remplacer les ressources. La configuration de superposition est déclarée dans la balise overlay-config-signature de la configuration système.
Le code suivant présente un exemple de balise <policy> dans le fichier
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>
Pour spécifier plusieurs règles, utilisez des barres verticales (|) comme caractères de séparation.
Lorsque plusieurs règles sont spécifiées, une superposition n'a besoin de respecter qu'une seule
règle pour remplacer les ressources listées dans la balise <policy>.
Configurer les superpositions
Android est compatible avec différents mécanismes de configuration de la mutabilité, de l'état par défaut et de la priorité des superpositions en fonction de la version d'Android.
Les appareils exécutant Android 11 ou version ultérieure peuvent utiliser un fichier
OverlayConfig(config.xml) au lieu d'attributs de fichier manifeste. L'utilisation d'un fichier de superposition est la méthode recommandée pour les superpositions.Tous les appareils peuvent utiliser des attributs de fichier manifeste (
android:isStaticetandroid:priority) pour configurer des RRO statiques.
Utiliser OverlayConfig
Dans Android 11 ou version ultérieure, vous pouvez utiliser OverlayConfig pour configurer la mutabilité, l'état par défaut et la priorité des superpositions. Pour configurer
une superposition, créez ou modifiez le fichier situé dans
partition/overlay/config/config.xml, où partition correspond à la partition de la
superposition à configurer. Pour être configurée, une superposition doit résider dans le répertoire overlay/ de la partition dans laquelle elle est configurée. Le code suivant présente un exemple de fichier 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>"
La balise <overlay> nécessite un attribut package qui indique le package de superposition
en cours de configuration. L'attribut enabled facultatif contrôle si la superposition est activée par défaut (false par défaut). L'attribut mutable facultatif contrôle si la superposition est mutable et si son état activé peut être modifié par programmation au moment de l'exécution (true par défaut). Les superpositions non listées dans un fichier de configuration sont mutables et désactivées par défaut.
Priorité de la superposition
Lorsque plusieurs superpositions remplacent les mêmes ressources, l'ordre des superpositions est important. Une superposition a une priorité plus élevée que les superpositions dont les configurations précèdent sa propre configuration. L'ordre de priorité des superpositions dans différentes partitions (de la priorité la plus faible à la priorité la plus élevée) est le suivant.
systemvendorodmoemproductsystem_ext
Fusionner des fichiers
L'utilisation de balises <merge> permet de fusionner d'autres fichiers de configuration à la
position spécifiée dans le fichier de configuration. L'attribut path de la balise représente le chemin d'accès du fichier à fusionner par rapport au répertoire contenant les fichiers de configuration de superposition.
Utiliser des attributs de fichier manifeste/des RRO statiques
Dans Android 10 ou version antérieure, l'immutabilité et la priorité de la superposition sont configurées à l'aide des attributs de fichier manifeste suivants.
android:isStatic. Lorsque la valeur de cet attribut booléen est définie surtrue, la superposition est activée par défaut et est immuable, ce qui l'empêche d'être désactivée.android:priority. La valeur de cet attribut numérique (qui n'affecte que les superpositions statiques) configure la priorité de la superposition lorsque plusieurs superpositions statiques ciblent la même valeur de ressource. Plus le nombre est élevé, plus la priorité est élevée.
Le code suivant présente un exemple de fichier 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>
Modifications dans Android 11
Dans Android 11 ou version ultérieure, si un fichier de configuration se trouve dans partition/overlay/config/config.xml, les superpositions sont configurées à l'aide de ce fichier, et android:isStatic et android:priority n'ont aucun effet sur les superpositions situées dans la partition. La définition d'un fichier de configuration de superposition dans n'importe quelle partition applique la priorité de la partition de superposition.
De plus, Android 11 ou version ultérieure supprime la possibilité d'utiliser des superpositions statiques pour affecter les valeurs des ressources lues lors de l'installation du package. Pour le cas d'utilisation courant des superpositions statiques afin de modifier la
valeur des booléens qui configurent l'état activé du composant, utilisez la balise
<component-override> SystemConfig (nouveauté d'Android
11).
Déboguer les superpositions
Pour activer, désactiver et vider manuellement les superpositions, utilisez la commande shell du gestionnaire de superpositions suivante.
adb shell cmd overlayL'utilisation de enable sans spécifier d'utilisateur affecte l'utilisateur actuel, c'est-à-dire l'utilisateur système (userId = 0), qui possède l'interface utilisateur du système. Cela n'affecte pas l'utilisateur au premier plan (userId = 10), qui possède les applications. Pour activer la RRO pour l'utilisateur au premier plan, utilisez le paramètre –-user 10 :
adb shell cmd overlay enable --user 10 com.example.carrroOverlayManagerService utilise idmap2 pour mapper les ID de ressources du package cible aux ID de ressources du package de superposition. Les mappages d'ID générés sont stockés dans /data/resource-cache/. Si votre superposition ne fonctionne pas correctement, recherchez le fichier idmap correspondant dans /data/resource-cache/, puis exécutez la commande suivante.
adb shell idmap2 dump --idmap-path [file]Cette commande affiche le mappage des ressources comme indiqué ci-dessous.
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType