Zmienianie wartości zasobów aplikacji w czasie działania

Nakładka zasobów środowiska wykonawczego (RRO) to pakiet, który zmienia wartości zasobów pakietu docelowego w czasie działania. Na przykład aplikacja zainstalowana w systemie może zmienić swoje działanie w zależności od wartości zasobu. Zamiast kodowanie na stałe wartości zasobu w momencie kompilacji, a RRO zainstalowane w innym partycja może zmieniać wartości zasobów aplikacji w czasie działania.

RRO można włączyć lub wyłączyć. Możesz automatycznie ustawić włączanie/wyłączanie, aby przełączać możliwość zmiany wartości zasobów przez RRO. RRO są domyślnie wyłączone (statyczne RRO są włączone przez ).

Zasoby nakładki

Nakładki działają, mapując zasoby zdefiniowane w pakiecie nakładek na zasoby zdefiniowane w pakiecie docelowym. Gdy aplikacja próbuje rozpoznać wartość zasobu w pakiecie docelowym, wartość zasobu nakładki docelowego, .

Konfigurowanie pliku manifestu

Pakiet jest uważany za pakiet RRO, jeśli zawiera tag <overlay> jako elementu potomnego tagu <manifest>.

  • Wartość wymaganego atrybutu android:targetPackage określa nazwę pakietu, który ma być nałożony na RRO.

  • Wartość opcjonalnego atrybutu android:targetName określa nazwę nakładalny podzbiór zasobów pakietu docelowego, do którego planuje uzyskać RRO nakładkę. Jeśli miejsce docelowe nie definiuje zbioru zasobów, które można nakładać, nie powinien być obecny.

Poniższy kod to przykładowa nakładka 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>

Nakładki nie mogą nakładać kodu, więc nie mogą zawierać plików DEX. Dodatkowo Atrybut android:hasCode elementu <application> w pliku manifestu musi być określony tag ustawiono na false.

Definiowanie mapy zasobów

W Androidzie 11 lub nowszym zalecany mechanizm zdefiniowanie mapy zasobów nakładki to utworzenie pliku w folderze res/xml w katalogu pakietu nakładki, podaj zasoby docelowe, nałożonych i ich zastępczych wartości, a potem ustaw wartość funkcji Atrybut android:resourcesMap tagu manifestu <overlay> powiązany z plikiem referencyjnym do pliku mapowania zasobów.

Poniższy kod to przykładowy plik 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>

Poniżej znajduje się przykładowy plik manifestu nakładki.

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

Tworzenie pakietu

Android 11 lub nowszy obsługuje regułę kompilacji Soong dla nakładki, które uniemożliwiają Android Asset Packaging Tool 2 (AAPT2), deduplikowanie konfiguracji zasobów o tej samej wartości (--no-resource-deduping) oraz usuwanie zasobów bez ustawień domyślnych (--no-resource-removal). Poniższy kod to przykład Android.bp.

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

Rozwiąż problem z zasobami

Jeśli zasób docelowy lub zasób nakładki ma wiele zdefiniowanych konfiguracji danego zasobu, środowisko wykonawcze zasobów zwraca wartość klucza która najlepiej pasuje do konfiguracji urządzenia. Aby określić, która konfiguracja najlepiej pasuje do konfiguracji, scal zestaw konfiguracji zasobów nakładanych na zbiór zasobów docelowych a następnie postępuj zgodnie ze zwykłym procesem rozpoznawania zasobów (na potrzeby Więcej informacji znajdziesz w artykule Jak Android znajduje najlepiej ).

Jeśli np. nakładka definiuje wartość konfiguracji drawable-en , a cel określa wartość dla drawable-en-port, drawable-en-port ma lepsze dopasowanie, więc wartość konfiguracji docelowej drawable-en-port jest wybierany w trakcie działania. Aby nakładać wszystkie konfiguracje drawable-en, nakładka musi określać wartość dla każdej konfiguracji drawable-en definiowanej przez cel.

