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

การอัปเดตที่ทํากับพื้นที่เฉพาะของจอแสดงผลมีดังนี้

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

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

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

การใช้งาน

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

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

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

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

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

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

การใช้งาน

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

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

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

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

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

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

ปืนยิงลูกระเบิด

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

รูปที่ 1 ตัวอย่างตัวเปิดหลายจอภาพสำหรับ platform/development/samples/MultiDisplay

โปรแกรมเปิดแอปที่มีอยู่ส่วนใหญ่ไม่รองรับอินสแตนซ์หลายรายการและไม่ได้เพิ่มประสิทธิภาพสำหรับหน้าจอขนาดใหญ่ นอกจากนี้ ผู้ใช้มักคาดหวังประสบการณ์การใช้งานที่แตกต่างออกไปบนจอแสดงผลรอง/ภายนอก 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())

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

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

วอลเปเปอร์

ใน Android 10 (และเวอร์ชันที่ใหม่กว่า) รองรับวอลเปเปอร์ในจอแสดงผลรอง ดังนี้

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

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

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

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

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

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

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

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

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

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

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

การใช้งาน

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

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

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

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