โอเวอร์เลย์ทรัพยากรรันไทม์ (RRO)

โอเวอร์เลย์ทรัพยากรรันไทม์ (RRO) เป็นแพ็กเกจที่เปลี่ยนค่าทรัพยากรของแพ็กเกจเป้าหมายขณะรันไทม์ ตัวอย่างเช่น แอปที่ติดตั้งบนอิมเมจระบบอาจเปลี่ยนลักษณะการทำงานตามมูลค่าของทรัพยากร แทนที่จะฮาร์ดโค้ดค่าทรัพยากร ณ เวลาสร้าง RRO ที่ติดตั้งบนพาร์ติชันอื่นสามารถเปลี่ยนค่าของทรัพยากรของแอปในขณะรันไทม์ได้

RRO สามารถเปิดหรือปิดได้ คุณสามารถตั้งค่าสถานะเปิด/ปิดใช้งานโดยทางโปรแกรมเพื่อสลับความสามารถของ RRO ในการเปลี่ยนค่าทรัพยากร RROs จะถูกยกเลิกโดยปริยาย (อย่างไร RROs คง มีการใช้งานโดยค่าเริ่มต้น)

ทรัพยากรซ้อนทับ

โอเวอร์เลย์ทำงานโดยการแมปทรัพยากรที่กำหนดไว้ในแพ็กเกจโอเวอร์เลย์กับรีซอร์สที่กำหนดไว้ในแพ็กเกจเป้าหมาย เมื่อแอพพยายามแก้ไขค่าของทรัพยากรในแพ็คเกจเป้าหมาย ค่าของทรัพยากรซ้อนทับที่ทรัพยากรเป้าหมายจะถูกจับคู่จะถูกส่งกลับแทน

ตั้งค่ารายการ

