रनटाइम संसाधन ओवरले (आरआरओ)

रनटाइम रिसोर्स ओवरले (RRO) एक ऐसा पैकेज है जो रनटाइम पर टारगेट पैकेज के रिसोर्स वैल्यू को बदलता है। उदाहरण के लिए, सिस्टम छवि पर स्थापित एक ऐप संसाधन के मूल्य के आधार पर अपना व्यवहार बदल सकता है। निर्माण समय पर संसाधन मूल्य को हार्डकोड करने के बजाय, एक अलग विभाजन पर स्थापित एक आरआरओ रनटाइम पर ऐप के संसाधनों के मूल्यों को बदल सकता है।

आरआरओ को सक्षम या अक्षम किया जा सकता है। आप संसाधन मूल्यों को बदलने के लिए RRO की क्षमता को चालू करने के लिए सक्षम/अक्षम स्थिति को प्रोग्रामेटिक रूप से सेट कर सकते हैं। आरआरओ डिफ़ॉल्ट रूप से अक्षम होते हैं (हालांकि, स्थिर आरआरओ डिफ़ॉल्ट रूप से सक्षम होते हैं)।

ओवरलेइंग संसाधन

ओवरले पैकेज में परिभाषित संसाधनों को लक्ष्य पैकेज में परिभाषित संसाधनों के साथ मैप करके काम करता है। जब कोई ऐप लक्ष्य पैकेज में संसाधन के मूल्य को हल करने का प्रयास करता है, तो इसके बजाय लक्ष्य संसाधन के लिए मैप किए गए ओवरले संसाधन का मान वापस कर दिया जाता है।

घोषणापत्र की स्थापना

एक पैकेज को एक आरआरओ पैकेज माना जाता है यदि इसमें <overlay> टैग <manifest> टैग के चाइल्ड के रूप में होता है।

  • आवश्यक android:targetPackage विशेषता का मान उस पैकेज का नाम निर्दिष्ट करता है जिसे RRO ओवरले करना चाहता है।

  • वैकल्पिक android:targetName विशेषता का मान लक्ष्य पैकेज के संसाधनों के ओवरलेएबल उपसमुच्चय का नाम निर्दिष्ट करता है जिसे RRO ओवरले करना चाहता है। यदि लक्ष्य संसाधनों के ओवरले करने योग्य सेट को परिभाषित नहीं करता है, तो यह विशेषता मौजूद नहीं होनी चाहिए।

निम्न कोड एक उदाहरण ओवरले 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>

ओवरले कोड को ओवरले नहीं कर सकते, इसलिए उनमें DEX फ़ाइलें नहीं हो सकतीं। इसके अलावा, मेनिफेस्ट में <application > टैग की android:hasCode विशेषता को false पर सेट किया जाना चाहिए।

संसाधन मानचित्र को परिभाषित करना

एंड्रॉइड 11 या उच्चतर में, ओवरले संसाधन मानचित्र को परिभाषित करने के लिए अनुशंसित तंत्र ओवरले पैकेज के res/xml निर्देशिका में एक फ़ाइल बनाना है, लक्ष्य संसाधनों की गणना करना चाहिए जिन्हें ओवरलैड किया जाना चाहिए और उनके प्रतिस्थापन मान, फिर का मान सेट करें android:resourcesMap संसाधन मैपिंग फ़ाइल के संदर्भ में <overlay> मेनिफेस्ट टैग की विशेषता।

निम्न कोड एक उदाहरण 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>

निम्न कोड एक उदाहरण ओवरले मेनिफेस्ट दिखाता है।

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

पैकेज का निर्माण

एंड्रॉइड 11 या उच्चतर ओवरले के लिए एक सूंग बिल्ड नियम का समर्थन करता है जो एंड्रॉइड एसेट पैकेजिंग टूल 2 (एएपीटी 2) को समान मूल्य वाले संसाधनों के कॉन्फ़िगरेशन को कम करने का प्रयास करने से रोकता है ( --no-resource-deduping ) और डिफ़ॉल्ट कॉन्फ़िगरेशन के बिना संसाधनों को हटाने से ( --no-resource-removal )। निम्न कोड Android.bp फ़ाइल का एक उदाहरण दिखाता है।

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

संसाधनों का समाधान

