Mengubah nilai sumber daya aplikasi pada waktu proses

Runtime resource overlay (RRO) adalah paket yang mengubah nilai sumber daya paket target saat runtime. Misalnya, aplikasi yang diinstal pada citra sistem mungkin mengubah perilakunya berdasarkan nilai sumber daya. Daripada melakukan hardcoding pada nilai sumber daya pada waktu build, RRO yang diinstal pada partisi berbeda dapat mengubah nilai sumber daya aplikasi pada waktu proses.

RRO dapat diaktifkan atau dinonaktifkan. Anda dapat secara terprogram mengatur status aktifkan/nonaktifkan untuk mengaktifkan kemampuan RRO dalam mengubah nilai sumber daya. RRO dinonaktifkan secara default (namun, RRO statis diaktifkan secara default).

Sumber daya hamparan

Overlay bekerja dengan memetakan sumber daya yang ditentukan dalam paket overlay ke sumber daya yang ditentukan dalam paket target. Saat aplikasi mencoba menyelesaikan nilai sumber daya dalam paket target, nilai sumber daya hamparan tempat sumber daya target dipetakan akan dikembalikan.

Siapkan manifes

Sebuah paket dianggap sebagai paket RRO jika berisi tag <overlay> sebagai turunan dari tag <manifest> .

  • Nilai atribut android:targetPackage yang diperlukan menentukan nama paket yang ingin dihamparkan RRO.

  • Nilai atribut opsional android:targetName menentukan nama subset sumber daya yang dapat dihamparkan dari paket target yang ingin dihamparkan oleh RRO. Jika target tidak menentukan kumpulan sumber daya yang dapat dihamparkan, atribut ini tidak akan ada.

Kode berikut menunjukkan contoh 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>

Overlay tidak dapat menghamparkan kode, sehingga tidak dapat memiliki file DEX. Selain itu, atribut android:hasCode dari tag <application > di manifes harus disetel ke false .

Tentukan peta sumber daya

Di Android 11 atau lebih tinggi, mekanisme yang direkomendasikan untuk menentukan peta sumber daya overlay adalah dengan membuat file di direktori res/xml paket overlay, menghitung sumber daya target yang harus di-overlay dan nilai penggantinya, lalu menetapkan nilai atribut android:resourcesMap dari tag manifes <overlay> ke referensi ke file pemetaan sumber daya.

Kode berikut menunjukkan contoh file 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>

Kode berikut menunjukkan contoh manifes 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"
                   android:resourcesMap="@xml/overlays"/>
</manifest>

Bangun paketnya

Android 11 atau lebih tinggi mendukung aturan build Soong untuk overlay yang mencegah Android Asset Packaging Tool 2 (AAPT2) mencoba menghapus duplikat konfigurasi resource dengan nilai yang sama ( --no-resource-deduping ) dan menghapus resource tanpa konfigurasi default ( --no-resource-removal ). Kode berikut menunjukkan contoh file Android.bp .

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

Selesaikan sumber daya

Jika sumber daya target atau sumber daya overlay memiliki beberapa konfigurasi yang ditentukan untuk sumber daya yang dikueri, runtime sumber daya akan mengembalikan nilai konfigurasi yang paling cocok dengan konfigurasi konfigurasi perangkat. Untuk menentukan konfigurasi mana yang merupakan konfigurasi paling cocok, gabungkan kumpulan konfigurasi sumber daya overlay ke dalam kumpulan konfigurasi sumber daya target, lalu ikuti alur resolusi sumber daya reguler (untuk detailnya, lihat Cara Android menemukan sumber daya yang paling cocok ).

Misalnya, jika overlay menentukan nilai untuk konfigurasi drawable-en dan target menentukan nilai untuk drawable-en-port , drawable-en-port memiliki kecocokan yang lebih baik sehingga nilai konfigurasi target drawable-en-port adalah dipilih saat runtime. Untuk menghamparkan semua konfigurasi drawable-en , overlay harus menentukan nilai untuk setiap konfigurasi drawable-en yang ditentukan target.

