Çalışma Zamanı Kaynak Bindirmeleri (RRO'lar)

Çalışma zamanı kaynak yerleşimi (RRO), çalışma zamanında hedef paketin kaynak değerlerini değiştiren bir pakettir. Örneğin, sistem görüntüsüne yüklenen bir uygulama, davranışını bir kaynağın değerine göre değiştirebilir. Kaynak değerini derleme zamanında sabit kodlamak yerine, farklı bir bölüme yüklenen bir RRO, uygulama kaynaklarının değerlerini çalışma zamanında değiştirebilir.

RRO'lar etkinleştirilebilir veya devre dışı bırakılabilir. Bir RRO'nun kaynak değerlerini değiştirme yeteneğini değiştirmek için etkinleştirme/devre dışı bırakma durumunu programlı olarak ayarlayabilirsiniz. RRO'lar varsayılan olarak devre dışıdır (ancak, statik RRO'lar varsayılan olarak etkindir).

Kaynakları bindirme

Kaplamalar, kaplama paketinde tanımlanan kaynakları hedef pakette tanımlanan kaynaklarla eşleyerek çalışır. Bir uygulama, hedef paketteki bir kaynağın değerini çözmeye çalıştığında, bunun yerine hedef kaynağın eşlendiği yer paylaşımlı kaynağın değeri döndürülür.

Manifest'i ayarlama

Bir paket, <manifest> etiketinin alt öğesi olarak bir <overlay> etiketi içeriyorsa, RRO paketi olarak kabul edilir.

  • Gerekli android:targetPackage özniteliğinin değeri, RRO'nun kaplamayı amaçladığı paketin adını belirtir.

  • İsteğe bağlı android:targetName özniteliğinin değeri, RRO'nun kaplamayı amaçladığı hedef paketin bindirilebilir kaynak alt kümesinin adını belirtir. Hedef, üst üste bindirilebilir bir kaynak kümesi tanımlamıyorsa, bu öznitelik mevcut olmamalıdır.

Aşağıdaki kod, örnek bir yer paylaşımı AndroidManifest.xml gösterir.

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

Bindirmeler kodu kaplayamaz, dolayısıyla DEX dosyalarına sahip olamazlar. Ayrıca, bildirimdeki <application > etiketinin android:hasCode özniteliği false olarak ayarlanmalıdır.

Kaynak haritasını tanımlama

Android 11 veya sonraki sürümlerde, bindirme kaynakları haritasını tanımlamak için önerilen mekanizma, bindirme paketinin res/xml dizininde bir dosya oluşturmak, üst üste bindirilmesi gereken hedef kaynakları ve bunların değiştirme değerlerini numaralandırmak, ardından değerini ayarlamaktır. <overlay> manifest etiketinin android:resourcesMap özniteliği, kaynak eşleme dosyasına bir başvuruya.

Aşağıdaki kod, örnek bir res/xml/overlays.xml dosyasını gösterir.

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

Aşağıdaki kod, örnek bir bindirme bildirimini gösterir.

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

Paketi oluşturmak

Android 11 veya sonraki sürümleri, Android Asset Packaging Tool 2'nin (AAPT2) aynı değere sahip kaynakların yapılandırmalarını tekilleştirmeye çalışmasını ( --no-resource-deduping ) ve varsayılan yapılandırmalar olmadan kaynakları kaldırmasını ( --no-resource-removal ). Aşağıdaki kod, örnek bir Android.bp dosyasını gösterir.

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

Kaynakları çözme

Bir hedef kaynak veya kaplama kaynağı, sorgulanan kaynak için tanımlanmış birden çok yapılandırmaya sahipse, kaynakların çalışma zamanı, cihaz yapılandırmasının yapılandırmasıyla en iyi eşleşen yapılandırmanın değerini döndürür. Hangi yapılandırmanın en iyi eşleşen yapılandırma olduğunu belirlemek için, kaplama kaynak yapılandırmaları kümesini hedef kaynak yapılandırmaları kümesiyle birleştirin ve ardından normal kaynak çözümleme akışını izleyin (ayrıntılar için Android en uygun kaynağı nasıl bulur bölümüne bakın).

Örneğin, bir bindirme, drawable-en yapılandırması için bir değer tanımlarsa ve hedef, drawable-en-port için bir değer tanımlarsa, drawable-en-port daha iyi bir eşleşmeye sahiptir, dolayısıyla, drawable-en-port hedef yapılandırmasının değeri şöyle olur: çalışma zamanında seçilir. Tüm drawable-en konfigürasyonları kaplamak için kaplama, hedefin tanımladığı her drawable-en konfigürasyon için bir değer tanımlamalıdır.