แพคเกจที่ถือว่าเป็นแพคเกจ RRO ถ้ามันมี <overlay> แท็กเป็นลูกของที่ <manifest> แท็ก

  • ค่าของที่จำเป็นต้องใช้ android:targetPackage แอตทริบิวต์ระบุชื่อของแพคเกจ RRO ตั้งใจที่จะซ้อนทับ

  • ค่าของที่ไม่จำเป็น android:targetName แอตทริบิวต์ระบุชื่อของเซต overlayable ของทรัพยากรของแพคเกจเป้าหมาย 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 > แท็กในไฟล์ Manifest ต้องกำหนดเป็น 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 สำหรับภาพซ้อนทับที่ป้องกันไม่ให้ Android สินทรัพย์บรรจุภัณฑ์เครื่องมือ 2 (AAPT2) จากความพยายามที่จะกำหนดค่า dedupe ของทรัพยากรที่มีค่าเดียวกัน ( --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 หรือต่ำกว่าซ้อนทับและแพคเกจเป้าหมายร่วมกันพื้นที่ ID ทรัพยากรเดียวกันซึ่งอาจทำให้เกิดการชนและพฤติกรรมที่ไม่คาดคิดเมื่อพวกเขาพยายามที่จะอ้างอิงทรัพยากรของตนเองโดยใช้ @type/name ไวยากรณ์

การเปิด/ปิดการซ้อนทับ

ใช้ OverlayManager API เพื่อเปิดใช้งานและการวางซ้อนแน่นอนปิดการใช้งาน (เรียกอินเตอร์เฟซ API โดยใช้ Context#getSystemService(Context.OVERLAY_SERVICE) ) การซ้อนทับสามารถเปิดใช้งานโดยเฉพาะแพคเกจที่กำหนดเป้าหมายหรือแพคเกจที่มี android.permission.CHANGE_OVERLAY_PACKAGES ได้รับอนุญาต เมื่อเปิดใช้งานหรือปิดใช้งานโอเวอร์เลย์ เหตุการณ์การเปลี่ยนแปลงการกำหนดค่าจะเผยแพร่ไปยังแพ็คเกจเป้าหมายและเปิดกิจกรรมเป้าหมายอีกครั้ง

การจำกัดทรัพยากรที่ซ้อนทับได้

ใน Android 10 หรือสูงกว่า <overlayable> แท็ก XML exposes ชุดของทรัพยากรที่ RROs ได้รับอนุญาตให้ซ้อนทับ ในตัวอย่างต่อไป res/values/overlayable.xml ไฟล์ string/foo และ integer/bar เป็นทรัพยากรที่ใช้สำหรับ theming ลักษณะของอุปกรณ์; ในการซ้อนทับทรัพยากรเหล่านี้ การซ้อนทับต้องกำหนดเป้าหมายคอลเลกชันของทรัพยากรที่ซ้อนทับได้อย่างชัดเจนตามชื่อ

<!-- 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> แท็ก แต่แท็กแต่ละคนจะต้องมีชื่อซ้ำกันภายในแพคเกจ ตัวอย่างเช่น มันคือ:

  • OK สำหรับสองแพคเกจที่แตกต่างกันทั้งกำหนด <overlayable name="foo">

  • ไม่ตกลงสำหรับเอพีเคเดียวที่จะมีสอง <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> แท็กซ้อนกำหนดเป้าหมาย app ที่:

  • ต้องระบุ targetName

  • สามารถวางซ้อนเพียงทรัพยากรที่ระบุไว้ภายใน <overlayable> แท็ก

  • สามารถกำหนดเป้าหมายเพียงหนึ่ง <overlayable> ชื่อ

คุณไม่สามารถเปิดใช้งานการซ้อนทับกำหนดเป้าหมายแพคเกจที่ exposes ทรัพยากร overlayable แต่ไม่ได้ใช้ android:targetName ในการกำหนดเป้าหมายที่เฉพาะเจาะจง <overlayable> แท็ก

นโยบายจำกัด

ใช้ <policy> แท็กในการบังคับใช้ข้อ จำกัด เกี่ยวกับทรัพยากร overlayable type ระบุแอตทริบิวต์ซึ่งนโยบายการซ้อนทับจะต้องปฏิบัติตามเพื่อแทนที่ทรัพยากรรวม ประเภทที่รองรับมีดังต่อไปนี้

  • public โอเวอร์เลย์ใดๆ สามารถแทนที่ทรัพยากรได้
  • system โอเวอร์เลย์ใดๆ บนพาร์ติชันระบบสามารถแทนที่รีซอร์สได้
  • vendor การซ้อนทับบนพาร์ติชันผู้จัดจำหน่ายสามารถแทนที่ทรัพยากรได้
  • product โอเวอร์เลย์ใดๆ บนพาร์ติชันผลิตภัณฑ์สามารถแทนที่รีซอร์สได้
  • signature โอเวอร์เลย์ใดๆ ที่ลงนามด้วยลายเซ็นเดียวกันกับ APK เป้าหมายสามารถแทนที่ทรัพยากรได้

แสดงให้เห็นว่ารหัสต่อไปตัวอย่างเช่น <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 ) เพื่อ RROs กำหนดค่าคงที่

การใช้ 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 ควบคุมแอตทริบิวต์หรือไม่ซ้อนทับไม่แน่นอนและสามารถมีรัฐเปิดการใช้งานเปลี่ยน programatically ที่รันไทม์ (ค่าปกติคือ true ) โอเวอร์เลย์ที่ไม่อยู่ในไฟล์คอนฟิกูเรชันสามารถเปลี่ยนแปลงได้และปิดใช้งานโดยค่าเริ่มต้น

ลำดับความสำคัญของโอเวอร์เลย์

เมื่อโอเวอร์เลย์หลายรายการแทนที่ทรัพยากรเดียวกัน ลำดับของการซ้อนทับจึงมีความสำคัญ โอเวอร์เลย์มีความสำคัญมากกว่าโอเวอร์เลย์ที่มีคอนฟิกูเรชันก่อนหน้าคอนฟิกูเรชันของตัวเอง ลำดับความสำคัญของการซ้อนทับในพาร์ติชันต่างๆ (จากลำดับความสำคัญน้อยไปมาก) มีดังนี้

  • system
  • vendor
  • oem
  • odm
  • 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>

การเปลี่ยนแปลงใน Android 11

ใน Android 11 หรือสูงกว่าถ้าแฟ้มการกำหนดค่าอยู่ใน partition/overlay/config/config.xml ซ้อนทับมีการกำหนดค่าใช้ว่าไฟล์และ android:isStatic และ android:priority ไม่ได้มีผลกระทบต่อการวางซ้อนอยู่ในพาร์ทิชัน การกำหนดไฟล์คอนฟิกูเรชันโอเวอร์เลย์ในพาร์ติชั่นใดๆ บังคับใช้ลำดับความสำคัญของโอเวอร์เลย์พาร์ติชั่น

นอกจากนี้ Android 11 ขึ้นไปจะลบความสามารถในการใช้สแตติกโอเวอร์เลย์เพื่อส่งผลต่อค่าของทรัพยากรที่อ่านระหว่างการติดตั้งแพ็คเกจ สำหรับกรณีการใช้งานทั่วไปของการใช้การซ้อนทับแบบคงที่จะเปลี่ยนค่าของ booleans ว่าองค์ประกอบที่กำหนดค่าเปิดใช้งานรัฐใช้ <component-override> SystemConfig แท็ก (ใหม่ใน Android 11)

การดีบักโอเวอร์เลย์

หากต้องการเปิดใช้งาน ปิดใช้งาน และดัมพ์โอเวอร์เลย์ด้วยตนเอง ให้ใช้คำสั่งเชลล์ตัวจัดการโอเวอร์เลย์ต่อไปนี้

adb shell cmd overlay

OverlayManagerService ใช้ idmap2 เพื่อทำแผนที่ทรัพยากรรหัสในแพคเกจเป้าหมายที่จะรหัสทรัพยากรในแพคเกจซ้อนทับ แมป ID ที่สร้างขึ้นจะถูกเก็บไว้ใน /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