Nakładki mogą odwoływać się do własnych zasobów, a ich działanie różni się w zależności od tego, Wersje Androida.

  • W Androidzie 11 lub nowszym każda nakładka ma swoje własne zarezerwowana przestrzeń identyfikatora zasobu, która nie nakłada się na przestrzeń identyfikatora zasobu docelowego, lub inne przestrzenie identyfikatorów zasobów, więc nakładki odwołujące się do własnych zasobów działać zgodnie z oczekiwaniami.

  • W Androidzie 10 lub starszym nakładki i pakiety docelowe współdzielą ten sam zasób przestrzeń identyfikatorów, która może powodować kolizje i nieoczekiwane działanie podczas próby może odwołać się do własnych zasobów przy użyciu składni @type/name.

Włączanie i wyłączanie nakładek

Używanie interfejsu API OverlayManager do włączania i wyłączania zmiennych nakładek (pobieranie interfejsu API za pomocą metody Context#getSystemService(Context.OVERLAY_SERVICE)). An można włączyć tylko przez pakiet, na który jest kierowana, lub przez pakiet z Uprawnienia: android.permission.CHANGE_OVERLAY_PACKAGES. Gdy nakładka jest włączone lub wyłączone, zdarzenia zmiany konfiguracji są rozpowszechniane w pakiecie docelowym i docelowych aktywności.

Ogranicz zasoby, które można nakładać

W Androidzie 10 lub nowszym tag XML <overlayable> ujawnia zbiór zasobów które można nałożyć na reklamy RRO. W poniższym przykładzie res/values/overlayable.xml plik, string/foo i integer/bar to zasoby używane do określania tematów wyglądu urządzenia; nałożenie na siebie tych zasobów, musi bezpośrednio wskazywać na zbiór zasobów nakładanych według nazwy.

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

Plik APK może określać wiele tagów <overlayable>, ale każdy tag musi mieć unikalny nazwę w pakiecie. Na przykład:

  • OK w przypadku 2 różnych pakietów, które definiują <overlayable name="foo">.

  • Jeden plik APK nie może mieć 2 bloków typu <overlayable name="foo">.

Poniższy kod pokazuje przykładową nakładkę w interfejsie 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>

Gdy aplikacja definiuje tag <overlayable>, nakłada się na tę aplikację:

  • Musisz określić wartość targetName.

  • Może nakładać się tylko na zasoby wymienione w tagu <overlayable>.

  • Można kierować tylko na 1 nazwę typu <overlayable>.

Nie możesz włączyć nakładki kierowanej na pakiet, który wyświetla nakładki zasobów, ale nie używa android:targetName do kierowania reklam na konkretny <overlayable>.

Zasady ograniczeń

Aby egzekwować ograniczenia dotyczące zasobów nakładanych, użyj tagu <policy>. Atrybut type określa zasady, które musi spełnić nakładka, aby ją zastąpić z dostępnych materiałów. Obsługiwane typy to między innymi:

  • public Każda nakładka może zastąpić zasób.
  • system Każda nakładka na partycji systemowej może zastąpić zasoby.
  • vendor Każda nakładka na partycji dostawcy może zastąpić zasoby.
  • product Każda nakładka na partycji produktu może zastąpić zasoby.
  • oem Każda nakładka na partycji OEM może zastąpić zasoby.
  • odm Każda nakładka na partycji odm może zastąpić zasoby.
  • signature Każda nakładka podpisana tym samym podpisem co docelowy plik APK może i zastępować zasoby.
  • actor Każda nakładka podpisana tym samym podpisem co pakiet APK aktualnego może i zastępować zasoby. Podmiot, który wykonał czynność, jest zadeklarowany w tagu named-actor w systemie. config.
  • config_signature wszelkie nakładki podpisane tym samym podpisem co Plik apk overlay-config może zastąpić zasoby. Konfiguracja nakładki to zadeklarowane w tagu overlay-config-signature w konfiguracji systemu.

Poniżej znajduje się przykładowy tag <policy> w sekcji 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>

Aby wskazać kilka zasad, użyj pionowych pasków (|) jako separatorów. Jeśli określono wiele zasad, nakładka musi spełniać tylko jedną do zastąpienia zasobów wymienionych w tagu <policy>.

Konfigurowanie nakładek

Android obsługuje różne mechanizmy konfigurowania zmienności, wartości domyślne oraz priorytet nakładek w zależności od wersji Androida.

  • Urządzenia z Androidem 11 lub nowszym mogą używać OverlayConfig (config.xml) zamiast atrybutów manifestu. Za pomocą pliku nakładki to zalecana metoda tworzenia nakładek.

  • Wszystkie urządzenia mogą używać atrybutów manifestu (android:isStatic i android:priority), aby skonfigurować statyczne RRO.

.

Użyj OverlayConfig

Na Androidzie 11 lub nowszym możesz używać aplikacji OverlayConfig do: skonfigurować zmienność, domyślny stan i priorytet nakładek. Aby skonfigurować utwórz lub zmodyfikuj plik znajdujący się pod adresem partition/overlay/config/config.xml, gdzie partition jest partycją do skonfigurowania. Aby można było skonfigurować nakładkę, musi się ona znajdować w Katalog overlay/ partycji, w której skonfigurowano nakładkę. ten kod pokazuje przykładowy 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>"

Tag <overlay> wymaga atrybutu package wskazującego, która nakładka pakiet jest konfigurowany. Opcjonalny atrybut enabled określa, czy lub nie, jest ona domyślnie włączona (domyślnie false). Parametr opcjonalny Atrybut mutable określa, czy nakładka jest elastyczna i może mieć stan włączenia zmienia się automatycznie w czasie działania (domyślnie jest to true). Nakładki, których nie ma na liście w pliku konfiguracji, można zmieniać i wyłączać przez wartość domyślną.

Pierwszeństwo nakładek

Gdy wiele nakładek zastępuje ten sam zasób, kolejność nakładek jest są ważne. Nakładka ma wyższy priorytet niż nakładki z konfiguracjami poprzedza własną konfigurację. Pierwszeństwo nakładek w różnych (w kolejności od najniższego do najwyższego).

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

Scal pliki

Użycie tagów <merge> umożliwia scalanie innych plików konfiguracji w folderze do pliku konfiguracji. Atrybut path tagu reprezentuje ścieżkę pliku do scalania względem katalogu zawierającego plików konfiguracji nakładek.

Używaj atrybutów pliku manifestu/statycznych RRO

W Androidzie 10 i starszych wersjach zasada niezmienności i pierwszeństwa nakładania jest konfigurowana za pomocą parametru tych atrybutów pliku manifestu.

  • android:isStatic Gdy wartość tego atrybutu logicznego jest ustawiona na true, Nakładka jest domyślnie włączona i nie można jej zmienić, co uniemożliwia nałożenie nakładki. przed ich wyłączeniem.

  • android:priority Wartość tego atrybutu liczbowego (mającego wpływ tylko na wartość statycznych nakładek) konfiguruje pierwszeństwo nakładki w przypadku wielu statycznych nakładki są kierowane na tę samą wartość zasobu. Im wyższa liczba, tym większa pierwszeństwo.

Poniższy kod to przykładowy 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>

Zmiany w Androidzie 11

W Androidzie 11 lub nowszym, jeśli plik konfiguracji to w lokalizacji partition/overlay/config/config.xml, nakładki są konfigurowane za pomocą ten plik oraz zasady android:isStatic i android:priority nie mają wpływu na które znajdują się na partycji. Definiowanie pliku konfiguracji nakładki w dowolnym wymusza pierwszeństwo partycji nakładki.

Oprócz tego Android 11 lub nowszy Zastosowanie statycznych nakładek do wpływania na wartości zasobów odczytywanych podczas pakietu instalacji. Częstą praktyką jest używanie nakładek statycznych do zmiany wartości logicznych, które konfigurują stan włączenia komponentu, należy użyć funkcji <component-override> tag SystemConfig (nowy w Androidzie) 11).

Debugowanie nakładek

Aby ręcznie włączyć, wyłączyć i skopiować nakładki, użyj następującej nakładki: polecenia powłoki menedżera.

adb shell cmd overlay

OverlayManagerService używa idmap2 do mapowania identyfikatorów zasobów w lokalizacji docelowej do identyfikatorów zasobów w pakiecie nakładki. Wygenerowane mapowania identyfikatorów są następujące: przechowywane w /data/resource-cache/. Jeśli nakładka nie działa prawidłowo, odpowiedni plik idmap z nakładką w języku: /data/resource-cache/, a następnie uruchom następujące polecenie.

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

To polecenie powoduje wydrukowanie mapowania zasobów w sposób pokazany poniżej.

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