Hamparan dapat mereferensikan sumber dayanya sendiri, dengan perilaku berbeda antar rilis Android.

  • Di Android 11 atau lebih tinggi, setiap overlay memiliki ruang ID sumber daya cadangannya sendiri yang tidak tumpang tindih dengan ruang ID sumber daya target atau ruang ID sumber daya overlay lainnya, sehingga overlay yang mereferensikan sumber dayanya berfungsi seperti yang diharapkan.

  • Di Android 10 atau yang lebih rendah, overlay dan paket target berbagi ruang ID sumber daya yang sama, yang dapat menyebabkan tabrakan dan perilaku tidak terduga saat mencoba mereferensikan sumber dayanya sendiri menggunakan sintaksis @type/name .

Mengaktifkan/menonaktifkan overlay

Gunakan API OverlayManager untuk mengaktifkan dan menonaktifkan overlay yang dapat diubah (mengambil antarmuka API menggunakan Context#getSystemService(Context.OVERLAY_SERVICE) ). Hamparan hanya dapat diaktifkan oleh paket targetnya atau oleh paket dengan izin android.permission.CHANGE_OVERLAY_PACKAGES . Saat overlay diaktifkan atau dinonaktifkan, peristiwa perubahan konfigurasi disebarkan ke paket target dan aktivitas target diluncurkan kembali.

Batasi sumber daya yang dapat dihamparkan

Di Android 10 atau lebih tinggi, tag XML <overlayable> menampilkan sekumpulan resource yang boleh dihamparkan oleh RRO. Dalam contoh file res/values/overlayable.xml berikut, string/foo dan integer/bar adalah sumber daya yang digunakan untuk menentukan tema tampilan perangkat; untuk menghamparkan sumber daya ini, hamparan harus secara eksplisit menargetkan kumpulan sumber daya yang dapat dihamparkan berdasarkan nama.

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

Sebuah APK dapat mendefinisikan beberapa tag <overlayable> , namun setiap tag harus memiliki nama unik di dalam paketnya. Misalnya, itu adalah:

  • OK untuk dua paket berbeda untuk mendefinisikan <overlayable name="foo"> .

  • Tidak diperbolehkan jika satu APK memiliki dua blok <overlayable name="foo"> .

Kode berikut menunjukkan contoh overlay pada 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>

Saat aplikasi menentukan tag <overlayable> , overlay menargetkan aplikasi tersebut:

  • Harus menentukan targetName .

  • Hanya dapat menghamparkan sumber daya yang tercantum dalam tag <overlayable> .

  • Hanya dapat menargetkan satu nama <overlayable> .

Anda tidak dapat mengaktifkan overlay yang menargetkan paket yang mengekspos sumber daya yang dapat di-overlay, namun tidak menggunakan android:targetName untuk menargetkan tag <overlayable> tertentu.

Batasi kebijakan

Gunakan tag <policy> untuk menerapkan pembatasan pada sumber daya yang dapat dihamparkan. Atribut type menentukan kebijakan mana yang harus dipenuhi oleh overlay untuk mengganti sumber daya yang disertakan. Jenis yang didukung meliputi berikut ini.

  • public . Hamparan apa pun dapat menggantikan sumber daya.
  • system . Hamparan apa pun pada partisi sistem dapat menimpa sumber daya.
  • vendor . Hamparan apa pun pada partisi vendor dapat menimpa sumber daya.
  • product . Hamparan apa pun pada partisi produk dapat menimpa sumber daya.
  • oem . Hamparan apa pun pada partisi oem dapat menimpa sumber daya.
  • odm . Hamparan apa pun pada partisi odm dapat menimpa sumber daya.
  • signature . Hamparan apa pun yang ditandatangani dengan tanda tangan yang sama dengan APK target dapat menggantikan sumber daya.
  • actor . Hamparan apa pun yang ditandatangani dengan tanda tangan yang sama dengan APK aktor dapat menggantikan sumber daya. Aktor dideklarasikan dalam tag bernama-aktor di konfigurasi sistem.
  • config_signature . Hamparan apa pun yang ditandatangani dengan tanda tangan yang sama dengan apk overlay-config dapat menggantikan sumber daya. Overlay-config dideklarasikan dalam tag overlay-config-signature di konfigurasi sistem.

Kode berikut menunjukkan contoh tag <policy> di 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>

Untuk menentukan beberapa kebijakan, gunakan batang vertikal (|) sebagai karakter pemisah. Jika beberapa kebijakan ditentukan, overlay hanya perlu memenuhi satu kebijakan untuk mengambil alih sumber daya yang tercantum dalam tag <policy> .

Konfigurasikan overlay

Android mendukung mekanisme berbeda untuk mengonfigurasi mutabilitas, status default, dan prioritas overlay bergantung pada versi rilis Android.

  • Perangkat yang menjalankan Android 11 atau lebih tinggi dapat menggunakan file OverlayConfig ( config.xml ) sebagai ganti atribut manifes. Menggunakan file overlay adalah metode yang disarankan untuk overlay.

  • Semua perangkat dapat menggunakan atribut manifes ( android:isStatic dan android:priority ) untuk mengonfigurasi RRO statis.

Gunakan OverlayConfig

Di Android 11 atau lebih tinggi, Anda dapat menggunakan OverlayConfig untuk mengonfigurasi mutabilitas, status default, dan prioritas overlay. Untuk mengkonfigurasi overlay, buat atau modifikasi file yang terletak di partition/overlay/config/config.xml , di mana partition adalah partisi overlay yang akan dikonfigurasi. Untuk dikonfigurasi, overlay harus berada di direktori overlay/ partisi di mana overlay dikonfigurasi. Kode berikut menunjukkan contoh 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> memerlukan atribut package yang menunjukkan paket overlay mana yang sedang dikonfigurasi. Atribut opsional enabled mengontrol apakah overlay diaktifkan secara default atau tidak (standarnya adalah false ). Atribut opsional yang dapat mutable mengontrol apakah overlay dapat diubah atau tidak dan status aktifnya dapat diubah secara terprogram saat waktu proses (standarnya adalah true ). Hamparan yang tidak tercantum dalam file konfigurasi dapat diubah dan dinonaktifkan secara default.

Prioritas overlay

Jika beberapa overlay mengambil alih sumber daya yang sama, urutan overlay menjadi penting. Hamparan memiliki prioritas lebih besar dibandingkan overlay dengan konfigurasi yang mendahului konfigurasinya sendiri. Urutan prioritas overlay pada partisi yang berbeda (dari prioritas terkecil hingga terbesar) adalah sebagai berikut.

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

Gabungkan file

Penggunaan tag <merge> memungkinkan file konfigurasi lain digabungkan pada posisi yang ditentukan ke dalam file konfigurasi. Atribut path dari tag mewakili jalur file yang akan digabungkan relatif terhadap direktori yang berisi file konfigurasi overlay.

Gunakan atribut manifes/RRO statis

Di Android 10 atau lebih rendah, kekekalan dan prioritas overlay dikonfigurasikan menggunakan atribut manifes berikut.

  • android:isStatic . Jika nilai atribut boolean ini disetel ke true , overlay diaktifkan secara default dan tidak dapat diubah, sehingga mencegah overlay dinonaktifkan.

  • android:priority . Nilai atribut numerik ini (yang hanya memengaruhi hamparan statis) mengonfigurasi prioritas hamparan ketika beberapa hamparan statis menargetkan nilai sumber daya yang sama. Angka yang lebih tinggi menunjukkan prioritas yang lebih tinggi.

Kode berikut menunjukkan contoh 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>

Perubahan di Android 11

Di Android 11 atau lebih tinggi, jika file konfigurasi terletak di partition/overlay/config/config.xml , overlay dikonfigurasi menggunakan file tersebut dan android:isStatic serta android:priority tidak berpengaruh pada overlay yang terletak di partisi. Mendefinisikan file konfigurasi overlay di partisi mana pun akan menerapkan prioritas partisi overlay.

Selain itu, Android 11 atau lebih tinggi menghilangkan kemampuan menggunakan overlay statis untuk memengaruhi nilai sumber daya yang dibaca selama instalasi paket. Untuk kasus penggunaan umum penggunaan overlay statis guna mengubah nilai boolean yang mengonfigurasi status komponen diaktifkan, gunakan tag SystemConfig <component-override> (yang baru di Android 11).

Men-debug hamparan

Untuk mengaktifkan, menonaktifkan, dan membuang overlay secara manual, gunakan perintah shell manajer overlay berikut.

adb shell cmd overlay

OverlayManagerService menggunakan idmap2 untuk memetakan ID sumber daya dalam paket target ke ID sumber daya dalam paket overlay. Pemetaan ID yang dihasilkan disimpan di /data/resource-cache/ . Jika overlay Anda tidak berfungsi dengan benar, temukan file idmap yang sesuai untuk overlay Anda di /data/resource-cache/ , lalu jalankan perintah berikut.

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

Perintah ini mencetak pemetaan sumber daya seperti yang ditunjukkan di bawah ini.

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