การรองรับการตกแต่งระบบ

การอัปเดตที่ทำในพื้นที่เฉพาะของโฆษณา Display เหล่านี้จะแสดงในหน้านี้

การตกแต่งระบบ

Android 10 เพิ่มการรองรับการกำหนดค่าจอแสดงผลรอง เพื่อแสดงการตกแต่งระบบบางอย่าง เช่น วอลเปเปอร์ แถบนำทาง และตัวเรียกใช้ โดยค่าเริ่มต้น จอแสดงผลหลักจะแสดงการตกแต่งระบบทั้งหมด และจอแสดงผลรองจะแสดงการตกแต่งที่เปิดใช้โดยไม่บังคับ คุณตั้งค่าการรองรับตัวแก้ไขวิธีการป้อนข้อมูล (IME) แยกจากการตกแต่งระบบอื่นๆ ได้

ใช้ DisplayWindowSettings#setShouldShowSystemDecorsLocked() เพื่อเพิ่มการรองรับการตกแต่งระบบในจอแสดงผลที่เฉพาะเจาะจงหรือระบุ ค่าเริ่มต้นใน /data/system/display_settings.xml ดูตัวอย่างได้ที่การตั้งค่าหน้าต่างแสดงผล

การใช้งาน

DisplayWindowSettings#setShouldShowSystemDecorsLocked() ยังแสดงใน WindowManager#setShouldShowSystemDecors() เพื่อการทดสอบด้วย การเรียกใช้เมธอดนี้ โดยมีเจตนาที่จะเปิดใช้การตกแต่งระบบจะไม่เพิ่มหน้าต่างตกแต่งที่ ก่อนหน้านี้ไม่มีอยู่ หรือนำออกหากก่อนหน้านี้มีอยู่ ในกรณีส่วนใหญ่ การเปลี่ยนแปลงการรองรับการตกแต่งระบบจะมีผลอย่างเต็มที่หลังจาก รีบูตอุปกรณ์แล้วเท่านั้น

การตรวจสอบการรองรับการตกแต่งระบบในโค้ดเบสของ WindowManager มักจะผ่าน DisplayContent#supportsSystemDecorations() ในขณะที่ การตรวจสอบบริการภายนอก (เช่น System UI เพื่อตรวจสอบว่าควรแสดงแถบนำทางหรือไม่) จะใช้ WindowManager#shouldShowSystemDecors() หากต้องการทำความเข้าใจว่าการตั้งค่านี้ควบคุมอะไรบ้าง ให้ดูจุดเรียกใช้ของเมธอดเหล่านี้

หน้าต่างตกแต่ง UI ของระบบ

Android 10 เพิ่มการรองรับหน้าต่างตกแต่งระบบ สำหรับแถบนำทางเท่านั้น เนื่องจากแถบนำทางเป็นสิ่งจำเป็น สำหรับการไปยังส่วนต่างๆ ระหว่างกิจกรรมและแอป โดยค่าเริ่มต้น แถบนำทางจะแสดง ปุ่มย้อนกลับและปุ่มหน้าแรก ซึ่งจะรวมไว้ก็ต่อเมื่อจอแสดงผลเป้าหมายรองรับ การตกแต่งระบบ (ดู DisplayWindowSettings)

แถบสถานะเป็นหน้าต่างระบบที่ซับซ้อนกว่า เนื่องจากมีทั้งหน้าต่างการแจ้งเตือน การตั้งค่าด่วน และหน้าจอล็อก ใน Android 10 ระบบไม่รองรับแถบสถานะในจอแสดงผลรอง ดังนั้น การแจ้งเตือน การตั้งค่า และการล็อกแบบเต็มจะใช้ได้เฉพาะใน จอแสดงผลหลักเท่านั้น

