Uygulama kaynaklarının değerini çalışma zamanında değiştirme

Çalışma zamanı kaynak yer paylaşımı (RRO), kaynak değerlerini değiştiren bir pakettir bir hedef paketin sayısını gösterir. Örneğin, sistemde yüklü bir uygulama bir kaynağın değerine bağlı olarak, ilgili görselin davranışını değiştirebilir. Proje yönetimi kaynak değerini kaynak koda sabitlediğinizde, farklı bir bölüm, çalışma zamanında uygulama kaynaklarının değerlerini değiştirebilir.

RRO'lar etkinleştirilebilir veya devre dışı bırakılabilir. Her bir arama teriminin etkinleştirme/devre dışı bırakma durumunu kullanarak RRO'nun kaynak değerlerini değiştirme olanağını açar/kapatır. RRO'lar varsayılan olarak devre dışıdır (ancak statik RRO'lar varsayılan olarak ayarlanır).

Kaynakları bindirme

Bindirmeler, bindirme paketinde tanımlanan kaynakların kaynaklarla eşlenmesiyle çalışır hedef pakette tanımlıdır. Uygulama, bir hedef paketteki kaynak, hedef paket kaynağının kaynak eşlendiğinde döndürülür.

Manifest dosyasını ayarlama

Bir paket,<overlay> <manifest> etiketinin alt öğesidir.

  • Gerekli android:targetPackage özelliğinin değeri, adı belirtir kullanmayı planladığı anlamına gelir.

  • İsteğe bağlı android:targetName özelliğinin değeri, RRO'nun amaçladığı hedef paketin kaynakların yer paylaşımlı alt kümesi kullanabilirsiniz. Hedef, yer paylaşımlı bir kaynak kümesi tanımlamazsa özelliği bulunmamalıdır.

Aşağıdaki kodda AndroidManifest.xml yer paylaşımı örneği gösterilmektedir.

<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 kod yer paylaşımında bulunamaz, bu nedenle DEX dosyası içeremez. Ayrıca, <application> öğesinin android:hasCode özelliği etiketindeki değer false olarak ayarlandı.

Kaynak haritasını tanımlama

Android 11 veya sonraki sürümlerde bindirme kaynakları haritasını tanımlamak, res/xml içinde bir dosya oluşturmaktır dizinini oluşturmak isterseniz, olması gereken hedef kaynakları ve bunların değiştirilme değerlerini belirleyip Bir referansa <overlay> manifest etiketinin android:resourcesMap özelliği kaynak eşleme dosyasına ekleyin.

Aşağıdaki kodda örnek bir res/xml/overlays.xml dosyası gösterilmektedir.

<?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 kodda örnek bir yer paylaşımlı manifest gösterilmektedir.

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

Android 11 veya sonraki sürümler şunun için bir kapatg derleme kuralını destekler: Android Öğe Paketleme Aracı 2'nin (AAPT2) devre dışı bırakmaya çalışmasını önleyen yer paylaşımları aynı değere sahip kaynak yapılandırmalarını tekilleştirme (--no-resource-deduping) ve kaynakları varsayılan olmadan kaldırmaktan yapılandırma (--no-resource-removal). Aşağıdaki kodda bir örnek Android.bp dosyası.

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

Kaynakları çözün

Bir hedef kaynağın veya yer paylaşımlı kaynağın sorgulanan kaynağın çalışma zamanı, sorgu çalıştırılan en iyi eşleşen yapılandırma ayarlarını belirleyebilirsiniz. En iyi eşleşen yapılandırmanın hangisi olduğunu belirlemek için yer paylaşımlı kaynak yapılandırmaları kümesi ile hedef kaynak kümesi yapılandırma ve ardından normal kaynak çözümleme akışını (ör. ayrıntılı bilgi için Android, en iyi eşleşmeyi nasıl bulur? kaynak) gösterilir.

Örneğin, bir yer paylaşımı drawable-en yapılandırması için bir değer tanımlarsa ve hedef drawable-en-port için bir değer tanımlar: drawable-en-port daha iyi bir eşleşmeye sahip olduğundan drawable-en-port hedef yapılandırmasının çalışma zamanında seçilir. Tüm drawable-en yapılandırmalarını yer paylaşımlı olarak kullanmak için yer paylaşımı hedefin tanımladığı her drawable-en yapılandırması için bir değer tanımlamalıdır.

