Un overlay di risorse di runtime è un pacchetto che modifica i valori delle risorse di un pacchetto di destinazione in fase di runtime. Ad esempio, un'app installata sull'immagine di sistema potrebbe modificare il proprio comportamento in base al valore di una risorsa. Anziché codificare il valore della risorsa in fase di compilazione, un RRO installato su una partizione diversa può modificare i valori delle risorse dell'app in fase di esecuzione.
Gli RRO possono essere attivati o disattivati. Puoi impostare programmaticamente lo stato attivo/disattivato per attivare/disattivare la possibilità di un RRO di modificare i valori delle risorse. I RRO sono disattivati per impostazione predefinita (tuttavia, i RRO statici sono attivati per impostazione predefinita).
Risorse in overlay
Gli overlay funzionano mappando le risorse definite nel pacchetto di overlay alle risorse definite nel pacchetto di destinazione. Quando un'app tenta di risolvere il valore di una risorsa nel pacchetto di destinazione, viene restituito il valore della risorsa overlay a cui è mappata la risorsa di destinazione.
Configurare il manifest
Un pacchetto è considerato un pacchetto RRO se contiene un tag <overlay>
come
secondario del tag <manifest>
.
Il valore dell'attributo obbligatorio
android:targetPackage
specifica il nome del pacchetto che l'RRO intende sovrapporre.Il valore dell'attributo facoltativo
android:targetName
specifica il nome del sottoinsieme di risorse sovrapponibile del pacchetto di destinazione che l'RRO intende sovrapporre. Se la destinazione non definisce un insieme di risorse sovrapponibili, questo attributo non deve essere presente.
Il seguente codice mostra un overlay di esempio 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>
Gli overlay non possono sovrapporre codice, quindi non possono contenere file DEX. Inoltre, l'attributo android:hasCode
del tag <application
> nel file manifest deve essere impostato su false
.
Definisci la mappa delle risorse
In Android 11 o versioni successive, il meccanismo consigliato per
definire la mappa delle risorse in overlay è creare un file nella directory res/xml
del pacchetto in overlay, enumerare le risorse di destinazione che devono essere
sovrapposte e i relativi valori di sostituzione, quindi impostare il valore dell'attributo
android:resourcesMap
del tag manifest <overlay>
su un riferimento
al file di mappatura delle risorse.
Il seguente codice mostra un file res/xml/overlays.xml
di esempio.
<?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>
Il seguente codice mostra un manifest overlay di esempio.
<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>
Creazione del pacchetto
Android 11 o versioni successive supporta una regola di compilazione Soong per gli overlay che impedisce ad Android Asset Packaging Tool 2 (AAPT2) di tentare di eliminare le duplicazioni delle configurazioni delle risorse con lo stesso valore (--no-resource-deduping
) e di rimuovere le risorse senza configurazioni predefinite (--no-resource-removal
). Il codice seguente mostra un esempio di file Android.bp
.
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
Risolvi le risorse
Se una risorsa di destinazione o una risorsa in overlay ha più configurazioni definite per la risorsa su cui viene eseguita la query, il runtime delle risorse restituisce il valore della configurazione che corrisponde meglio alla configurazione del dispositivo. Per determinare quale configurazione è la più adatta, unisci l'insieme delle configurazioni delle risorse in overlay con l'insieme delle configurazioni delle risorse di destinazione e poi segui il normale flusso di risoluzione delle risorse (per maggiori dettagli, consulta In che modo Android trova la risorsa più adatta).
Ad esempio, se un overlay definisce un valore per la configurazione drawable-en
e il target definisce un valore per drawable-en-port
, drawable-en-port
ha una corrispondenza migliore, pertanto il valore della configurazione target drawable-en-port
viene scelto in fase di runtime. Per sovrapporre tutte le configurazioni di drawable-en
, l'overlay deve definire un valore per ogni configurazione di drawable-en
definita dal target.
Gli overlay possono fare riferimento alle proprie risorse, con comportamenti diversi tra le release di Android.
In Android 11 o versioni successive, ogni overlay ha il proprio spazio ID risorsa riservato che non si sovrappone allo spazio ID risorsa di destinazione o ad altri spazi ID risorsa degli overlay, pertanto gli overlay che fanno riferimento alle proprie risorse funzionano come previsto.
In Android 10 o versioni precedenti, gli overlay e i pacchetti di destinazione condividono lo stesso spazio ID risorsa, il che può causare collisioni e comportamenti imprevisti quando tentano di fare riferimento alle proprie risorse utilizzando la sintassi
@type/name
.
Attivazione/disattivazione degli overlay
Utilizza l'API OverlayManager
per attivare e disattivare gli overlay mutabili (recupera
l'interfaccia API utilizzando Context#getSystemService(Context.OVERLAY_SERVICE)
). Un
overlay può essere attivato solo dal pacchetto di destinazione o da un pacchetto con l'android.permission.CHANGE_OVERLAY_PACKAGES
. Quando un overlay viene attivato o disattivato, gli eventi di modifica della configurazione si propagano al pacchetto di destinazione e le attività di destinazione vengono riavviate.
Limita risorse sovrapponibili
In Android 10 o versioni successive, il tag XML <overlayable>
espone un insieme di risorse
che gli RRO possono sovrapporre. Nel seguente file res/values/overlayable.xml
, string/foo
e integer/bar
sono risorse utilizzate per impostare i temi dell'aspetto del dispositivo. Per sovrapporre queste risorse, un overlay deve scegliere esplicitamente come target la raccolta di risorse sovrapponibili.
<!-- 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 può definire più tag <overlayable>
, ma ogni tag deve avere un nome univoco all'interno del pacchetto. Ad esempio:
È possibile che due pacchetti diversi definiscano entrambi
<overlayable name="foo">
.Non è possibile che un singolo APK abbia due blocchi
<overlayable name="foo">
.
Il seguente codice mostra un esempio di overlay nel file 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>
Quando un'app definisce un tag <overlayable>
, il targeting dell'app viene sovrapposto:
Deve essere specificato
targetName
.Può sovrapporsi solo alle risorse elencate all'interno del tag
<overlayable>
.Può avere come target un solo nome
<overlayable>
.
Non puoi attivare un overlay che ha come target un pacchetto che espone risorse sovrapponibili, ma non utilizza android:targetName
per scegliere come target un tag <overlayable>
specifico.
Limitare i criteri
Utilizza il tag <policy>
per applicare limitazioni alle risorse sovrapposte. L'attributo
type
specifica i criteri che un overlay deve soddisfare per eseguire l'override
delle risorse incluse. I tipi supportati includono quanto segue.
public
. Qualsiasi overlay può sostituire la risorsa.system
. Qualsiasi overlay sulla partizione di sistema può sostituire le risorse.vendor
. Qualsiasi overlay sulla partizione del fornitore può sostituire le risorse.product
. Qualsiasi overlay sulla partizione del prodotto può sostituire le risorse.oem
. Qualsiasi overlay sulla partizione OEM può sostituire le risorse.odm
. Qualsiasi overlay sulla partizione ODM può sostituire le risorse.signature
. Qualsiasi overlay firmato con la stessa firma dell'APK di destinazione può eseguire l'override delle risorse.actor
. Qualsiasi overlay firmato con la stessa firma dell'APK attore può eseguire l'override delle risorse. L'attore è dichiarato nel tag named-actor nella configurazione di sistema.config_signature
. Qualsiasi overlay firmato con la stessa firma dell'APK overlay-config può sostituire le risorse. La configurazione overlay è dichiarata nel tag overlay-config-signature nella configurazione di sistema.
Il seguente codice mostra un tag <policy>
di esempio nel file 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>
Per specificare più criteri, utilizza le barre verticali (|) come caratteri separatori.
Quando sono specificati più criteri, un overlay deve soddisfare solo un criterio per sostituire le risorse elencate nel tag <policy>
.
Configurare gli overlay
Android supporta diversi meccanismi per configurare la mutabilità, lo stato predefinito e la priorità degli overlay a seconda della versione della release di Android.
I dispositivi con Android 11 o versioni successive possono utilizzare un file
OverlayConfig
(config.xml
) anziché gli attributi manifest. L'utilizzo di un file di overlay è il metodo consigliato per gli overlay.Tutti i dispositivi possono utilizzare gli attributi manifest (
android:isStatic
eandroid:priority
) per configurare RRO statici.
Utilizzare OverlayConfig
In Android 11 o versioni successive, puoi usare OverlayConfig
per configurare la mutabilità, lo stato predefinito e la priorità degli overlay. Per configurare
un overlay, crea o modifica il file situato in
partition/overlay/config/config.xml
, dove partition
è la partizione dell'overlay da configurare. Per essere configurato, un overlay deve trovarsi nella directoryoverlay/
della partizione in cui è configurato. Il seguente codice mostra un esempio 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>"
Il tag <overlay>
richiede un attributo package
che indica quale pacchetto di overlay
viene configurato. L'attributo facoltativo enabled
controlla se l'overlay è attivato o meno per impostazione predefinita (il valore predefinito è false
). L'attributo facoltativo mutable
controlla se l'overlay è mutabile e se il suo stato di attivazione può essere modificato tramite programmazione in fase di esecuzione (il valore predefinito è true
). Gli overlay non elencati in un file di configurazione sono mutabili e disattivati per impostazione predefinita.
Priorità dell'overlay
Quando più overlay sostituiscono le stesse risorse, l'ordine degli overlay è importante. Un overlay ha la precedenza sugli overlay con configurazioni precedenti alla propria configurazione. L'ordine di precedenza degli overlay in diverse partizioni (dalla meno alla massima precedenza) è il seguente.
system
vendor
odm
oem
product
system_ext
Unisci file
L'utilizzo dei tag <merge>
consente di unire altri file di configurazione nella posizione specificata nel file di configurazione. L'attributo path
del tag rappresenta il percorso del file da unire rispetto alla directory contenente i file di configurazione dell'overlay.
Utilizzare attributi manifest/RRO statici
In Android 10 o versioni precedenti, l'immutabilità e la precedenza dell'overlay vengono configurate utilizzando i seguenti attributi manifest.
android:isStatic
. Quando il valore di questo attributo booleano è impostato sutrue
, l'overlay è abilitato per impostazione predefinita ed è immutabile, il che impedisce la sua disabilitazione.android:priority
. Il valore di questo attributo numerico (che influisce solo sugli overlay statici) configura la precedenza dell'overlay quando più overlay statici hanno come target lo stesso valore della risorsa. Un numero più alto indica una priorità maggiore.
Il seguente codice mostra un esempio 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>
Modifiche in Android 11
In Android 11 o versioni successive, se un file di configurazione si trova in partition/overlay/config/config.xml
, gli overlay vengono configurati utilizzando quel file e android:isStatic
e android:priority
non influiscono sugli overlay nella partizione. La definizione di un file di configurazione dell'overlay in qualsiasi
partizione impone la precedenza della partizione dell'overlay.
Inoltre, Android 11 o versioni successive elimina la possibilità di utilizzare overlay statici per influire sui valori delle risorse lette durante l'installazione dei pacchetti. Per il caso d'uso comune di utilizzare overlay statici per modificare il valore dei valori booleani che configurano lo stato di attivazione del componente, utilizza il tag <component-override>
SystemConfig
(novità in Android 11).
Overlay di debug
Per attivare, disattivare ed eseguire manualmente il dump degli overlay, utilizza il seguente comando della shell di gestione degli overlay.
adb shell cmd overlay
OverlayManagerService
utilizza idmap2
per mappare gli ID risorsa nel pacchetto di destinazione agli ID risorsa nel pacchetto overlay. Le mappature degli ID generate vengono memorizzate in /data/resource-cache/
. Se l'overlay non funziona correttamente, trova il file idmap
corrispondente in /data/resource-cache/
, quindi esegui questo comando.
adb shell idmap2 dump --idmap-path [file]
Questo comando stampa la mappatura delle risorse come mostrato di seguito.
[target res id] - > [overlay res id] [resource name]
0x01040151 -> 0x01050001 string/config_dozeComponent
0x01040152 -> 0x01050002 string/config_dozeDoubleTapSensorType
0x01040153 -> 0x01050003 string/config_dozeLongPressSensorType