रनटाइम पर किसी ऐप के संसाधनों का मान बदलें

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

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

ओवरले संसाधन

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

मेनिफेस्ट सेट करें

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

  • आवश्यक 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 निर्देशिका में एक फ़ाइल बनाना है, उन लक्ष्य संसाधनों की गणना करना है जिन्हें ओवरलेड किया जाना चाहिए और उनके प्रतिस्थापन मान, फिर का मान निर्धारित करें संसाधन मैपिंग फ़ाइल के संदर्भ में <overlay> मेनिफेस्ट टैग की android:resourcesMap विशेषता।

निम्नलिखित कोड एक उदाहरण 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",
}

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

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

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

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

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

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

ओवरले सक्षम/अक्षम करें

परिवर्तनीय ओवरले को सक्षम और अक्षम करने के लिए OverlayManager API का उपयोग करें ( Context#getSystemService(Context.OVERLAY_SERVICE) का उपयोग करके API इंटरफ़ेस पुनर्प्राप्त करें)। एक ओवरले को केवल उस पैकेज द्वारा सक्षम किया जा सकता है जिसे वह लक्षित करता है या 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 । उत्पाद विभाजन पर कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है।
  • oem . OEM विभाजन पर कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है।
  • odm . ODM विभाजन पर कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है।
  • signature । लक्ष्य एपीके के समान हस्ताक्षर के साथ हस्ताक्षरित कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है।
  • actorअभिनेता एपीके के समान हस्ताक्षर के साथ हस्ताक्षरित कोई भी ओवरले संसाधनों को ओवरराइड कर सकता है। सिस्टम कॉन्फ़िगरेशन में अभिनेता को नामांकित-अभिनेता टैग में घोषित किया गया है।
  • config_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> टैग के भीतर सूचीबद्ध संसाधनों को ओवरराइड करने के लिए केवल एक नीति को पूरा करने की आवश्यकता होती है।

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

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

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

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

ओवरले कॉन्फिग का उपयोग करें

एंड्रॉइड 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
  • odm
  • oem
  • product
  • system_ext

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

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

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

एंड्रॉइड 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>

एंड्रॉइड 11 में बदलाव

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

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