यदि लक्ष्य संसाधन या ओवरले संसाधन में क्वेरी किए जा रहे संसाधन के लिए कई कॉन्फ़िगरेशन परिभाषित हैं, तो संसाधन रनटाइम कॉन्फ़िगरेशन का मान देता है जो डिवाइस कॉन्फ़िगरेशन के कॉन्फ़िगरेशन से सबसे अच्छा मेल खाता है। यह निर्धारित करने के लिए कि कौन सा कॉन्फ़िगरेशन सबसे अच्छा मिलान करने वाला कॉन्फ़िगरेशन है, ओवरले संसाधन कॉन्फ़िगरेशन के सेट को लक्ष्य संसाधन कॉन्फ़िगरेशन के सेट में मर्ज करें और फिर नियमित संसाधन रिज़ॉल्यूशन प्रवाह का पालन करें (विवरण के लिए, देखें कि Android कैसे सर्वोत्तम-मिलान संसाधन ढूंढता है )।

उदाहरण के लिए, यदि कोई ओवरले drawable-en कॉन्फ़िगरेशन के लिए एक मान को परिभाषित करता है और लक्ष्य drawable-en-port लिए एक मान को परिभाषित करता है, तो drawable-en-port का बेहतर मिलान होता है, इसलिए लक्ष्य कॉन्फ़िगरेशन drawable-en-port का मान है रनटाइम पर चुना गया। सभी drawable-en कॉन्फ़िगरेशन को ओवरले करने के लिए, ओवरले को प्रत्येक drawable-en कॉन्फ़िगरेशन के लिए एक मान परिभाषित करना चाहिए जिसे लक्ष्य परिभाषित करता है।

ओवरले अपने स्वयं के संसाधनों को संदर्भित कर सकते हैं, Android रिलीज़ के बीच भिन्न व्यवहार के साथ।

  • एंड्रॉइड 11 या उच्चतर में, प्रत्येक ओवरले का अपना आरक्षित संसाधन आईडी स्थान होता है जो लक्ष्य संसाधन आईडी स्थान या अन्य ओवरले संसाधन आईडी रिक्त स्थान को ओवरलैप नहीं करता है, इसलिए अपने स्वयं के संसाधनों को संदर्भित करने वाले ओवरले अपेक्षा के अनुरूप काम करते हैं।

  • एंड्रॉइड 10 या उससे कम में, ओवरले और लक्ष्य पैकेज समान संसाधन आईडी स्थान साझा करते हैं, जो टकराव और अप्रत्याशित व्यवहार का कारण बन सकते हैं जब वे @type/name सिंटैक्स का उपयोग करके अपने स्वयं के संसाधनों को संदर्भित करने का प्रयास करते हैं।

ओवरले को सक्षम/अक्षम करना