หน้าต่างระบบภาพรวม/ล่าสุดไม่รองรับในหน้าจอรอง ใน Android 10 นั้น AOSP จะแสดงรายการล่าสุดใน จอแสดงผลเริ่มต้นเท่านั้น และมีกิจกรรมจากจอแสดงผลทั้งหมด เมื่อเปิดจาก ล่าสุด ระบบจะนำกิจกรรมที่อยู่บนจอแสดงผลรองมาไว้ด้านหน้าบนจอแสดงผลนั้นโดยค่าเริ่มต้น แนวทางนี้มีปัญหาที่ทราบกันอยู่บ้าง เช่น ไม่ อัปเดตทันทีเมื่อแอปปรากฏบนหน้าจออื่นๆ

การใช้งาน

หากต้องการใช้ฟีเจอร์ UI ของระบบเพิ่มเติม ผู้ผลิตอุปกรณ์ควรใช้คอมโพเนนต์ UI ของระบบเพียงรายการเดียวที่คอยฟังการเพิ่มหรือนำจอแสดงผลออก และแสดงเนื้อหาที่เหมาะสม

คอมโพเนนต์ UI ของระบบที่รองรับการแสดงผลหลายจอ (MD) ควรจัดการกรณีต่อไปนี้

  • การเริ่มต้นการแสดงผลหลายรายการเมื่อเริ่มต้นระบบ
  • เพิ่มจอแสดงผลที่รันไทม์
  • แสดงผลที่นำออกในขณะรันไทม์

เมื่อ UI ของระบบตรวจพบการเพิ่มจอแสดงผลก่อน WindowManager ระบบจะสร้าง สภาวะแข่ง คุณหลีกเลี่ยงปัญหานี้ได้โดยการใช้ Callback ที่กำหนดเองจาก WindowManager ไปยัง UI ของระบบเมื่อมีการเพิ่มจอแสดงผลแทนการสมัครรับข้อมูลเหตุการณ์ DisplayManager.DisplayListener ดูการติดตั้งใช้งานอ้างอิงได้ที่ CommandQueue.Callbacks#onDisplayAddSystemDecorations สำหรับการรองรับแถบนำทาง และ WallpaperManagerInternal#onDisplayAddSystemDecorations สำหรับวอลเปเปอร์

นอกจากนี้ Android 10 ยังมีการอัปเดตต่อไปนี้ด้วย

  • คลาส NavigationBarController จะควบคุมฟังก์ชันการทำงานทั้งหมด ที่เกี่ยวข้องกับแถบนำทาง
  • หากต้องการดูแถบนำทางที่ปรับแต่งแล้ว ให้ดูที่ CarStatusBar
  • TYPE_NAVIGATION_BAR ไม่ได้จำกัดไว้ที่อินสแตนซ์เดียวอีกต่อไปและสามารถใช้ต่อจอแสดงผลได้
  • IWindowManager#hasNavigationBar() ได้รับการอัปเดตให้รวมพารามิเตอร์ displayId สำหรับ UI ของระบบเท่านั้น

Launcher

ใน Android 10 แต่ละจอแสดงผลที่กำหนดค่าให้รองรับ การตกแต่งระบบจะมีสแต็กหน้าแรกเฉพาะสำหรับกิจกรรมตัวเรียกใช้ที่มีประเภท WindowConfiguration#ACTIVITY_TYPE_HOMEโดยค่าเริ่มต้น จอแสดงผลแต่ละจอ จะใช้กิจกรรมตัวเรียกใช้คนละอินสแตนซ์

รูปที่ 1 ตัวอย่างโปรแกรมเรียกใช้แบบหลายจอแสดงผลสำหรับ platform/development/samples/MultiDisplay

โดย Launcher ที่มีอยู่ส่วนใหญ่ไม่รองรับหลายอินสแตนซ์และไม่ได้ปรับให้เหมาะกับ หน้าจอขนาดใหญ่ นอกจากนี้ ผู้ใช้มักคาดหวังประสบการณ์การใช้งานที่แตกต่างกัน บนจอแสดงผลรอง/ภายนอก Android 10 ได้เปิดตัวSECONDARY_HOMEหมวดหมู่ในตัวกรอง Intent เพื่อจัดกิจกรรมเฉพาะสำหรับหน้าจอรอง ระบบจะใช้อินสแตนซ์ของกิจกรรมนี้ในจอแสดงผลทั้งหมดที่รองรับการตกแต่งระบบ จอแสดงผลละ 1 รายการ

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

