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

تراكب موارد وقت التشغيل (RRO) عبارة عن حزمة تعمل على تغيير قيم الموارد للحزمة المستهدفة في وقت التشغيل. على سبيل المثال، قد يغير التطبيق المثبت على صورة النظام سلوكه بناءً على قيمة المورد. بدلاً من تشفير قيمة المورد في وقت الإنشاء، يمكن لـ RRO المثبت على قسم مختلف تغيير قيم موارد التطبيق في وقت التشغيل.

يمكن تمكين أو تعطيل RROs. يمكنك تعيين حالة التمكين/التعطيل برمجيًا لتبديل قدرة RRO على تغيير قيم الموارد. يتم تعطيل RROs بشكل افتراضي (ومع ذلك، يتم تمكين RROs الثابتة بشكل افتراضي).

تراكب الموارد

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

قم بإعداد البيان

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

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

في Android 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>

بناء الحزمة

يدعم Android 11 أو الإصدارات الأحدث قاعدة Soong build للتراكبات التي تمنع 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 أو الإصدارات الأحدث، يحتوي كل تراكب على مساحة معرف المورد المحجوزة الخاصة به والتي لا تتداخل مع مساحة معرف المورد الهدف أو مساحات معرف مورد التراكب الأخرى، لذلك تعمل التراكبات التي تشير إلى مواردها الخاصة كما هو متوقع.

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

تمكين/تعطيل التراكبات

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

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

في نظام التشغيل Android 10 أو الإصدارات الأحدث، تكشف علامة XML <overlayable> عن مجموعة من الموارد التي يُسمح لـ RROs بتراكبها. في المثال التالي، يعتبر ملف 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 . يمكن لأي تراكب على قسم OEM تجاوز الموارد.
  • odm . يمكن لأي تراكب على قسم odm تجاوز الموارد.
  • signature . يمكن لأي تراكب موقّع بنفس توقيع ملف APK المستهدف أن يتجاوز الموارد.
  • actor . يمكن لأي تراكب موقّع بنفس توقيع ملف APK الخاص بالممثل أن يتجاوز الموارد. تم الإعلان عن الممثل في علامة الممثل المسمى في تكوين النظام.
  • config_signature . يمكن لأي تراكب موقّع بنفس التوقيع مثل ملف apk overlay-config أن يتجاوز الموارد. تم الإعلان عن تكوين التراكب في علامة توقيع التكوين في تكوين النظام.

يعرض التعليمة البرمجية التالية مثالاً لعلامة <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 ) لتكوين عمليات RRO الثابتة.

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

استخدم سمات البيان/RROs الثابتة

في نظام التشغيل 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>

التغييرات في أندرويد 11

في Android 11 أو الإصدارات الأحدث، إذا كان ملف التكوين موجودًا في partition/overlay/config/config.xml ، فسيتم تكوين التراكبات باستخدام هذا الملف ولن يكون لـ android:isStatic و android:priority أي تأثير على التراكبات الموجودة في القسم. يؤدي تحديد ملف تكوين التراكب في أي قسم إلى فرض أسبقية قسم التراكب.

بالإضافة إلى ذلك، يزيل Android 11 أو الإصدارات الأحدث القدرة على استخدام التراكبات الثابتة للتأثير على قيم الموارد المقروءة أثناء تثبيت الحزمة. بالنسبة لحالة الاستخدام الشائع لاستخدام التراكبات الثابتة لتغيير قيمة القيم المنطقية التي تقوم بتكوين حالة تمكين المكون، استخدم علامة SystemConfig <component-override> (الجديدة في Android 11).

تراكبات التصحيح

لتمكين التراكبات وتعطيلها وتفريغها يدويًا، استخدم أمر shell manager للتراكب التالي.

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