उत्परिवर्तित ओवरले को सक्षम और अक्षम करने के लिए OverlayManager API का उपयोग करें (API इंटरफ़ेस को Context#getSystemService(Context.OVERLAY_SERVICE) का उपयोग करके पुनर्प्राप्त करें)। एक ओवरले को केवल उसके द्वारा लक्षित पैकेज या android.permission.CHANGE_OVERLAY_PACKAGES अनुमति वाले पैकेज द्वारा सक्षम किया जा सकता है। जब कोई ओवरले सक्षम या अक्षम होता है, तो कॉन्फ़िगरेशन परिवर्तन ईवेंट लक्ष्य पैकेज और लक्ष्य गतिविधियों को पुन: लॉन्च करने के लिए प्रचारित करते हैं।

ओवरले करने योग्य संसाधनों को प्रतिबंधित करना

एंड्रॉइड 10 या उच्चतर में, <overlayable> एक्सएमएल टैग संसाधनों के एक सेट को उजागर करता है जिसे आरआरओ को ओवरले करने की अनुमति है। निम्नलिखित उदाहरण में res/values/overlayable.xml फ़ाइल, string/foo और integer/bar ऐसे संसाधन हैं जिनका उपयोग डिवाइस की उपस्थिति को थीम करने के लिए किया जाता है; इन संसाधनों को ओवरले करने के लिए, एक ओवरले को नाम से ओवरले करने योग्य संसाधनों के संग्रह को स्पष्ट रूप से लक्षित करना चाहिए।

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

एक एपीके कई <overlayable> टैग को परिभाषित कर सकता है, लेकिन प्रत्येक टैग का पैकेज के भीतर एक अद्वितीय नाम होना चाहिए। उदाहरण के लिए, यह है:

  • <overlayable name="foo"> दोनों को परिभाषित करने के लिए दो अलग-अलग पैकेजों के लिए ठीक है।

  • किसी एक APK के लिए दो <overlayable name="foo"> ब्लॉक होना ठीक नहीं है।

निम्न कोड 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>

जब कोई ऐप एक <overlayable> टैग को परिभाषित करता है, तो उस ऐप को लक्षित करके ओवरले किया जाता है:

  • targetName निर्दिष्ट करना होगा।

  • केवल <overlayable> टैग में सूचीबद्ध संसाधनों को ही ओवरले कर सकता है।

  • केवल एक <overlayable> नाम को लक्षित कर सकता है।

आप किसी ऐसे पैकेज को लक्षित करने वाले ओवरले को सक्षम नहीं कर सकते जो ओवरले करने योग्य संसाधनों को उजागर करता है लेकिन किसी विशिष्ट <overlayable> टैग को लक्षित करने के लिए android:targetName का उपयोग नहीं करता है।

नीतियों को प्रतिबंधित करना

ओवरले करने योग्य संसाधनों पर प्रतिबंध लागू करने के लिए <policy> टैग का उपयोग करें। type विशेषता निर्दिष्ट करती है कि शामिल संसाधनों को ओवरराइड करने के लिए एक ओवरले को किन नीतियों को पूरा करना चाहिए। समर्थित प्रकारों में निम्नलिखित शामिल हैं।

  • public . कोई भी ओवरले संसाधन को ओवरराइड कर सकता है।
  • system । सिस्टम विभाजन पर कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है।
  • vendor । विक्रेता विभाजन पर कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है।
  • product । उत्पाद विभाजन पर कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है।
  • signature । लक्ष्य एपीके के समान हस्ताक्षर के साथ हस्ताक्षरित कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है।

निम्न कोड res/values/overlayable.xml फ़ाइल में एक उदाहरण <policy> टैग दिखाता है।

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

एकाधिक नीतियों को निर्दिष्ट करने के लिए, लंबवत बार (|) को विभाजक वर्णों के रूप में उपयोग करें। जब एक से अधिक नीतियां निर्दिष्ट की जाती हैं, तो एक ओवरले को <policy> टैग में सूचीबद्ध संसाधनों को ओवरराइड करने के लिए केवल एक नीति को पूरा करने की आवश्यकता होती है।

ओवरले कॉन्फ़िगर करना

एंड्रॉइड रिलीज संस्करण के आधार पर परिवर्तनशीलता, डिफ़ॉल्ट स्थिति और ओवरले की प्राथमिकता को कॉन्फ़िगर करने के लिए एंड्रॉइड विभिन्न तंत्रों का समर्थन करता है।

  • Android 11 या उसके बाद वाले वर्शन चलाने वाले डिवाइस मेनिफ़ेस्ट विशेषताओं के बजाय OverlayConfig फ़ाइल ( config.xml ) का उपयोग कर सकते हैं। ओवरले फ़ाइल का उपयोग करना ओवरले के लिए अनुशंसित तरीका है।

  • स्थिर आरआरओ को कॉन्फ़िगर करने के लिए सभी डिवाइस मेनिफेस्ट विशेषताओं ( android:isStatic और android:priority ) का उपयोग कर सकते हैं।

OverlayConfig का उपयोग करना

एंड्रॉइड 11 या उच्चतर में, आप OverlayConfig का उपयोग परिवर्तनशीलता, डिफ़ॉल्ट स्थिति और ओवरले की प्राथमिकता को कॉन्फ़िगर करने के लिए कर सकते हैं। ओवरले को कॉन्फ़िगर करने के लिए, partition/overlay/config/config.xml पर स्थित फाइल बनाएं या संशोधित करें, जहां partition ओवरले का विभाजन है जिसे कॉन्फ़िगर किया जाना है। कॉन्फ़िगर किए जाने के लिए, एक ओवरले उस पार्टीशन के overlay/ निर्देशिका में होना चाहिए जिसमें ओवरले कॉन्फ़िगर किया गया है। निम्न कोड एक उदाहरण 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>"

<overlay> टैग को एक package विशेषता की आवश्यकता होती है जो इंगित करती है कि कौन सा ओवरले पैकेज कॉन्फ़िगर किया जा रहा है। वैकल्पिक enabled विशेषता नियंत्रित करती है कि ओवरले डिफ़ॉल्ट रूप से सक्षम है या नहीं (डिफ़ॉल्ट false है)। वैकल्पिक उत्परिवर्तनीय विशेषता नियंत्रित करती है कि ओवरले mutable है या नहीं और इसकी सक्षम स्थिति को रनटाइम पर प्रोग्रामेटिक रूप से बदला जा सकता है (डिफ़ॉल्ट true )। कॉन्फ़िगरेशन फ़ाइल में सूचीबद्ध नहीं किए गए ओवरले डिफ़ॉल्ट रूप से परिवर्तनशील और अक्षम होते हैं।

ओवरले वरीयता

जब एक से अधिक ओवरले समान संसाधनों को ओवरराइड करते हैं, तो ओवरले का क्रम महत्वपूर्ण होता है। ओवरले की अपने स्वयं के कॉन्फ़िगरेशन से पहले के कॉन्फ़िगरेशन वाले ओवरले की तुलना में अधिक प्राथमिकता होती है। विभिन्न विभाजनों (कम से कम से सबसे बड़ी पूर्वता) में ओवरले का पूर्वता क्रम इस प्रकार है।

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

फ़ाइलें मर्ज करना

<merge> टैग का उपयोग करने से अन्य कॉन्फ़िगरेशन फ़ाइलों को कॉन्फ़िगरेशन फ़ाइल में निर्दिष्ट स्थान पर मर्ज किया जा सकता है। टैग की path विशेषता ओवरले कॉन्फ़िगरेशन फ़ाइलों वाली निर्देशिका के सापेक्ष मर्ज करने के लिए फ़ाइल के पथ का प्रतिनिधित्व करती है।

मेनिफेस्ट विशेषताओं (स्थिर आरआरओ) का उपयोग करना

Android 10 या उसके बाद के संस्करण में, ओवरले अपरिवर्तनीयता और पूर्वता को निम्नलिखित मेनिफेस्ट विशेषताओं का उपयोग करके कॉन्फ़िगर किया गया है।

  • android:isStatic है। जब इस बूलियन विशेषता का मान true पर सेट होता है, तो ओवरले डिफ़ॉल्ट रूप से सक्षम होता है और अपरिवर्तनीय होता है, जो ओवरले को अक्षम होने से रोकता है।

  • android:priority । इस संख्यात्मक विशेषता का मान (जो केवल स्थिर ओवरले को प्रभावित करता है) ओवरले की प्राथमिकता को तब कॉन्फ़िगर करता है जब एकाधिक स्थिर ओवरले समान संसाधन मान को लक्षित करते हैं। एक उच्च संख्या एक उच्च प्राथमिकता को इंगित करती है।

निम्न कोड एक उदाहरण 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>

Android 11 में बदलाव

Android 11 या उच्चतर में, यदि कोई कॉन्फ़िगरेशन फ़ाइल partition/overlay/config/config.xml में स्थित है, तो उस फ़ाइल का उपयोग करके ओवरले कॉन्फ़िगर किए जाते हैं और android:isStatic और android:priority का विभाजन में स्थित ओवरले पर कोई प्रभाव नहीं पड़ता है। किसी भी पार्टीशन में एक ओवरले कॉन्फ़िगरेशन फ़ाइल को परिभाषित करना ओवरले विभाजन पूर्वता को लागू करता है।

इसके अलावा, एंड्रॉइड 11 या उच्चतर पैकेज स्थापना के दौरान पढ़े गए संसाधनों के मूल्यों को प्रभावित करने के लिए स्थिर ओवरले का उपयोग करने की क्षमता को हटा देता है। घटक सक्षम स्थिति को कॉन्फ़िगर करने वाले बूलियन के मान को बदलने के लिए स्थिर ओवरले का उपयोग करने के सामान्य उपयोग के मामले के लिए, <component-override> SystemConfig टैग (Android 11 में नया) का उपयोग करें।

डिबगिंग ओवरले

ओवरले को मैन्युअल रूप से सक्षम, अक्षम और डंप करने के लिए, निम्न ओवरले प्रबंधक शेल कमांड का उपयोग करें।

adb shell cmd overlay

OverlayManagerService लक्ष्य पैकेज में संसाधन आईडी को ओवरले पैकेज में संसाधन आईडी में मैप करने के लिए idmap2 का उपयोग करता है। उत्पन्न आईडी मैपिंग /data/resource-cache/ में संग्रहीत हैं। यदि आपका ओवरले ठीक से काम नहीं कर रहा है, तो /data/resource-cache/ में अपने ओवरले के लिए संबंधित idmap फ़ाइल ढूंढें, फिर निम्न कमांड चलाएँ।

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

यह कमांड संसाधनों की मैपिंग को प्रिंट करता है जैसा कि नीचे दिखाया गया है।

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