กิจกรรมต้องมีโหมดการเปิดตัวที่ไม่อนุญาตให้มีหลายอินสแตนซ์ และคาดว่าจะปรับให้เข้ากับขนาดหน้าจอต่างๆ ได้ โหมดการเปิดตัว ต้องไม่ใช่ singleInstance หรือ singleTask

การใช้งาน

ใน Android 10 RootActivityContainer#startHomeOnDisplay() จะเลือกคอมโพเนนต์และ Intent ที่ต้องการโดยอัตโนมัติตามจอแสดงผล ที่เปิดใช้หน้าจอหลัก RootActivityContainer#resolveSecondaryHomeActivity() มีตรรกะในการค้นหาคอมโพเนนต์กิจกรรมของ Launcher โดยขึ้นอยู่กับ Launcher ที่เลือกในปัจจุบัน และสามารถใช้ค่าเริ่มต้นของระบบได้หากจำเป็น (ดู ActivityTaskManagerService#getSecondaryHomeIntent())

ข้อจำกัดด้านความปลอดภัย

นอกเหนือจากข้อจำกัดที่ใช้กับกิจกรรมบนจอแสดงผลรองแล้ว เพื่อหลีกเลี่ยงความเป็นไปได้ที่แอปที่เป็นอันตรายจะสร้างจอแสดงผลเสมือนที่มีการตกแต่งระบบ ที่เปิดใช้และอ่านข้อมูลที่ละเอียดอ่อนของผู้ใช้จากพื้นผิว ตัวเรียกใช้จะปรากฏเฉพาะ บนจอแสดงผลเสมือนที่เป็นของระบบ Launcher ไม่แสดงเนื้อหาในจอแสดงผลเสมือนที่ไม่ใช่ระบบ

วอลเปเปอร์

ใน Android 10 ขึ้นไป ระบบรองรับวอลเปเปอร์ในจอแสดงผลรอง

รูปที่ 2 วอลเปเปอร์เคลื่อนไหวบนจอแสดงผลภายใน (ด้านบน) และภายนอก (ด้านล่าง)

นักพัฒนาแอปสามารถประกาศการรองรับฟีเจอร์วอลเปเปอร์ได้โดยระบุ android:supportsMultipleDisplays="true" ในคำจำกัดความ XML ของ WallpaperInfo นอกจากนี้ นักพัฒนาวอลเปเปอร์ยัง ควรโหลดชิ้นงานโดยใช้บริบทการแสดงผลใน WallpaperService.Engine#getDisplayContext() ด้วย

เฟรมเวิร์กจะสร้างWallpaperService.Engineอินสแตนซ์ ต่อจอแสดงผล 1 รายการ เพื่อให้แต่ละเอนจินมีบริบทพื้นผิวและบริบทการแสดงผลของตัวเอง นักพัฒนาแอปต้องตรวจสอบว่าแต่ละเอนจินวาดภาพแยกกันได้ที่ อัตราเฟรมที่แตกต่างกันโดยคำนึงถึง VSync

เลือกวอลเปเปอร์สำหรับแต่ละหน้าจอ

Android 10 ไม่รองรับแพลตฟอร์มโดยตรงสำหรับการเลือกวอลเปเปอร์ สำหรับแต่ละหน้าจอ ในการดำเนินการนี้ คุณต้องมีตัวระบุการแสดงผลที่เสถียรเพื่อคงการตั้งค่าวอลเปเปอร์ต่อการแสดงผล Display#getDisplayId()เป็นแบบไดนามิก จึงไม่มีการรับประกันว่าจอแสดงผลจริงจะมีรหัสเดียวกันหลังจากรีบูต

