تغيير قيمة موارد التطبيق في وقت التشغيل

تراكب الموارد في وقت التشغيل (RRO) هو حزمة تغيّر قيم الموارد لحزمة مستهدَفة في وقت التشغيل. على سبيل المثال، قد يغيّر تطبيق مثبَّت على ملف ‎system image سلوكه استنادًا إلى قيمة أحد الموارد. بدلاً من الترميز الثابت لقيمة المورد في وقت الإصدار، يمكن أن تغير قيمة RRO المثبتة على قسم مختلف قيم موارد التطبيق في وقت التشغيل.

يمكن تفعيل RROs أو إيقافها. يمكنك ضبط حالة التفعيل/الإيقاف آليًا لتبديل قدرة RRO على تغيير قيم الموارد. تكون تطبيقات RRO غير مفعَّلة تلقائيًا (ومع ذلك، تكون تطبيقات RRO الثابتة مفعَّلة تلقائيًا).

الموارد التي تظهر على سطح الشاشة

تعمل التراكبات عن طريق تعيين الموارد المحددة في حزمة التراكب إلى الموارد المحددة في الحزمة المستهدفة. عندما يحاول أحد التطبيقات حل قيمة أحد الموارد في الحزمة المستهدفة، يتم عرض قيمة المورد المتراكب الذي يتم تعيين المورد المستهدف له بدلاً من ذلك.

إعداد البيان

تُعتبر الحزمة حزمة RRO إذا كانت تحتوي على علامة <overlay> باعتبارها تابعة للعلامة <manifest>.

  • تحدد قيمة السمة المطلوبة android:targetPackage اسم الحزمة التي تريد إضافة المحتوى إليها.

  • تحدّد قيمة السمة 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. بالإضافة إلى ذلك، يجب ضبط السمة android:hasCode للعلامة <application> في البيان على false.

تحديد خريطة الموارد

في الإصدار 11 من نظام التشغيل Android أو الإصدارات الأحدث، الآلية المقترَحة لتحديد ملف ربط الموارد التي تظهر على سطح الشاشة هي إنشاء ملف في الدليل 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>

بناء الحزمة

