Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Runtime Resource Overlays (RROs)

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

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

Sumber daya overlay

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

Menyiapkan manifes

Paket dianggap sebagai paket RRO jika berisi tag <overlay> sebagai anak dari tag <manifest> .

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

  • Nilai atribut android:targetName opsional menentukan nama subset resource yang dapat dihamparkan dari paket target yang ingin dihamparkan oleh RRO. Jika target tidak menentukan kumpulan sumber daya yang dapat dihamparkan, atribut ini tidak boleh 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 > dalam manifes harus disetel ke false .

Mendefinisikan 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 dihamparkan dan nilai penggantinya, lalu menyetel nilai 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 hamparan.

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

Membangun paket

Android 11 atau yang lebih tinggi mendukung aturan build Soong untuk overlay yang mencegah Android Asset Packaging Tool 2 (AAPT2) mencoba menghapus 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",
}

Mengatasi sumber daya

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

Misalnya, jika hamparan 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 ditentukan target.

Overlay dapat mereferensikan resource-nya sendiri, dengan perilaku yang berbeda di antara rilis Android.

  • Di Android 11 atau lebih tinggi, setiap overlay memiliki ruang ID resource yang dipesan sendiri yang tidak tumpang tindih dengan ruang ID resource target atau ruang ID resource overlay lainnya, jadi overlay yang mereferensikan resource mereka berfungsi seperti yang diharapkan.

  • Di Android 10 atau lebih rendah, overlay dan paket target berbagi ruang ID resource yang sama, yang dapat menyebabkan benturan dan perilaku tidak terduga saat mencoba mereferensikan resource mereka sendiri menggunakan sintaks @type/name .

Mengaktifkan / menonaktifkan overlay

Gunakan API OverlayManager untuk mengaktifkan dan menonaktifkan overlay yang dapat diubah (ambil antarmuka API menggunakan Context#getSystemService(Context.OVERLAY_SERVICE) ). Hamparan hanya dapat diaktifkan dengan paket yang ditargetkannya atau dengan paket dengan izin android.permission.CHANGE_OVERLAY_PACKAGES . Saat overlay diaktifkan atau dinonaktifkan, peristiwa perubahan konfigurasi menyebar ke paket target dan peluncuran ulang aktivitas target.

Membatasi sumber daya yang dapat tumpang tindih

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

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

APK dapat menentukan beberapa <overlayable> , tetapi setiap tag harus memiliki nama unik di dalam paket. Misalnya:

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

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

Kode berikut menunjukkan contoh overlay di 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 dihamparkan tetapi tidak menggunakan android:targetName untuk menargetkan tag <overlayable> .

Membatasi kebijakan

Gunakan tag <policy> untuk memberlakukan 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 menimpa sumber daya.
  • system . Setiap overlay pada partisi sistem dapat menimpa sumber daya.
  • vendor . Setiap overlay pada partisi vendor dapat menimpa sumber daya.
  • product . Setiap overlay pada partisi produk dapat menimpa sumber daya.
  • signature . Overlay apa pun yang ditandatangani dengan tanda tangan yang sama dengan APK target dapat mengganti resource.

Kode berikut menunjukkan contoh <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 bilah vertikal (|) sebagai karakter pemisah. Jika beberapa kebijakan ditentukan, hamparan hanya perlu memenuhi satu kebijakan untuk mengganti sumber daya yang tercantum dalam tag <policy> .

Mengonfigurasi overlay

Android mendukung berbagai mekanisme 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 direkomendasikan untuk overlay.

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

Menggunakan 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 dari overlay yang akan dikonfigurasi. Untuk dikonfigurasi, overlay harus berada di direktori overlay/ dari partisi tempat 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> membutuhkan atribut package yang menunjukkan paket overlay mana yang sedang dikonfigurasi. Atribut enabled opsional mengontrol apakah hamparan diaktifkan secara default (defaultnya false ). Atribut opsional yang mutable mengontrol apakah hamparan dapat diubah atau tidak dan status aktifnya dapat diubah secara terprogram pada waktu proses (defaultnya adalah true ). Overlay yang tidak terdaftar dalam file konfigurasi dapat berubah dan dinonaktifkan secara default.

Prioritas hamparan

Jika beberapa overlay menimpa sumber daya yang sama, urutan dari overlay menjadi penting. Hamparan memiliki prioritas yang lebih tinggi daripada hamparan dengan konfigurasi yang mendahului konfigurasinya sendiri. Urutan prioritas hamparan di partisi yang berbeda (dari prioritas terkecil hingga terbesar) adalah sebagai berikut.

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

Menggabungkan file

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

Menggunakan atribut manifes (RRO statis)

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

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

  • android:priority . Nilai atribut numerik ini (yang hanya memengaruhi hamparan statis) mengonfigurasi prioritas hamparan saat 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 itu dan android:isStatic dan 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 yang lebih tinggi menghapus kemampuan untuk menggunakan overlay statis untuk memengaruhi nilai resource yang dibaca selama penginstalan paket. Untuk kasus penggunaan umum penggunaan hamparan statis untuk mengubah nilai boolean yang mengonfigurasi status komponen aktif, gunakan <component-override> SystemConfig (baru di Android 11).

Debugging overlay

Untuk mengaktifkan, menonaktifkan, dan membuang overlay secara manual, gunakan perintah shell manager 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 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