Yer paylaşımları, Android sürümleri arasında farklı davranışlarla kendi kaynaklarına başvurabilir.

  • Android 11 veya sonraki sürümlerde, her kaplamanın hedef kaynak kimliği alanıyla veya diğer kaplama kaynak kimliği alanlarıyla çakışmayan kendi ayrılmış kaynak kimliği alanı vardır, bu nedenle kendi kaynaklarına başvuran kaplamalar beklendiği gibi çalışır.

  • Android 10 veya önceki sürümlerde, kaplamalar ve hedef paketler aynı kaynak kimliği alanını paylaşır; bu, @type/name sözdizimini kullanarak kendi kaynaklarına başvurmaya çalıştıklarında çakışmalara ve beklenmeyen davranışlara neden olabilir.

Bindirmeleri etkinleştirme/devre dışı bırakma

Değiştirilebilir kaplamaları etkinleştirmek ve devre dışı bırakmak için OverlayManager API'sini kullanın ( Context#getSystemService(Context.OVERLAY_SERVICE) kullanarak API arayüzünü alın). Bir yer paylaşımı, yalnızca hedeflediği paket tarafından veya android.permission.CHANGE_OVERLAY_PACKAGES iznine sahip bir paket tarafından etkinleştirilebilir. Bir kaplama etkinleştirildiğinde veya devre dışı bırakıldığında, yapılandırma değişikliği olayları hedef pakete yayılır ve hedef etkinlikler yeniden başlatılır.

Üst üste bindirilebilir kaynakları kısıtlama

Android 10 veya sonraki sürümlerde, <overlayable> XML etiketi, RRO'ların bindirmesine izin verilen bir dizi kaynağı ortaya çıkarır. Aşağıdaki örnekte res/values/overlayable.xml dosyasında, string/foo ve integer/bar , aygıtın görünümünü oluşturmak için kullanılan kaynaklardır; bu kaynakları kaplamak için, kaplamanın açık bir şekilde kaplama kaynakların koleksiyonunu ada göre hedeflemesi gerekir.

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

Bir APK, birden çok <overlayable> etiketi tanımlayabilir, ancak her etiketin paket içinde benzersiz bir adı olmalıdır. Örneğin:

  • Her ikisinin de <overlayable name="foo"> tanımlaması için iki farklı paket için tamam.

  • Tek bir APK'nın iki <overlayable name="foo"> bloğuna sahip olması uygun değil.

Aşağıdaki kod, AndroidManifest.xml dosyasındaki bir kaplama örneğini gösterir.

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

Bir uygulama bir <overlayable> etiketi tanımladığında, o uygulamayı hedefleyen bindirmeler:

  • targetName belirtilmelidir.

  • Yalnızca <overlayable> etiketinde listelenen kaynakları kaplayabilir.

  • Yalnızca bir <overlayable> adı hedefleyebilir.

Bindirilebilir kaynakları ortaya çıkaran ancak belirli bir <overlayable> etiketini hedeflemek için android:targetName kullanmayan bir paketi hedefleyen bir kaplamayı etkinleştiremezsiniz.

kısıtlama politikaları

Üst üste bindirilebilir kaynaklar üzerindeki kısıtlamaları uygulamak için <policy> etiketini kullanın. type özelliği, dahil edilen kaynakları geçersiz kılmak için bir kaplamanın hangi ilkeleri yerine getirmesi gerektiğini belirtir. Desteklenen türler aşağıdakileri içerir.

  • public . Herhangi bir kaplama, kaynağı geçersiz kılabilir.
  • system . Sistem bölümündeki herhangi bir kaplama, kaynakları geçersiz kılabilir.
  • vendor . Satıcı bölümündeki herhangi bir kaplama, kaynakları geçersiz kılabilir.
  • product . Ürün bölümündeki herhangi bir kaplama, kaynakları geçersiz kılabilir.
  • signature Hedef APK ile aynı imzayla imzalanmış herhangi bir bindirme, kaynakları geçersiz kılabilir.

Aşağıdaki kod, res/values/overlayable.xml dosyasındaki örnek bir <policy> etiketini gösterir.

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

Birden çok ilke belirtmek için ayırıcı karakterler olarak dikey çubuklar (|) kullanın. Birden çok ilke belirtildiğinde, bir kaplamanın <policy> etiketinde listelenen kaynakları geçersiz kılmak için yalnızca bir ilkeyi yerine getirmesi gerekir.

Bindirmeleri yapılandırma

Android, Android yayın sürümüne bağlı olarak yer paylaşımlarının değişebilirliğini, varsayılan durumunu ve önceliğini yapılandırmak için farklı mekanizmaları destekler.

  • Android 11 veya sonraki sürümleri çalıştıran cihazlar, bildirim öznitelikleri yerine bir OverlayConfig dosyası ( config.xml ) kullanabilir. Bir bindirme dosyası kullanmak, bindirmeler için önerilen yöntemdir.

  • Tüm cihazlar, statik RRO'ları yapılandırmak için bildirim özniteliklerini ( android:isStatic ve android:priority ) kullanabilir.