يتوافق نظام التشغيل Android 11 أو الإصدارات الأحدث مع قاعدة إصدار Sayg للتراكبات التي تمنع أداة Android Asset Packaging Tool 2 (AAPT2) من محاولة إزالة تكرار إعدادات الموارد التي لها القيمة نفسها (--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.

  • في الإصدار Android 11 أو الإصدارات الأحدث، يكون لكل طبقة مساحة معرّف موارد محجوزة خاصة لا تتداخل مع مساحة معرّف المورد المستهدف أو مساحات معرّفات الموارد الأخرى المركّبة، لذا تعمل العناصر المركّبة التي تشير إلى مواردها على النحو المتوقَّع.

  • في الإصدار 10 من Android أو الإصدارات الأقدم، تتشارك الحِزم المتراكبة والحِزم المستهدَفة مساحة معرّف موارد المعروفة نفسها، ما قد يؤدي إلى حدوث تداخلات وسلوك غير متوقّع عند محاولة الإشارة إلى مواردها باستخدام بنية @type/name.

تفعيل تراكبات الصور أو إيقافها

يمكنك استخدام واجهة برمجة التطبيقات OverlayManager لتفعيل التراكبات القابلة للتغيّر وإيقافها (استرداد واجهة واجهة برمجة التطبيقات باستخدام Context#getSystemService(Context.OVERLAY_SERVICE)). ولا يمكن تفعيل التداخل إلا من خلال الحزمة التي تستهدفها أو من خلال حزمة لديها إذن android.permission.CHANGE_OVERLAY_PACKAGES. عند تفعيل طبقة مركّبة أو إيقافها، يتم نشر أحداث تغيير الضبط في الحزمة المستهدَفة وتتم إعادة بدء الأنشطة المستهدَفة.

تقييد الموارد القابلة للتراكب

في الإصدار Android 10 أو الإصدارات الأحدث، تعرض علامة XML الخاصة بـ <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>

يمكن أن يحدِّد حِزمة APK علامات <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> واحد فقط.

لا يمكنك تفعيل عرض مركّب يستهدف حزمة تعرض موارد قابلة للتراكب، ولكنها لا تستخدم android:targetName لاستهداف علامة <overlayable> محددة.

تقييد السياسات

استخدِم علامة <policy> لفرض قيود على الموارد التي يمكن تداخلها. تحدِّد سمة type السياسات التي يجب أن تستوفيها الصورة المتراكبة لإلغاء الموارد المضمّنة. تشمل الأنواع المتوافقة ما يلي:

  • public. يمكن لأيّ تراكب إلغاء المورد.
  • system. يمكن أن يؤدي أي تراكب في قسم النظام إلى إلغاء الموارد.
  • vendor. يمكن أن يؤدي أي تراكب في قسم المورِّد إلى إلغاء الموارد.
  • product. يمكن أن يلغي أي تراكب في قسم المنتج الموارد.
  • oem. يمكن لأي تراكب في قسم المصنّع الأصلي للجهاز إلغاء الموارد.
  • odm. يمكن لأيّ تراكب على قسم odm إلغاء الموارد.
  • signature. إنّ أي تركيب موقَّع يحمل التوقيع نفسه لحزمة APK المستهدَفة يمكن أن يحلّ محلّ الموارد.
  • actor. يمكن أن تؤدي أي طبقة مثبّتة موقَّعة بالتوقيع نفسه لحزمة APK الخاصة بالممثّل إلى إلغاء الموارد. يتمّ الإعلان عن الفاعل في علامة named-actor في system config.
  • config_signature. يمكن لأي عنصر مصغّر موقَّع بالتوقيع نفسه لحزمة APK overlay-config إلغاء الموارد. يتم توضيح تكوين التراكب في العلامة overlay-config-signature في تهيئة النظام.

يعرض الرمز التالي مثالاً على علامة <policy> في ملف 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>

لتحديد سياسات متعدّدة، استخدِم الأشرطة العمودية (|) كأحرف فاصلة. عند تحديد سياسات متعدّدة، يجب أن يفي التراكب بسياسة واحدة فقط لإلغاء الموارد المدرَجة في العلامة <policy>.

تهيئة التراكبات

يتيح Android آليات مختلفة لضبط قابلية التغيير والحالة الافتراضية وأولوية العناصر التي تظهر على سطح الشاشة، وذلك استنادًا إلى إصدار Android.

  • يمكن للأجهزة التي تعمل بنظام التشغيل Android 11 أو الإصدارات الأحدث استخدام ملف OverlayConfig (config.xml) بدلاً من سمات البيان. يعد استخدام ملف تراكب الطريقة الموصى بها للتراكبات.

  • يمكن لجميع الأجهزة استخدام سمات البيان (android:isStatic و android:priority) لضبط عمليات التثبيت من مصدر غير معروف الثابتة.

استخدام OverlayConfig

في نظام التشغيل Android 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 للعلامة مسار الملف الذي سيتم دمجه بالنسبة إلى الدليل الذي يحتوي علىملفّات إعدادات التراكب.

استخدام سمات البيان أو قوائم RRO الثابتة

في الإصدار 10 من نظام التشغيل Android أو الإصدارات الأقدم، يتم ضبط عدم قابلية تغيير التراكب وأولويته باستخدام سمات البيان التالية.

  • 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 من نظام التشغيل Android أو الإصدارات الأحدث إمكانية استخدام تراكبات ثابتة للتأثير في قيم الموارد التي تتم قراءتها أثناء تثبيت الحِزم. في حالة الاستخدام الشائعة لاستخدام العناصر المركّبة الثابتة لتغيير قيمة القيم المنطقية التي تضبط حالة تفعيل المكوّنات، يمكنك استخدام علامة SystemConfig المسماة <component-override> (الجديدة في Android 11).

تصحيح أخطاء التراكبات

لتفعيل التراكب يدويًا وإيقافه وتفريغه، استخدِم الأمر التالي في واجهة أوامر مدير التراكب.

adb shell cmd overlay

يستخدم OverlayManagerService idmap2 لربط أرقام تعريف الموارد في الحزمة المستهدفة بأرقام تعريف الموارد في حزمة التراكب. يتم تخزين عمليات ربط المعرّفات التي تم إنشاؤها في /data/resource-cache/. إذا لم يعمل التراكب بشكل صحيح، ابحث عنملف idmap المقابل للتراكب في /data/resource-cache/، ثمشغِّل الأمر التالي.

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