อย่างไรก็ตาม Android 10 ได้เพิ่ม DisplayInfo.mAddress ซึ่งมีตัวระบุที่เสถียรสำหรับจอแสดงผลจริงและสามารถใช้สำหรับการติดตั้งใช้งานแบบเต็ม ในอนาคต ขออภัย เราไม่สามารถใช้ตรรกะ สำหรับ Android 10 ได้แล้ว วิธีแก้ปัญหาที่แนะนำ

  1. ใช้WallpaperManager คลาสเพื่อตั้งค่าวอลเปเปอร์

    WallpaperManager ได้มาจากออบเจ็กต์ Context และออบเจ็กต์ Context แต่ละรายการมีข้อมูลเกี่ยวกับ การแสดงผลที่เกี่ยวข้อง (Context#getDisplay()/getDisplayId()) ดังนั้นคุณจึง รับ displayId จากอินสแตนซ์ WallpaperManager ได้ โดยไม่ต้องเพิ่มเมธอดใหม่

  2. ในฝั่งเฟรมเวิร์ก ให้ใช้ displayId ที่ได้จากออบเจ็กต์ Context แล้วแมปกับตัวระบุแบบคงที่ (เช่น พอร์ตของ จอแสดงผลจริง) ใช้ตัวระบุแบบคงที่เพื่อคงวอลเปเปอร์ที่เลือกไว้

วิธีแก้ปัญหานี้ใช้การติดตั้งใช้งานที่มีอยู่สำหรับเครื่องมือเลือกวอลเปเปอร์ หากเปิดในจอแสดงผลที่เฉพาะเจาะจงและใช้บริบทที่ถูกต้อง เมื่อเรียกใช้เพื่อตั้งวอลเปเปอร์ ระบบจะระบุจอแสดงผลได้โดยอัตโนมัติ

หากจำเป็นต้องตั้งค่าวอลเปเปอร์สำหรับจอแสดงผลอื่นที่ไม่ใช่จอแสดงผลปัจจุบัน ให้สร้างออบเจ็กต์ Context ใหม่สำหรับจอแสดงผลเป้าหมาย (Context#createDisplayContext) และรับอินสแตนซ์ WallpaperManager จากจอแสดงผลนั้น

ข้อจำกัดด้านความปลอดภัย

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

การใช้งาน

ใน Android 10 อินเทอร์เฟซ IWallpaperConnection#attachEngine() และ IWallpaperService#attach() จะยอมรับพารามิเตอร์ displayId เพื่อสร้างการเชื่อมต่อต่อจอแสดงผล WallpaperManagerService.DisplayConnectorแคปซูลเครื่องมือและช่องทางการเชื่อมต่อวอลเปเปอร์ต่อจอแสดงผล ใน WindowManager จะมีการสร้างเครื่องควบคุมวอลเปเปอร์สำหรับออบเจ็กต์ DisplayContent แต่ละรายการในระหว่างการสร้างแทนที่จะสร้าง WallpaperController รายการเดียวสำหรับจอแสดงผลทั้งหมด

การใช้งานเมธอด WallpaperManager สาธารณะบางอย่าง (เช่น WallpaperManager#getDesiredMinimumWidth()) ได้รับการอัปเดตเพื่อคำนวณ และให้ข้อมูลสำหรับการแสดงผลที่เกี่ยวข้อง WallpaperInfo#supportsMultipleDisplays() และแอตทริบิวต์ทรัพยากรที่เกี่ยวข้อง เพื่อให้นักพัฒนาแอปสามารถรายงานวอลเปเปอร์ที่พร้อมสำหรับหลายหน้าจอได้

หากบริการวอลเปเปอร์ที่แสดงบนจอแสดงผลเริ่มต้นไม่รองรับจอแสดงผลหลายจอ ระบบจะแสดงวอลเปเปอร์เริ่มต้นบนจอแสดงผลรอง

รูปที่ 3 ตรรกะการเปลี่ยนวอลเปเปอร์สำรองสำหรับจอแสดงผลรอง