Bindirmeler, kendi kaynaklarına başvurabilir ve Android sürümleri

  • Android 11 veya sonraki sürümlerde her yer paylaşımının kendi bölümü vardır. hedef kaynak kimliği alanıyla çakışmayan, ayrılmış kaynak kimliği alanı veya diğer yer paylaşımlı kaynak kimliği alanları sayesinde, kendi kaynaklarına referans veren yer paylaşımları beklendiği gibi çalışıyor.

  • Android 10 veya önceki sürümlerde yer paylaşımları ve hedef paketler aynı kaynağı paylaşır. Kimlik alanı (bu kimlik alanı, denemeler yaptıklarında çakışmalara ve beklenmedik davranışlara neden olabilir) @type/name söz dizimini kullanarak kendi kaynaklarına başvuruda bulunmalıdır.

Yer paylaşımlarını etkinleştirme/devre dışı bırakma

Değişebilir yer paylaşımlarını etkinleştirmek ve devre dışı bırakmak için OverlayManager API'sini kullan (al Context#getSystemService(Context.OVERLAY_SERVICE) kullanan API arayüzü) kullanılır. yer paylaşımı, yalnızca hedeflediği paket tarafından veya android.permission.CHANGE_OVERLAY_PACKAGES izni. Yer paylaşımı Etkinleştirildiğinde veya devre dışı bırakıldığında, yapılandırma değişikliği etkinlikleri hedef pakete uygulanır ve hedef etkinlikler yeniden başlatılır.

Yer paylaşımlı kaynakları kısıtlama

Android 10 veya sonraki sürümlerde <overlayable> XML etiketi, bir dizi kaynağı gösterir. izin verildiğini gösterdik. Aşağıdaki örnekte res/values/overlayable.xml dosyası, string/foo ve integer/bar kaynaklar cihazın görünümü için tema oluşturmak; bu kaynakları bir araya getirip Yer paylaşımlı kaynakların koleksiyonunu ada göre açıkça hedeflemelidir.

<!-- 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 fazla <overlayable> etiketi tanımlayabilir ancak her etiketin benzersiz bir etiketi olmalıdır bir ad verebilirsiniz. Örneğin:

  • Tamam, her ikisi de <overlayable name="foo"> öğesini tanımlayan iki farklı paket için geçerlidir.

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

Aşağıdaki kod, AndroidManifest.xml öğesindeki bir yer paylaşımının örneğini gösterir dosyası olarak kaydedebilirsiniz.

<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, bu uygulamayı hedefleyen yer paylaşımları:

  • targetName belirtilmelidir.

  • Yalnızca <overlayable> etiketinde listelenen kaynaklarla yer paylaşımlı olabilir.

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

Yer paylaşımlı reklamlar görüntüleyen bir paketi hedefleyen yer paylaşımını etkinleştiremezsiniz kaynaklar ancak belirli bir hedefi hedeflemek için android:targetName kullanma <overlayable> etiketi.

Politikaları kısıtlama

Yer paylaşımlı kaynaklarda kısıtlamaları uygulamak için <policy> etiketini kullanın. İlgili içeriği oluşturmak için kullanılan type özelliği, bir yer paylaşımının geçersiz kılmak için hangi politikaları yerine getirmesi gerektiğini belirtir bazı kaynakları inceleyelim. Desteklenen türler şunlardır:

  • public Herhangi bir yer paylaşımı, kaynağı geçersiz kılabilir.
  • system Sistem bölümündeki herhangi bir yer paylaşımı, kaynakları geçersiz kılabilir.
  • vendor Tedarikçi firma bölümündeki herhangi bir yer paylaşımı, kaynakları geçersiz kılabilir.
  • product Ürün bölümündeki herhangi bir yer paylaşımı, kaynakları geçersiz kılabilir.
  • oem Oem bölümündeki herhangi bir yer paylaşımı, kaynakları geçersiz kılabilir.
  • odm Om bölümündeki herhangi bir yer paylaşımı, kaynakları geçersiz kılabilir.
  • signature Hedef APK ile aynı imzaya sahip olan herhangi bir yer paylaşımı kaynakları geçersiz kılmaktır.
  • actor İşlemi yapan APK ile aynı imzaya sahip herhangi bir yer paylaşımı kaynakları geçersiz kılmaktır. İşlemi gerçekleştiren, sistemdeki named-actor etiketinde tanımlandı yapılandırma.
  • config_signature overlay-config apk, kaynakları geçersiz kılabilir. yer paylaşımlı yapılandırma sistem yapılandırmasındaki overlay-config-signature etiketinde tanımlanmıştır.

Aşağıdaki kod, <policy> etiketini res/values/overlayable.xml dosya

<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 politika belirtmek için ayırıcı karakterler olarak dikey çubukları (|) kullanın. Birden fazla politika belirtildiğinde, yer paylaşımının yalnızca bir politikayı yerine getirmesi gerekir politikası ile birlikte <policy> etiketi içinde listelenen kaynakları geçersiz kılabilirsiniz.

Yer paylaşımlarını yapılandırma

