การอัปเดตที่ทำในพื้นที่เฉพาะของโฆษณา Display เหล่านี้จะแสดงในหน้านี้
การตกแต่งระบบ
Android 10 เพิ่มการรองรับการกำหนดค่าจอแสดงผลรองเพื่อแสดงการตกแต่งระบบบางอย่าง เช่น วอลเปเปอร์ แถบนำทาง และตัวเรียกใช้ โดยค่าเริ่มต้น จอแสดงผลหลักจะแสดงการตกแต่งระบบทั้งหมด และ จอแสดงผลรองจะแสดงการตกแต่งที่เปิดใช้โดยไม่บังคับ คุณตั้งค่าการรองรับตัวแก้ไขวิธีการป้อนข้อมูล (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 ระบบจะสร้างภาวะแข่งขัน คุณหลีกเลี่ยงปัญหานี้ได้โดยการใช้ Callback ที่กำหนดเองจาก
WindowManager ไปยัง UI ของระบบเมื่อเพิ่มจอแสดงผลแทนการสมัครรับข้อมูลเหตุการณ์ DisplayManager.DisplayListener ดูการติดตั้งใช้งานอ้างอิงได้ที่
CommandQueue.Callbacks#onDisplayAddSystemDecorations
สำหรับการรองรับแถบนำทาง
และ WallpaperManagerInternal#onDisplayAddSystemDecorations
สำหรับวอลเปเปอร์
นอกจากนี้ Android 10 ยังมีการอัปเดตต่อไปนี้ด้วย
- คลาส
NavigationBarControllerควบคุมฟังก์ชันการทำงานทั้งหมด ที่เฉพาะเจาะจงกับแถบนำทาง - หากต้องการดูแถบนำทางที่ปรับแต่งแล้ว ให้ดู
CarStatusBar TYPE_NAVIGATION_BARไม่ได้จำกัดไว้ที่อินสแตนซ์เดียวอีกต่อไปและสามารถใช้ต่อจอแสดงผลได้IWindowManager#hasNavigationBarได้รับการอัปเดตให้มีพารามิเตอร์displayIdสำหรับ UI ของระบบเท่านั้น
Launcher
ใน Android 10 แต่ละจอแสดงผลที่กำหนดค่าให้รองรับ
การตกแต่งระบบจะมีสแต็กหน้าแรกเฉพาะสำหรับกิจกรรมของ Launcher ที่มีประเภท
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
มีตรรกะในการค้นหาคอมโพเนนต์กิจกรรมของตัวเรียกใช้โดยขึ้นอยู่กับตัวเรียกใช้ที่เลือกในปัจจุบัน
และสามารถใช้ค่าเริ่มต้นของระบบได้หากจำเป็น (ดู
ActivityTaskManagerService#getSecondaryHomeIntent)
ข้อจำกัดด้านความปลอดภัย
นอกเหนือจากข้อจำกัดที่ใช้กับกิจกรรมบนจอแสดงผลรองแล้ว เพื่อหลีกเลี่ยงความเป็นไปได้ที่แอปที่เป็นอันตรายจะสร้างจอแสดงผลเสมือนที่มีการตกแต่งระบบ และอ่านข้อมูลที่ละเอียดอ่อนของผู้ใช้จากพื้นผิว ตัวเรียกใช้งานจะปรากฏเฉพาะ บนจอแสดงผลเสมือนที่เป็นของระบบเท่านั้น ตัวเรียกใช้จะไม่แสดงเนื้อหาในจอแสดงผลเสมือนที่ไม่ใช่ระบบ
วอลเปเปอร์
ใน 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 ได้แล้ว วิธีแก้ปัญหาที่แนะนำ
- ใช้
WallpaperManagerคลาสเพื่อตั้งค่าวอลเปเปอร์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 ตรรกะการเปลี่ยนวอลเปเปอร์สำหรับจอแสดงผลรอง
เปิดใช้การรองรับวอลเปเปอร์เคลื่อนไหว
ใน Android 10 ขึ้นไป (API 29) นักพัฒนาแอปสามารถใช้แอตทริบิวต์ android:supportsMultipleDisplays
เพื่อระบุว่าวอลเปเปอร์ของตนเองจะแสดงในจอแสดงผลต่างๆ ได้หรือไม่ ในสภาพแวดล้อมของหน้าต่างเดสก์ท็อป
ซึ่งมีการทำงานแบบมัลติทาสก์อย่างหนาแน่น การแสดงวอลเปเปอร์เคลื่อนไหวบนจอแสดงผลภายนอกอาจส่งผลกระทบอย่างมากต่อ
ค่าใช้จ่ายของ GPU และหน่วยความจำ
ระบบจะไม่แสดงวอลเปเปอร์เคลื่อนไหวบนจอแสดงผลที่เชื่อมต่อโดยค่าเริ่มต้นเพื่อรักษาทรัพยากรของระบบ เมื่อมีการจำกัดวอลเปเปอร์เคลื่อนไหวโดยการกำหนดค่าระบบหรือ ไฟล์ Manifest ของแอป ระบบจะแสดงวอลเปเปอร์แบบคงที่สำรอง
OEM สามารถปรับแต่งประสบการณ์นี้ได้โดยการเปิดใช้การรองรับวอลเปเปอร์เคลื่อนไหวสำหรับฮาร์ดแวร์ระดับไฮเอนด์ หรือปรับแต่งวอลเปเปอร์สำรองแบบคงที่เพื่อให้มีรูปลักษณ์ของแบรนด์
หากฮาร์ดแวร์แสดงผลวอลเปเปอร์เคลื่อนไหวหลายอินสแตนซ์ได้ ให้ลบล้างการกำหนดค่าต่อไปนี้
| เส้นทางทรัพยากร | frameworks/base/core/res/res/values/config.xml |
|---|---|
| ชื่อการกำหนดค่า | config_isLiveWallpaperSupportedInDesktopExperience |
ปรับแต่งวอลเปเปอร์สำรอง
หากผู้ให้บริการปิดใช้หรือไม่รองรับวอลเปเปอร์เคลื่อนไหว ระบบจะใช้คอมโพเนนต์เริ่มต้น คุณสามารถชี้ไปยังผู้ให้บริการวอลเปเปอร์แบบคงที่ของคุณเองได้โดยทำดังนี้
| เส้นทางทรัพยากร | frameworks/base/core/res/res/values/config.xml |
|---|---|
| ชื่อการกำหนดค่า | fallback_wallpaper_component |
ใช้การรองรับวอลเปเปอร์
หากต้องการใช้การเปลี่ยนแปลงเหล่านี้ ให้ใช้การวางซ้อนทรัพยากรในเวลาบิลด์ในโฟลเดอร์เฉพาะอุปกรณ์ ซึ่งโดยปกติคือ device/<vendor>/<product>/overlay/frameworks/base/core/res/res/values/