OverlayConfig'i kullanma

Android 11 veya sonraki sürümlerde, yer paylaşımlarının değişebilirliğini, varsayılan durumunu ve önceliğini yapılandırmak için OverlayConfig kullanabilirsiniz. Bir kaplamayı yapılandırmak için, partition/overlay/config/config.xml bulunan dosyayı oluşturun veya değiştirin; burada partition , yapılandırılacak bindirmenin bölümüdür. Yapılandırılması için, bindirmenin yapılandırıldığı bölümün overlay/ dizininde bir kaplama bulunmalıdır. Aşağıdaki kod, bir product/overlay/config/config.xml örneğini gösterir.

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

<overlay> etiketi, hangi bindirme paketinin yapılandırıldığını gösteren bir package özniteliği gerektirir. İsteğe bağlı enabled özniteliği, kaplamanın varsayılan olarak etkinleştirilip etkinleştirilmediğini denetler (varsayılan olarak false ). İsteğe bağlı mutable özniteliği, kaplamanın değişebilir olup olmadığını denetler ve etkin durumunun çalışma zamanında programlı olarak değiştirilmesini sağlayabilir (varsayılan true ). Bir yapılandırma dosyasında listelenmeyen kaplamalar değiştirilebilir ve varsayılan olarak devre dışıdır.

Yer paylaşımı önceliği

Birden çok kaplama aynı kaynakları geçersiz kıldığında, kaplamaların sırası önemlidir. Bir bindirme, konfigürasyonları kendi konfigürasyonundan önce gelen bindirmelerden daha büyük önceliğe sahiptir. Farklı bölümlerdeki bindirmelerin öncelik sırası (en küçükten en büyüğe) aşağıdaki gibidir.

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

Dosyaları birleştirme

<merge> etiketlerinin kullanılması, diğer konfigürasyon dosyalarının konfigürasyon dosyasında belirtilen konumda birleştirilmesine izin verir. Etiketin path özelliği, bindirme yapılandırma dosyalarını içeren dizine göre birleştirilecek dosyanın yolunu temsil eder.

Bildirim niteliklerini kullanma (statik RRO'lar)

Android 10 veya önceki sürümlerde, yer paylaşımı değişmezliği ve öncelik, aşağıdaki bildirim öznitelikleri kullanılarak yapılandırılır.

  • android:isStatic . Bu boole özelliğinin değeri true olarak ayarlandığında, kaplama varsayılan olarak etkinleştirilir ve değişmezdir, bu da kaplamanın devre dışı bırakılmasını önler.

  • android:priority . Bu sayısal özniteliğin değeri (yalnızca statik kaplamaları etkiler), birden çok statik kaplama aynı kaynak değerini hedeflediğinde kaplamanın önceliğini yapılandırır. Daha yüksek bir sayı, daha yüksek bir önceliği gösterir.

Aşağıdaki kod, bir örnek AndroidManifest.xml gösterir.

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

Android 11'deki değişiklikler

Android 11 veya sonraki sürümlerde, partition/overlay/config/config.xml içinde bir yapılandırma dosyası bulunuyorsa, bindirmeler bu dosya kullanılarak yapılandırılır ve android:isStatic ve android:priority , bölümde bulunan bindirmeler üzerinde bir etkiye sahip değildir. Herhangi bir bölümde bir bindirme yapılandırma dosyası tanımlamak, bindirme bölümü önceliğini zorlar.

Ek olarak, Android 11 veya sonraki sürümler, paket yüklemesi sırasında okunan kaynakların değerlerini etkilemek için statik bindirmeleri kullanma özelliğini kaldırır. Bileşen etkin durumunu yapılandıran booleanların değerini değiştirmek üzere statik bindirmeleri kullanmanın yaygın kullanım durumu için <component-override> SystemConfig etiketini kullanın (Android 11'de yeni).

Bindirmelerde hata ayıklama

Kaplamaları manuel olarak etkinleştirmek, devre dışı bırakmak ve boşaltmak için aşağıdaki kaplama yöneticisi kabuk komutunu kullanın.

adb shell cmd overlay

OverlayManagerService , hedef paketteki kaynak kimliklerini yer paylaşımı paketindeki kaynak kimlikleriyle eşleştirmek için idmap2 kullanır. Oluşturulan kimlik eşlemeleri /data/resource-cache/ içinde saklanır. Bindirmeniz düzgün çalışmıyorsa, bindirmeniz için ilgili idmap dosyasını /data/resource-cache/ içinde bulun ve ardından aşağıdaki komutu çalıştırın.

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

Bu komut, aşağıda gösterildiği gibi kaynakların eşlenmesini yazdırır.

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