Runtime resource overlay (RRO) adalah paket yang mengubah nilai resource paket target saat runtime. Misalnya, aplikasi yang diinstal pada image sistem dapat mengubah perilakunya berdasarkan nilai resource. Daripada melakukan hardcode nilai resource pada waktu build, RRO yang diinstal pada partisi yang berbeda dapat mengubah nilai resource aplikasi saat runtime.
RRO dapat diaktifkan atau dinonaktifkan. Anda dapat menetapkan status aktifkan/nonaktifkan secara terprogram untuk mengalihkan kemampuan RRO guna mengubah nilai resource. RRO dinonaktifkan secara default (tetapi, RRO statis diaktifkan secara default).
Resource overlay
Overlay berfungsi dengan memetakan resource yang ditentukan dalam paket overlay ke resource yang ditetapkan dalam paket target. Saat aplikasi mencoba me-resolve nilai resource dalam paket target, nilai resource overlay yang dipetakan ke resource target akan ditampilkan.
Menyiapkan manifes
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 ditempatkan oleh RRO untuk ditempatkan.Nilai atribut
android:targetName
opsional menentukan nama subset resource yang dapat ditempatkan dari paket target yang ingin ditempatkan oleh RRO. Jika target tidak menentukan kumpulan resource yang dapat ditempatkan, 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 menempatkan kode, sehingga tidak dapat memiliki file DEX. Selain itu,
atribut android:hasCode
dari tag <application
> dalam manifes harus
ditetapkan ke false
.
Menentukan peta resource
Di Android 11 atau yang lebih tinggi, mekanisme yang direkomendasikan untuk
menentukan peta resource overlay adalah dengan membuat file dalam direktori res/xml
dari paket overlay, mengenumerasi resource target yang harus
ditempatkan secara luas dan nilai penggantinya, lalu menetapkan nilai atribut
android:resourcesMap
tag manifes <overlay>
ke referensi
ke file pemetaan resource.
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>
Mem-build paket
Android 11 atau yang lebih baru 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 dari menghapus resource tanpa konfigurasi
default (--no-resource-removal
). Kode berikut menampilkan contoh file
Android.bp
.
runtime_resource_overlay {
name: "ExampleOverlay",
sdk_version: "current",
}
Menyelesaikan resource
Jika resource target atau resource overlay memiliki beberapa konfigurasi yang ditentukan untuk resource yang dikueri, runtime resource akan menampilkan nilai konfigurasi yang paling sesuai dengan konfigurasi konfigurasi perangkat. Untuk menentukan konfigurasi mana yang merupakan konfigurasi yang paling cocok, gabungkan kumpulan konfigurasi resource overlay ke dalam kumpulan konfigurasi resource target, lalu ikuti alur resolusi resource reguler (untuk mengetahui detailnya, lihat Cara Android menemukan resource yang paling cocok).
Misalnya, jika overlay menentukan nilai untuk konfigurasi drawable-en
dan target menentukan nilai untuk drawable-en-port
, drawable-en-port
akan memiliki kecocokan yang lebih baik sehingga nilai konfigurasi target drawable-en-port
dipilih pada runtime. Untuk menempatkan semua konfigurasi drawable-en
, overlay
harus menentukan nilai untuk setiap konfigurasi drawable-en
yang ditentukan target.
Overlay dapat mereferensikan resource-nya sendiri, dengan perilaku yang berbeda di antara rilis Android.
Di Android 11 atau yang lebih tinggi, setiap overlay memiliki ruang ID resource yang dicadangkan sendiri yang tidak tumpang-tindih dengan ruang ID resource target atau ruang ID resource overlay lainnya, sehingga overlay yang mereferensikan resourcenya sendiri berfungsi seperti yang diharapkan.
Di Android 10 atau yang lebih lama, overlay dan paket target berbagi ruang ID resource yang sama, yang dapat menyebabkan konflik dan perilaku yang tidak terduga saat mencoba mereferensikan resource-nya sendiri menggunakan sintaksis
@type/name
.
Mengaktifkan/menonaktifkan overlay
Gunakan OverlayManager
API untuk mengaktifkan dan menonaktifkan overlay yang dapat diubah (ambil
antarmuka API menggunakan Context#getSystemService(Context.OVERLAY_SERVICE)
). Overlay
hanya dapat diaktifkan oleh paket yang ditargetkannya atau oleh paket dengan
izin android.permission.CHANGE_OVERLAY_PACKAGES
. Saat overlay
diaktifkan atau dinonaktifkan, peristiwa perubahan konfigurasi akan diterapkan ke paket target
dan aktivitas target akan diluncurkan ulang.
Membatasi resource yang dapat ditempatkan
Di Android 10 atau yang lebih tinggi, tag XML <overlayable>
mengekspos kumpulan resource
yang diizinkan untuk ditempatkan oleh RRO. Pada contoh file
res/values/overlayable.xml
berikut, string/foo
dan integer/bar
adalah resource
yang digunakan untuk memberi tema tampilan perangkat; untuk menempatkan resource ini, overlay
harus secara eksplisit menargetkan kumpulan resource yang dapat ditempatkan menurut 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>
APK dapat menentukan beberapa tag <overlayable>
, tetapi setiap tag harus memiliki nama
unik dalam paket. Misalnya, nilainya adalah:
Mengizinkan dua paket yang berbeda untuk menentukan
<overlayable name="foo">
.Tidak disarankan untuk satu APK memiliki dua blok
<overlayable name="foo">
.
Kode berikut menunjukkan contoh overlay dalam 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 yang menargetkan aplikasi tersebut:
Harus menentukan
targetName
.Hanya dapat menempatkan resource yang tercantum dalam tag
<overlayable>
.Hanya dapat menargetkan satu nama
<overlayable>
.
Anda tidak dapat mengaktifkan overlay yang menargetkan paket yang mengekspos resource
yang dapat di-overlay, tetapi tidak menggunakan android:targetName
untuk menargetkan tag
<overlayable>
tertentu.
Kebijakan pembatasan
Gunakan tag <policy>
untuk menerapkan batasan pada resource yang dapat ditempatkan. Atribut
type
menentukan kebijakan yang harus dipenuhi overlay untuk mengganti
resource yang disertakan. Jenis yang didukung meliputi hal berikut.
public
. Overlay apa pun dapat mengganti resource.system
. Overlay apa pun di partisi sistem dapat mengganti resource.vendor
. Overlay apa pun di partisi vendor dapat mengganti resource.product
. Setiap overlay pada partisi produk dapat mengganti resource.oem
. Overlay apa pun di partisi oem dapat mengganti resource.odm
. Overlay pada partisi odm dapat mengganti resource.signature
. Overlay apa pun yang ditandatangani dengan tanda tangan yang sama dengan APK target dapat mengganti resource.actor
. Overlay apa pun yang ditandatangani dengan tanda tangan yang sama dengan APK actor dapat mengganti resource. Pelaku dideklarasikan dalam tag Rename-actor dalam konfigurasi sistem.config_signature
. Setiap overlay yang ditandatangani dengan tanda tangan yang sama dengan apk overlay-config dapat mengganti resource. Konfigurasi overlay dideklarasikan dalam tag overlay-config-signature di konfigurasi sistem.
Kode berikut menunjukkan contoh tag <policy>
dalam
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 garis vertikal (|) sebagai karakter pemisah.
Jika beberapa kebijakan ditentukan, overlay hanya perlu memenuhi satu
kebijakan untuk mengganti resource 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 yang lebih tinggi dapat menggunakan file
OverlayConfig
(config.xml
), bukan atribut manifes. Menggunakan file overlay adalah metode yang direkomendasikan untuk overlay.Semua perangkat dapat menggunakan atribut manifes (
android:isStatic
danandroid:priority
) untuk mengonfigurasi RRO statis.
Menggunakan OverlayConfig
Di Android 11 atau yang lebih tinggi, Anda dapat menggunakan OverlayConfig
untuk
mengonfigurasi mutabilitas, status default, dan prioritas overlay. Untuk mengonfigurasi overlay, buat atau ubah file yang terletak di partition/overlay/config/config.xml
, dengan partition
adalah partisi overlay yang akan dikonfigurasi. Agar dapat dikonfigurasi, overlay harus berada di
direktori overlay/
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>
memerlukan atribut package
yang menunjukkan paket
overlay mana yang sedang dikonfigurasi. Atribut enabled
opsional mengontrol apakah
overlay diaktifkan secara default atau tidak (defaultnya adalah false
). Atribut
mutable
opsional mengontrol apakah overlay dapat diubah atau tidak dan dapat
mengubah status pengaktifannya secara terprogram saat runtime (defaultnya adalah true
).
Overlay yang tidak tercantum dalam file konfigurasi dapat diubah dan dinonaktifkan secara
default.
Prioritas overlay
Jika beberapa overlay mengganti resource yang sama, urutan overlay sangat penting. Overlay memiliki prioritas yang lebih besar daripada overlay dengan konfigurasi yang mendahului konfigurasinya sendiri. Urutan prioritas overlay dalam berbagai partisi (dari prioritas paling kecil hingga terbesar) adalah sebagai berikut.
system
vendor
odm
oem
product
system_ext
Gabungkan file
Penggunaan tag <merge>
memungkinkan file konfigurasi lainnya digabungkan pada posisi yang ditentukan ke dalam file konfigurasi. Atribut path
pada tag
mewakili jalur file yang akan digabungkan, secara relatif terhadap direktori yang berisi
file konfigurasi overlay.
Menggunakan atribut manifes/RRO statis
Di Android 10 atau yang lebih lama, ketidakmutlakan dan prioritas overlay dikonfigurasi menggunakan atribut manifes berikut.
android:isStatic
. Jika nilai atribut boolean ini ditetapkan ketrue
, overlay diaktifkan secara default dan tidak dapat diubah, sehingga mencegah overlay dinonaktifkan.android:priority
. Nilai atribut numerik ini (yang hanya memengaruhi overlay statis) mengonfigurasi prioritas overlay saat beberapa overlay statis menargetkan nilai resource 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 yang lebih tinggi, jika file konfigurasi
berada di partition/overlay/config/config.xml
, overlay dikonfigurasi menggunakan
file tersebut dan android:isStatic
serta android:priority
tidak berpengaruh pada
overlay yang berada di partisi. Menentukan 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 guna memengaruhi nilai resource yang dibaca selama penginstalan
paket. Untuk kasus penggunaan umum penggunaan overlay statis guna mengubah
nilai boolean yang mengonfigurasi status pengaktifan komponen, gunakan
tag <component-override>
SystemConfig
(baru di Android
11).
Overlay debug
Untuk mengaktifkan, menonaktifkan, dan membuang overlay secara manual, gunakan perintah shell pengelola overlay berikut.
adb shell cmd overlay
OverlayManagerService
menggunakan idmap2
untuk memetakan ID resource dalam paket
target ke ID resource dalam paket overlay. Pemetaan ID yang dihasilkan disimpan di /data/resource-cache/
. Jika overlay tidak berfungsi dengan benar, cari
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 resource 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