การซ้อนทับทรัพยากรรันไทม์ (RRO) คือแพ็กเกจที่เปลี่ยนค่าทรัพยากร ของแพ็กเกจเป้าหมายในรันไทม์ เช่น แอปที่ติดตั้งในอิมเมจระบบ อาจเปลี่ยนลักษณะการทำงานตามค่าของทรัพยากร RRO ที่ติดตั้งในพาร์ติชันอื่นจะเปลี่ยนค่าของทรัพยากรของแอปในขณะรันไทม์ได้ แทนที่จะ ฮาร์ดโค้ดค่าทรัพยากรในเวลาบิลด์
คุณเปิดหรือปิดใช้ RRO ได้ คุณตั้งค่าสถานะเปิด/ปิดโดยใช้โปรแกรมเพื่อสลับความสามารถของ RRO ในการเปลี่ยนค่าทรัพยากรได้ RRO จะปิดใช้อยู่โดยค่าเริ่มต้น (แต่RRO แบบคงที่จะเปิดใช้อยู่โดย ค่าเริ่มต้น)
ทรัพยากรการซ้อนทับ
การวางซ้อนทำงานโดยการจับคู่ทรัพยากรที่กำหนดไว้ในแพ็กเกจการวางซ้อนกับทรัพยากรที่กำหนดไว้ในแพ็กเกจเป้าหมาย เมื่อแอปพยายามที่จะระบุค่าของทรัพยากรในแพ็กเกจเป้าหมาย ระบบจะแสดงค่าของทรัพยากรที่ซ้อนทับซึ่งทรัพยากรเป้าหมายแมปไว้แทน
ตั้งค่าไฟล์ Manifest
ระบบจะถือว่าแพ็กเกจเป็นแพ็กเกจ RRO หากมีแท็ก <overlay> เป็น
แท็กย่อยของแท็ก <manifest>
ค่าของแอตทริบิวต์
android:targetPackageที่จำเป็นจะระบุชื่อ ของแพ็กเกจที่ RRO ต้องการซ้อนทับค่าของแอตทริบิวต์
android:targetNameที่ไม่บังคับจะระบุชื่อของ ชุดย่อยของทรัพยากรที่วางซ้อนได้ของแพ็กเกจเป้าหมายที่ RRO ต้องการ วางซ้อน หากเป้าหมายไม่ได้กำหนดชุดทรัพยากรที่วางซ้อนได้ คุณไม่ควรระบุแอตทริบิวต์นี้
โค้ดต่อไปนี้แสดงตัวอย่างการวางซ้อน AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.e>xampl<e.overlay"
application andro>id:ha<sCode="false" /
overlay android:targetPackage="com.example.target"
an>d<roid:targ>etName="OverlayableResources"/
/manifest
เนื่องจากส่วนซ้อนทับไม่สามารถซ้อนทับโค้ดได้ จึงไม่มีไฟล์ DEX นอกจากนี้ ต้องตั้งค่าandroid:hasCodeแอตทริบิวต์ของแท็ก <application> ในไฟล์ Manifest เป็น false
กำหนดแผนที่ทรัพยากร
ใน Android 11 ขึ้นไป กลไกที่แนะนำสำหรับ
การกำหนดแผนที่ทรัพยากรการซ้อนทับคือการสร้างไฟล์ในไดเรกทอรี res/xml
ของแพ็กเกจการซ้อนทับ แสดงรายการทรัพยากรเป้าหมายที่ควร
ซ้อนทับและค่าแทนที่ จากนั้นตั้งค่าแอตทริบิวต์ android:resourcesMap ของแท็ก Manifest <overlay> เป็นการอ้างอิง
ไปยังไฟล์การแมปทรัพยากร
โค้ดต่อไปนี้แสดงตัวอย่างไฟล์ res/xml/overlays.xml
<?xml version="1.0" encodin>g<="utf-8"?
overlay xmlns:android="http://schemas.andr>oid.c<om/apk/res/android"
!-- Overlays string/config1 and string/conf>ig2 w<ith the same resource. --
item target="string/>confi<g1" value="@string/overlay1" /
item >target<="string/config2" value="@string/overl>ay1&q<uot; /
!-- Overlays string/config3 with the string &q>uot;ye<s". --
item target="string/config3" value=">;@and<roid:string/yes" /
!-- Overlays string/config>4 with< the string "Hardcoded string". --
item >targe<t="string/config4" value="H>a<rdcoded >string" /
!-- Overlays integer/config5 with the integer "42". --
item target="integer/config5" value="42" /
/overlay
โค้ดต่อไปนี้แสดงตัวอย่างไฟล์ Manifest ของการวางซ้อน
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.e>xampl<e.overlay"
application andro>id:ha<sCode="false" /
overlay android:targetPackage="com.example.target"
android:targetName="OverlayableResources"
> < > android:resourcesMap="@xml/overlays"/
/manifest
สร้างแพ็กเกจ
Android 11 ขึ้นไปรองรับกฎการสร้าง Soong สำหรับ
การซ้อนทับที่ป้องกันไม่ให้ 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
เปิด/ปิดใช้การวางซ้อน
คุณเปิด/ปิดใช้ภาพซ้อนทับได้ด้วยตนเองและแบบเป็นโปรแกรม
ปิดใช้หรือเปิดใช้การซ้อนทับด้วยตนเอง
หากต้องการเปิดใช้และยืนยัน RRO ด้วยตนเอง ให้เรียกใช้คำสั่งต่อไปนี้
adb shell cmd overlay enable --user current com.example.carrro
adb shell cmd overlay list --user current | grep -i com.example com.example.carrroซึ่งจะเปิดใช้ RRO สำหรับผู้ใช้ระบบ (userId = 0) ที่เป็นเจ้าของ SystemUI
คำสั่งนี้ไม่มีผลต่อแอปที่ผู้ใช้ที่อยู่เบื้องหน้าเริ่มทำงาน
(userId = 10) หากต้องการเปิดใช้ RRO สำหรับผู้ใช้ที่อยู่เบื้องหน้า ให้ใช้พารามิเตอร์
-–user 10
adb shell cmd overlay enable --user 10 com.example.carrroเปิดหรือปิดใช้การซ้อนทับโดยใช้โปรแกรม
ใช้ OverlayManager API เพื่อเปิดและปิดใช้การซ้อนทับที่เปลี่ยนแปลงได้ (เรียกอินเทอร์เฟซ API โดยใช้ Context#getSystemService(Context.OVERLAY_SERVICE)) การซ้อนทับจะเปิดใช้ได้โดยแพ็กเกจที่กำหนดเป้าหมายเท่านั้น หรือโดยแพ็กเกจที่มีandroid.permission.CHANGE_OVERLAY_PACKAGESสิทธิ์ เมื่อเปิดหรือปิดใช้การซ้อนทับ ระบบจะเผยแพร่เหตุการณ์การเปลี่ยนแปลงการกำหนดค่าไปยังแพ็กเกจเป้าหมาย
และกิจกรรมเป้าหมายจะเปิดตัวอีกครั้ง
จำกัดทรัพยากรที่วางซ้อนได้
ใน Android 10 ขึ้นไป แท็ก XML <overlayable> จะแสดงชุดทรัพยากร
ที่ RRO ได้รับอนุญาตให้ซ้อนทับ ในตัวอย่างไฟล์
res/values/overlayable.xml ต่อไปนี้ string/foo และ integer/bar คือทรัพยากร
ที่ใช้สำหรับกำหนดธีมลักษณะที่ปรากฏของอุปกรณ์ หากต้องการซ้อนทับทรัพยากรเหล่านี้ การซ้อนทับ
ต้องกำหนดเป้าหมายไปยังคอลเล็กชันของทรัพยากรที่ซ้อนทับได้โดยใช้ชื่ออย่างชัดเจน
<!-- The collection of resources for theming the appearance of the device -->
<overlayable name="ThemeResou>rces&quo<t;
policy typ>e="public&q<uot;
item type=&q>uot;string"< name="foo/" /
> i<tem typ>e="inte<ger" na>me="bar/" /
/policy
...
/overlayable
APK สามารถกำหนดแท็ก <overlayable> ได้หลายแท็ก แต่แต่ละแท็กต้องมีชื่อที่ไม่ซ้ำกันภายในแพ็กเกจ เช่น
OK for two different packages to both define
<overlayable name="foo">.ไม่อนุญาตให้ APK เดียวมีบล็อก
<overlayable name="foo">2 บล็อก
โค้ดต่อไปนี้แสดงตัวอย่างการวางซ้อนในไฟล์ AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my>.theme.o<verlay"
application andro>id:hasCo<de="false" /
!-- This overlay will override t>he Theme<Resources resources --
overlay android:targetPackage="android&q>u<ot; andro>id: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 จะ ลบล้างทรัพยากรได้ โดยจะประกาศนักแสดงในแท็ก named-actor ใน system configconfig_signatureการซ้อนทับที่ลงนามด้วยลายเซ็นเดียวกันกับ APK ของ overlay-config จะลบล้างทรัพยากรได้ ประกาศ overlay-config ในแท็ก overlay-config-signature ในการกำหนดค่าระบบ
โค้ดต่อไปนี้แสดงตัวอย่างแท็ก <policy> ในไฟล์
res/values/overlayable.xml
<overlayable name="ThemeResou>rces<"
policy type>="v<endor"
item type=&>quot<;string>&quo<t; name="foo" /
/pol>icy
p<olicy type="product|signat>ure"<;
item type="stri>ng&q<uot; na>m<e="bar&>quot; /
item type="string" name="baz" /
/policy
/overlayable
หากต้องการระบุนโยบายหลายรายการ ให้ใช้เครื่องหมายไปป์ (|) เป็นตัวคั่น
เมื่อระบุนโยบายหลายรายการ การวางซ้อนจะต้องเป็นไปตามนโยบายเพียงข้อเดียว
เพื่อลบล้างทรัพยากรที่แสดงในแท็ก <policy>
กำหนดค่าการซ้อนทับ
Android รองรับกลไกต่างๆ ในการกำหนดค่าความสามารถในการเปลี่ยนแปลง สถานะเริ่มต้น และลำดับความสำคัญของการซ้อนทับ ทั้งนี้ขึ้นอยู่กับเวอร์ชัน Android ที่เผยแพร่
อุปกรณ์ที่ใช้ Android 11 ขึ้นไปจะใช้ไฟล์
OverlayConfig(config.xml) แทนแอตทริบิวต์ Manifest ได้ การใช้ ไฟล์ซ้อนทับเป็นวิธีที่แนะนำสำหรับการซ้อนทับอุปกรณ์ทุกเครื่องสามารถใช้แอตทริบิวต์ไฟล์ Manifest (
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.x>ml&qu<ot; /
overlay package="com.oem.overlay.device" mutable=&quo>t;fal<se" enabled="true" /
overlay packag>e<=">com.oem.green.theme" enabled="true" /
/config"
แท็ก <overlay> ต้องมีแอตทริบิวต์ package ที่ระบุว่ากำลังกำหนดค่าแพ็กเกจ
ภาพซ้อนทับใด แอตทริบิวต์ enabled ที่ไม่บังคับจะควบคุมว่าระบบจะเปิดใช้
หรือไม่เปิดใช้ภาพซ้อนทับโดยค่าเริ่มต้น (ค่าเริ่มต้นคือ false) แอตทริบิวต์ mutable ที่ไม่บังคับจะควบคุมว่าภาพซ้อนทับจะเปลี่ยนแปลงได้หรือไม่ และจะเปลี่ยนสถานะที่เปิดใช้ได้โดยการเขียนโปรแกรมในขณะรันไทม์หรือไม่ (ค่าเริ่มต้นคือ true)
ภาพซ้อนทับที่ไม่ได้อยู่ในไฟล์กำหนดค่าจะเปลี่ยนแปลงได้และปิดใช้โดย
ค่าเริ่มต้น
ลำดับความสำคัญของการวางซ้อน
เมื่อการซ้อนทับหลายรายการลบล้างทรัพยากรเดียวกัน ลำดับของการซ้อนทับจะมีความสำคัญ การซ้อนทับมีลำดับความสำคัญสูงกว่าการซ้อนทับที่มีการกำหนดค่า ก่อนการกำหนดค่าของตัวเอง ลำดับความสำคัญของการซ้อนทับในพาร์ติชันต่างๆ (จากความสำคัญน้อยที่สุดไปมากที่สุด) มีดังนี้
systemvendorodmoemproductsystem_ext
ผสานไฟล์
การใช้แท็ก <merge> จะช่วยให้รวมไฟล์การกำหนดค่าอื่นๆ ได้ที่ตำแหน่งที่ระบุลงในไฟล์การกำหนดค่า แอตทริบิวต์ path ของแท็ก
แสดงเส้นทางของไฟล์ที่จะผสานเทียบกับไดเรกทอรีที่มี
ไฟล์การกำหนดค่าการซ้อนทับ
ใช้แอตทริบิวต์ไฟล์ Manifest/RRO แบบคงที่
ใน Android 10 หรือต่ำกว่า จะมีการกำหนดค่าความคงที่และการจัดลำดับความสำคัญของการซ้อนทับโดยใช้แอตทริบิวต์ Manifest ต่อไปนี้
android:isStaticเมื่อตั้งค่าแอตทริบิวต์บูลีนนี้เป็นtrueระบบจะเปิดใช้ภาพซ้อนทับโดยค่าเริ่มต้นและจะแก้ไขไม่ได้ ซึ่งจะป้องกันไม่ให้ปิดใช้ภาพซ้อนทับandroid:priorityค่าของแอตทริบิวต์ตัวเลขนี้ (ซึ่งมีผลกับเฉพาะภาพซ้อนแบบคงที่) จะกำหนดลำดับความสำคัญของภาพซ้อนเมื่อภาพซ้อนแบบคงที่หลายรายการกำหนดเป้าหมายเป็นค่าทรัพยากรเดียวกัน ตัวเลขที่สูงขึ้นบ่งบอกถึงลำดับความสำคัญที่สูงขึ้น
โค้ดต่อไปนี้แสดงตัวอย่าง AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.e>xampl<e.overlay"
application andro>id:ha<sCode="false" /
overlay android:targetPackage="com.example.target"
android:isStatic="t>r<ue"<>/span>
android:priority="5"/
/manifest
การเปลี่ยนแปลงใน Android 11
ใน Android 11 ขึ้นไป หากไฟล์การกำหนดค่าอยู่ใน partition/overlay/config/config.xml ระบบจะกำหนดค่าการวางซ้อนโดยใช้ไฟล์ดังกล่าว และ android:isStatic กับ android:priority จะไม่มีผลต่อการวางซ้อนที่อยู่ในพาร์ติชัน การกำหนดไฟล์การกำหนดค่าการวางซ้อนในพาร์ติชันใดก็ตามจะบังคับใช้ลำดับความสำคัญของพาร์ติชันการวางซ้อน
นอกจากนี้ Android 11 ขึ้นไปยังนำความสามารถ
ในการใช้การซ้อนทับแบบคงที่เพื่อส่งผลต่อค่าของทรัพยากรที่อ่านในระหว่างการติดตั้ง
แพ็กเกจออกด้วย สําหรับกรณีการใช้งานทั่วไปในการใช้ภาพซ้อนทับแบบคงที่เพื่อเปลี่ยนค่าของบูลีนที่กําหนดค่าสถานะที่เปิดใช้คอมโพเนนต์ ให้ใช้แท็ก <component-override> SystemConfig (ใหม่ใน Android 11)
การวางซ้อนการแก้ไขข้อบกพร่อง
หากต้องการเปิด ปิด และทิ้งข้อมูลการซ้อนทับด้วยตนเอง ให้ใช้คำสั่งเชลล์ overlay manager ต่อไปนี้
adb shell cmd overlayการใช้ enable โดยไม่ระบุผู้ใช้จะมีผลกับผู้ใช้ปัจจุบัน ซึ่งก็คือ
ผู้ใช้ระบบ (userId = 0) ที่เป็นเจ้าของ UI ของระบบ การดำเนินการนี้จะไม่ส่งผลต่อผู้ใช้ที่อยู่เบื้องหน้า (userId = 10) ซึ่งเป็นเจ้าของแอป หากต้องการเปิดใช้ RRO สำหรับ
ผู้ใช้ที่ใช้งานอยู่ ให้ใช้พารามิเตอร์ –-user 10
adb shell cmd overlay enable --user 10 com.example.carrroOverlayManagerService ใช้ 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