การอัปเดตที่ทำในพื้นที่เฉพาะการแสดงผลเหล่านี้มีดังต่อไปนี้:
ตกแต่งระบบ
Android 10 เพิ่มการรองรับการกำหนดค่าจอแสดงผลรองเพื่อแสดงการตกแต่งระบบบางอย่าง เช่น วอลเปเปอร์ แถบนำทาง และ Launcher ตามค่าเริ่มต้น จอแสดงผลหลักจะแสดงการตกแต่งระบบทั้งหมด และจอแสดงผลรองจะแสดงการตกแต่งที่เลือกได้ การสนับสนุนตัวแก้ไขวิธีการป้อนข้อมูล (IME) สามารถตั้งค่าแยกต่างหากจากการตกแต่งระบบอื่นๆ
ใช้ DisplayWindowSettings#setShouldShowSystemDecorsLocked()
เพื่อเพิ่มการสนับสนุนสำหรับการตกแต่งระบบบนจอแสดงผลเฉพาะหรือระบุค่าเริ่มต้นใน /data/system/display_settings.xml
ตัวอย่างเช่น โปรดดู การตั้งค่าหน้าต่างการแสดงผล
การนำไปปฏิบัติ
DisplayWindowSettings#setShouldShowSystemDecorsLocked()
ยังถูกเปิดเผยใน WindowManager#setShouldShowSystemDecors()
สำหรับการทดสอบอีกด้วย การเรียกใช้วิธีนี้โดยมีเจตนาที่จะเปิดใช้งานการตกแต่งระบบจะไม่เพิ่มหน้าต่างการตกแต่งที่หายไปก่อนหน้านี้ หรือลบออกหากก่อนหน้านี้มีอยู่ ในกรณีส่วนใหญ่ การเปลี่ยนแปลงการสนับสนุนการตกแต่งระบบจะมีผลสมบูรณ์หลังจากการรีบูตอุปกรณ์เท่านั้น
การตรวจสอบการสนับสนุนการตกแต่งระบบในฐานโค้ด WindowManager มักจะดำเนินการผ่าน DisplayContent#supportsSystemDecorations()
ในขณะที่ตรวจสอบบริการภายนอก (เช่น System UI เพื่อตรวจสอบว่าควรแสดงแถบนำทางหรือไม่) ให้ใช้ WindowManager#shouldShowSystemDecors()
เพื่อทำความเข้าใจสิ่งที่ควบคุมโดยการตั้งค่านี้ ให้สำรวจจุดโทรของวิธีการเหล่านี้
หน้าต่างตกแต่ง UI ของระบบ
Android 10 เพิ่มการรองรับหน้าต่างตกแต่งระบบสำหรับแถบนำทาง เท่านั้น เนื่องจากแถบนำทางจำเป็นสำหรับการนำทางระหว่างกิจกรรมและแอพ ตามค่าเริ่มต้น แถบนำทางจะแสดงค่า Back และ Home ซึ่งจะรวมไว้เฉพาะในกรณีที่จอแสดงผลเป้าหมายรองรับการตกแต่งระบบ (ดู DisplayWindowSettings
)
แถบสถานะ เป็นหน้าต่างระบบที่ซับซ้อนกว่า เนื่องจากมีแถบการแจ้งเตือน การตั้งค่าด่วน และหน้าจอล็อคด้วย ใน Android 10 ไม่รองรับแถบสถานะบนจอแสดงผลรอง ดังนั้นการแจ้งเตือน การตั้งค่า และการป้องกันปุ่มแบบเต็มจึงใช้งานได้บนจอแสดงผลหลักเท่านั้น
ไม่รองรับหน้าต่างระบบ ภาพรวม/ล่าสุด บนหน้าจอรอง ใน Android 10 AOSP จะแสดงเฉพาะล่าสุดบนจอแสดงผลเริ่มต้นและมีกิจกรรมจากจอแสดงผลทั้งหมด เมื่อเปิดใช้งานจากล่าสุด กิจกรรมที่อยู่บนจอแสดงผลรองจะถูกนำมาที่ด้านหน้าของจอแสดงผลนั้นตามค่าเริ่มต้น วิธีการนี้มีปัญหาที่ทราบบางประการ เช่น การไม่อัปเดตทันทีเมื่อแอปปรากฏบนหน้าจออื่น
การนำไปปฏิบัติ
หากต้องการใช้คุณลักษณะ System UI เพิ่มเติม ผู้ผลิตอุปกรณ์ควรใช้ส่วนประกอบ System UI เดียวที่คอยรับฟังการเพิ่ม/ลบจอแสดงผลและนำเสนอเนื้อหาที่เหมาะสม
ส่วนประกอบ System UI ที่รองรับ Multi-Display (MD) ควรจัดการกับกรณีต่อไปนี้:
- การเริ่มต้นการแสดงผลหลายจอเมื่อเริ่มต้น
- เพิ่มจอแสดงผลเมื่อรันไทม์
- จอแสดงผลถูกลบออกขณะรันไทม์
เมื่อ System UI ตรวจพบการเพิ่มจอแสดงผลก่อน WindowManager ระบบจะสร้างสภาวะการแข่งขัน สิ่งนี้สามารถหลีกเลี่ยงได้โดยการใช้การเรียกกลับแบบกำหนดเองจาก WindowManager ไปยัง System UI เมื่อมีการเพิ่มจอแสดงผลแทนที่จะสมัครรับเหตุการณ์ DisplayManager .DisplayListener
สำหรับการดำเนินการอ้างอิง โปรดดูที่ CommandQueue.Callbacks#onDisplayReady
สำหรับการรองรับแถบนำทาง และ WallpaperManagerInternal#onDisplayReady
สำหรับวอลเปเปอร์
นอกจากนี้ Android 10 ยังมีการอัปเดตเหล่านี้:
- คลาส
NavigationBarController
ควบคุมการทำงานทั้งหมดที่เฉพาะเจาะจงสำหรับแถบนำทาง - หากต้องการดูแถบนำทางแบบกำหนดเอง โปรดดูที่
CarStatusBar
-
TYPE_NAVIGATION_BAR
ไม่ได้จำกัดอยู่เพียงอินสแตนซ์เดียวอีกต่อไป และสามารถใช้ได้ต่อจอแสดงผล -
IWindowManager#hasNavigationBar()
ได้รับการอัปเดตเพื่อรวมพารามิเตอร์displayId
สำหรับ System UI เท่านั้น
ตัวเปิด
ใน Android 10 จอแสดงผลแต่ละจอที่กำหนดค่าให้รองรับการตกแต่งระบบจะมีโฮมสแต็กเฉพาะสำหรับกิจกรรมตัวเรียกใช้งานประเภท WindowConfiguration#ACTIVITY_TYPE_HOME
ตามค่าเริ่มต้น แต่ละจอแสดงผลใช้กิจกรรมตัวเรียกใช้งานแยกต่างหาก
รูปที่ 1 ตัวอย่างตัวเรียกใช้งานหลายจอแสดงผลสำหรับ platform/development/samples/MultiDisplay
ตัวเรียกใช้งานที่มีอยู่ส่วนใหญ่ไม่รองรับหลายอินสแตนซ์และไม่ได้รับการปรับให้เหมาะกับขนาดหน้าจอขนาดใหญ่ นอกจากนี้ มักจะคาดหวังประสบการณ์ที่แตกต่างออกไปในจอแสดงผลรอง/จอแสดงผลภายนอก เพื่อจัดเตรียมกิจกรรมเฉพาะสำหรับหน้าจอรอง Android 10 ขอแนะนำหมวดหมู่ SECONDARY_HOME
ในตัวกรอง Intent อินสแตนซ์ของกิจกรรมนี้ใช้กับจอแสดงผลทั้งหมดที่รองรับการตกแต่งระบบ หนึ่งจอต่อจอแสดงผล
<activity> ... <intent-filter> <category android:name="android.intent.category.SECONDARY_HOME" /> ... </intent-filter> </activity>
กิจกรรมต้องมีโหมดการเปิดตัวที่ไม่ป้องกันหลายอินสแตนซ์ และคาดว่าจะปรับให้เข้ากับขนาดหน้าจอที่แตกต่างกัน โหมดการเปิดตัวไม่สามารถเป็น singleInstance
หรือ singleTask
การนำไปปฏิบัติ
ใน Android 10 นั้น RootActivityContainer#startHomeOnDisplay()
จะเลือกส่วนประกอบและจุดประสงค์ที่ต้องการโดยอัตโนมัติ ขึ้นอยู่กับจอแสดงผลที่หน้าจอหลักเปิดขึ้น RootActivityContainer#resolveSecondaryHomeActivity()
มีตรรกะเพื่อค้นหาคอมโพเนนต์กิจกรรมตัวเรียกใช้งาน ขึ้นอยู่กับตัวเรียกทำงานที่เลือกในปัจจุบัน และสามารถใช้ค่าดีฟอลต์ของระบบได้ หากจำเป็น (ดู ActivityTaskManagerService#getSecondaryHomeIntent()
ข้อจำกัดด้านความปลอดภัย
นอกเหนือจากข้อจำกัดที่ใช้กับกิจกรรมบนจอแสดงผลรอง เพื่อหลีกเลี่ยงความเป็นไปได้ที่แอปที่เป็นอันตรายจะสร้างจอแสดงผลเสมือนพร้อม การตกแต่งระบบ ที่เปิดใช้งาน และการอ่านข้อมูลที่ละเอียดอ่อนของผู้ใช้จากพื้นผิว ตัวเรียกใช้งานจะปรากฏเฉพาะบนจอแสดงผลเสมือนที่ระบบเป็นเจ้าของเท่านั้น ตัวเรียกใช้งานไม่แสดงเนื้อหาบนจอแสดงผลเสมือนที่ไม่ใช่ระบบ
วอลเปเปอร์
ใน Android 10 (และสูงกว่า) วอลเปเปอร์ได้รับการรองรับบนจอแสดงผลรอง:
รูปที่ 2 Live Wallpaper บนจอแสดงผลภายใน (ด้านบน) และภายนอก (ด้านล่าง)
นักพัฒนาสามารถประกาศการสนับสนุนคุณสมบัติวอลเปเปอร์ได้โดยระบุ android:supportsMultipleDisplays="true"
ในคำจำกัดความ WallpaperInfo
XML นักพัฒนาวอลเปเปอร์ยังได้รับการคาดหวังให้โหลดเนื้อหาโดยใช้บริบทการแสดงผลใน WallpaperService.Engine#getDisplayContext()
เฟรมเวิร์กจะสร้างอินสแตนซ์ WallpaperService.Engine
หนึ่งอินสแตนซ์ต่อจอแสดงผล ดังนั้นแต่ละเอ็นจิ้นจึงมีพื้นผิวและบริบทการแสดงผลของตัวเอง นักพัฒนาจำเป็นต้องตรวจสอบให้แน่ใจว่าแต่ละเอ็นจิ้นสามารถวาดได้อย่างอิสระที่อัตราเฟรมที่แตกต่างกัน โดยคำนึงถึง VSYNC
เลือกวอลเปเปอร์สำหรับแต่ละหน้าจอ
Android 10 ไม่รองรับแพลตฟอร์มโดยตรงสำหรับการเลือกวอลเปเปอร์สำหรับแต่ละหน้าจอ เพื่อให้บรรลุเป้าหมายนี้ จำเป็นต้องมีตัวระบุการแสดงผลที่เสถียรเพื่อคงการตั้งค่าวอลเปเปอร์ต่อจอแสดงผล Display#getDisplayId()
เป็นแบบไดนามิก ดังนั้นจึงไม่มีการรับประกันว่าจอแสดงผลจริงจะมีรหัสเดียวกันหลังจากรีบูต
อย่างไรก็ตาม Android 10 ได้เพิ่ม DisplayInfo.mAddress
ซึ่งมีตัวระบุที่เสถียรสำหรับการแสดงผลจริงและสามารถนำมาใช้เพื่อการใช้งานเต็มรูปแบบได้ในอนาคต ขออภัย มันสายเกินไปที่จะใช้ตรรกะสำหรับ Android 10 วิธีแก้ไขที่แนะนำ:
- ใช้
WallpaperManager
API เพื่อตั้งค่าวอลเปเปอร์ -
WallpaperManager
ได้มาจากContext
บริบท และแต่ละContext
บริบทมีข้อมูลเกี่ยวกับการแสดงผลที่สอดคล้องกัน (Context#getDisplay()/getDisplayId()
) ดังนั้น คุณสามารถรับdisplayId
จากอินสแตนซ์WallpaperManager
ได้โดยไม่ต้องเพิ่มวิธีการใหม่ - ในด้านเฟรมเวิร์ก ให้ใช้
displayId
ที่ได้รับจากContext
บริบท และแมปกับตัวระบุแบบคงที่ (เช่น พอร์ตของจอแสดงผลจริง) ใช้ตัวระบุแบบคงที่เพื่อคงวอลเปเปอร์ที่เลือกไว้
วิธีแก้ปัญหานี้ใช้การใช้งานที่มีอยู่สำหรับตัวเลือกวอลเปเปอร์ หากเปิดบนจอแสดงผลเฉพาะและใช้บริบทที่ถูกต้อง เมื่อเรียกให้ตั้งค่าวอลเปเปอร์ ระบบจะสามารถระบุจอแสดงผลได้โดยอัตโนมัติ
หากจำเป็นต้องตั้งค่าวอลเปเปอร์สำหรับจอแสดงผลอื่นที่ไม่ใช่จอแสดงผลปัจจุบัน ให้สร้าง Context
บริบทใหม่สำหรับจอแสดงผลเป้าหมาย ( Context#createDisplayContext
) และรับอินสแตนซ์ WallpaperManager
จากจอแสดงผลนั้น
ข้อจำกัดด้านความปลอดภัย
ระบบจะไม่แสดงวอลเปเปอร์บนจอแสดงผลเสมือนจริงที่ระบบไม่ได้เป็นเจ้าของ นี่เป็นเพราะข้อกังวลด้านความปลอดภัยที่แอปที่เป็นอันตรายสามารถสร้างจอแสดงผลเสมือนที่รองรับการตกแต่งระบบที่เปิดใช้งาน และอ่านข้อมูลที่ละเอียดอ่อนของผู้ใช้จากพื้นผิว (เช่น ภาพถ่ายส่วนตัว)
การนำไปปฏิบัติ
ใน Android 10 IWallpaperConnection#attachEngine()
และ IWallpaperService#attach()
ยอมรับพารามิเตอร์ displayId
เพื่อสร้างการเชื่อมต่อต่อจอแสดงผล WallpaperManagerService.DisplayConnector
สรุปเอ็นจิ้นวอลเปเปอร์ต่อการแสดงผลและการเชื่อมต่อ ใน WindowManager ตัวควบคุมวอลเปเปอร์จะถูกสร้างขึ้นสำหรับออบเจ็กต์ DisplayContent
แต่ละรายการในขณะที่สร้าง แทนที่จะเป็น WallpaperController
ตัวเดียวสำหรับจอแสดงผลทั้งหมด
การใช้งานเมธอด WallpaperManager
สาธารณะบางส่วน (เช่น WallpaperManager#getDesiredMinimumWidth()
) ได้รับการอัปเดตเพื่อคำนวณและให้ข้อมูลสำหรับจอแสดงผลที่เกี่ยวข้อง WallpaperInfo#supportsMultipleDisplays()
และแอตทริบิวต์ทรัพยากรที่เกี่ยวข้องถูกเพิ่มเข้ามา เพื่อให้นักพัฒนาแอปสามารถรายงานว่าวอลเปเปอร์ใดบ้างที่พร้อมสำหรับหลายหน้าจอ
หากบริการวอลเปเปอร์ที่แสดงบนจอแสดงผลเริ่มต้นไม่รองรับจอแสดงผลหลายจอ ระบบจะแสดงวอลเปเปอร์เริ่มต้นบนจอแสดงผลรอง
รูปที่ 3. ตรรกะทางเลือกของวอลเปเปอร์สำหรับจอแสดงผลรอง