Android, değişkenliği yapılandırmak için farklı mekanizmaları destekler. Varsayılan ayar durumunu ve yer paylaşımlarının önceliğini görebilirsiniz.

  • Android 11 veya sonraki sürümleri çalıştıran cihazlar OverlayConfig dosyası (config.xml) kullanmanız gerekir. Bir yer paylaşımlı dosya, yer paylaşımları için önerilen yöntemdir.

  • Tüm cihazlar manifest özelliklerini kullanabilir (android:isStatic ve android:priority).

ziyaret edin.

OverlayConfig kullanma

Android 11 veya sonraki sürümlerde OverlayConfig ile şunları yapabilirsiniz: yer paylaşımlarının değişkenliğini, varsayılan durumunu ve önceliğini yapılandırın. Yapılandırmak için veya yer paylaşımlı dosyayı partition/overlay/config/config.xml; burada partition, yapılandırılacak. Bir yer paylaşımının yapılandırılabilmesi için Yer paylaşımının yapılandırıldığı bölümün overlay/ dizini. İlgili içeriği oluşturmak için kullanılan aşağıdaki kodda bir product/overlay/config/config.xml örneği gösterilmektedir.

<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 için hangi yer paylaşımını belirten package özelliği gerekiyor paketi yapılandırılıyor. İsteğe bağlı enabled özelliği, veya yer paylaşımı varsayılan olarak etkin değildir (varsayılan olarak false). İsteğe bağlı mutable özelliği, yer paylaşımının değiştirilebilir olup olmadığını ve etkin durumu çalışma zamanında programatik olarak değiştirildi (varsayılan değer true). Yapılandırma dosyasında listelenmeyen bindirmeler, varsayılandır.

Yer paylaşımı önceliği

Birden fazla yer paylaşımı aynı kaynakları geçersiz kıldığında yer paylaşımları önemlidir. Yer paylaşımı, yapılandırmalı yer paylaşımlarından daha fazla önceliğe sahiptir kendi yapılandırmasından önce gelir. Farklı konumlardaki yer paylaşımlarının öncelik sırası bölümleri (en az öncelikliden en yüksek önceliğe) aşağıdaki gibidir.

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

Dosyaları birleştir

<merge> etiketlerinin kullanılması, diğer yapılandırma dosyalarının belirtilen konumu yapılandırma dosyasına ekleyin. Etiketin path özelliği birleştirilecek dosyanın, aşağıdakileri içeren dizine göre yolunu gösterir yer paylaşımlı yapılandırma dosyalarıdır.

Manifest özelliklerini/statik RRO'ları kullan

Android 10 veya önceki sürümlerde yer paylaşımı sabitliği ve önceliği aşağıdaki manifest özelliklerini içerir.

  • android:isStatic Bu boole özelliğinin değeri true olarak ayarlandığında, Yer paylaşımı varsayılan olarak etkindir ve sabit olduğundan, devre dışı bırakılmasını engeller.

  • android:priority Bu sayısal özelliğin değeri (yalnızca statik yer paylaşımları), birden fazla statik reklam öğesi olduğunda yer paylaşımları aynı kaynak değerini hedefler. Sayı yükseldikçe daha yüksek önceliklendirme.

Aşağıdaki kodda bir AndroidManifest.xml örneği gösterilmektedir.

<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 bir yapılandırma dosyası partition/overlay/config/config.xml konumunda bulunmaktadır, yer paylaşımları bu dosyanın ve android:isStatic ile android:priority öğesinin yer paylaşımları belirlenebilir. Herhangi bir bölüm, yer paylaşımlı bölüm önceliğini uygular.

Ayrıca Android 11 veya sonraki sürümler paket sırasında okunan kaynakların değerlerini etkilemek için statik yer paylaşımları kullanmak teşekkür ederiz. Statik yer paylaşımlarını değiştirmek için statik yer paylaşımları durumunu yapılandıran boole değerleri için <component-override> SystemConfig etiketi (Android'de yeni) 11).

Yer paylaşımlarında hata ayıklama

Yer paylaşımlarını manuel olarak etkinleştirmek, devre dışı bırakmak ve aktarmak için aşağıdaki yer paylaşımını kullanın yönetici kabuk komutunu kullanabilirsiniz.

adb shell cmd overlay

OverlayManagerService, hedefteki kaynak kimliklerini eşlemek için idmap2 kullanıyor paketindeki kaynak kimliklerine yönlendirir. Oluşturulan kimlik eşlemeleri /data/resource-cache/ içinde depolanıyor. Yer paylaşımınız düzgün çalışmıyorsa /data/resource-cache/'daki yer paylaşımınıza karşılık gelen idmap dosyasını, 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şlemesini 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