שנה את הערך של משאבי אפליקציה בזמן ריצה

שכבת משאב בזמן ריצה (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 .

הגדר את מפת המשאבים

באנדרואיד 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 ומעלה תומך בכלל בנייה של Soong לשכבות-על שמונעות מ-Android Asset Packaging Tool 2 (AAPT2) לנסות לבטל תצורות של משאבים עם אותו ערך ( --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 שהיעד מגדיר.

שכבות-על יכולות להתייחס למשאבים שלהן, עם התנהגויות שונות בין גרסאות אנדרואיד.

  • ב-Android 11 ומעלה, לכל שכבת-על יש מרחב שמור משלה לזיהוי משאבים שאינו חופף למרחב מזהה משאב-על או למרחבים אחרים של זיהוי משאבי-על, כך ששכבות-על המתייחסות למשאבים שלהן פועלות כצפוי.

  • ב-Android 10 ומטה, שכבות-על וחבילות יעד חולקות את אותו מרחב מזהה משאב, מה שעלול לגרום להתנגשויות ולהתנהגות בלתי צפויה כאשר הם מנסים להפנות למשאבים שלהם באמצעות תחביר @type/name .

הפעל/השבת שכבות-על

השתמש ב- OverlayManager API כדי להפעיל ולהשבית שכבות-על הניתנות לשינוי (אחזר את ממשק ה-API באמצעות Context#getSystemService(Context.OVERLAY_SERVICE) ). ניתן להפעיל שכבת-על רק על-ידי החבילה אליה היא ממקדת או על-ידי חבילה עם הרשאת android.permission.CHANGE_OVERLAY_PACKAGES . כאשר שכבת-על מופעלת או מושבתת, אירועי שינוי תצורה מתפשטים לחבילת היעד וההפעלה מחדש של פעילויות היעד.

הגבל משאבים שניתנים לשכבת-על

באנדרואיד 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 של השחקן יכולה לעקוף את המשאבים. השחקן מוצהר בתג בשם-actor בתצורת המערכת.
  • config_signature . כל שכבת-על שנחתמה באותה חתימה כמו ה- overlay-config 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> .

הגדר שכבות-על

אנדרואיד תומכת במנגנונים שונים לקביעת התצורה של השינוי, מצב ברירת המחדל והעדיפות של שכבות-על בהתאם לגרסת המהדורה של אנדרואיד.

  • מכשירים עם אנדרואיד 11 ומעלה יכולים להשתמש בקובץ OverlayConfig ( config.xml ) במקום תכונות מניפסט. שימוש בקובץ שכבת-על היא השיטה המומלצת לשכבות-על.

  • כל המכשירים יכולים להשתמש בתכונות מניפסט ( android:isStatic ו- android:priority ) כדי להגדיר RROs סטטיים.

השתמש ב-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
  • odm
  • oem
  • product
  • system_ext

מיזוג קבצים

שימוש בתגיות <merge> מאפשר למזג קבצי תצורה אחרים במיקום שצוין לתוך קובץ התצורה. תכונת path של התג מייצגת את הנתיב של הקובץ למיזוג ביחס לספרייה המכילה קובצי תצורת שכבת-על.

השתמש במאפייני מניפסט/ RRO סטטיים

ב-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 אין השפעה על שכבות-על הממוקמות במחיצה. הגדרת קובץ תצורת שכבת-על בכל מחיצה אוכפת את קדימות מחיצת-העל.

בנוסף, אנדרואיד 11 ומעלה מסיר את היכולת להשתמש בשכבות-על סטטיות כדי להשפיע על ערכי המשאבים הנקראים במהלך התקנת החבילה. למקרה השימוש הנפוץ של שימוש בשכבות-על סטטיות כדי לשנות את הערך של בוליאנים המגדירים מצב מאופשר רכיב, השתמש בתג <component-override> SystemConfig (חדש באנדרואיד 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