Thông tin cập nhật về những khu vực dành riêng cho quảng cáo hiển thị này sẽ được cung cấp trên trang này.
Thành phần trang trí hệ thống
Android 10 bổ sung tính năng hỗ trợ định cấu hình màn hình phụ để hiển thị một số thành phần trang trí hệ thống, chẳng hạn như hình nền, thanh điều hướng và trình chạy. Theo mặc định, màn hình chính sẽ hiển thị tất cả các thành phần trang trí hệ thống và màn hình phụ sẽ hiển thị những thành phần được bật (nếu có). Bạn có thể thiết lập chế độ hỗ trợ cho trình chỉnh sửa phương thức nhập (IME) riêng biệt với các thành phần trang trí khác của hệ thống.
Sử dụng DisplayWindowSettings#setShouldShowSystemDecorsLocked()
để thêm tính năng hỗ trợ cho các thành phần trang trí hệ thống trên một màn hình cụ thể hoặc cung cấp giá trị mặc định trong /data/system/display_settings.xml
. Để biết ví dụ, hãy xem phần Chế độ cài đặt cửa sổ hiển thị.
Triển khai
DisplayWindowSettings#setShouldShowSystemDecorsLocked()
cũng được hiển thị trong WindowManager#setShouldShowSystemDecors()
để kiểm thử. Việc kích hoạt phương thức này với mục đích bật các thành phần trang trí hệ thống sẽ không thêm các cửa sổ trang trí bị thiếu trước đó hoặc xoá chúng nếu chúng đã có trước đó. Trong hầu hết các trường hợp, thay đổi về chế độ hỗ trợ thành phần trang trí hệ thống chỉ có hiệu lực hoàn toàn sau khi thiết bị khởi động lại.
Các hoạt động kiểm tra để hỗ trợ trang trí hệ thống trong cơ sở mã WindowManager thường diễn ra thông qua DisplayContent#supportsSystemDecorations()
, trong khi các hoạt động kiểm tra dịch vụ bên ngoài (chẳng hạn như Giao diện người dùng hệ thống để kiểm tra xem thanh điều hướng có nên xuất hiện hay không) sẽ sử dụng WindowManager#shouldShowSystemDecors()
.
Để hiểu rõ chế độ cài đặt này kiểm soát những gì, hãy khám phá các điểm gọi của những phương thức này.
Cửa sổ trang trí giao diện người dùng hệ thống
Android 10 chỉ hỗ trợ cửa sổ trang trí hệ thống cho thanh điều hướng , vì thanh điều hướng là thành phần thiết yếu để di chuyển giữa các hoạt động và ứng dụng. Theo mặc định, thanh điều hướng sẽ hiển thị các thành phần hỗ trợ thao tác Quay lại và Trang chủ. Điều này chỉ được đưa vào nếu màn hình đích hỗ trợ các thành phần trang trí hệ thống (xem DisplayWindowSettings
).
Thanh trạng thái là một cửa sổ hệ thống phức tạp hơn vì thanh này cũng chứa Ngăn thông báo, phần Cài đặt nhanh và Màn hình khoá. Trong Android 10, thanh trạng thái không được hỗ trợ trên màn hình phụ. Do đó, thông báo, chế độ cài đặt và toàn bộ khoá bảo vệ chỉ có trên màn hình chính.
Cửa sổ hệ thống Tổng quan/Gần đây không được hỗ trợ trên màn hình phụ. Trong Android 10, AOSP chỉ hiển thị phần Gần đây trên màn hình mặc định và chứa các hoạt động từ tất cả màn hình. Khi chạy từ phần Gần đây, theo mặc định, một hoạt động trên màn hình phụ sẽ được đưa lên trước trên màn hình đó. Phương pháp này có một số vấn đề đã biết, chẳng hạn như không cập nhật ngay khi các ứng dụng xuất hiện trên màn hình khác.
Triển khai
Để triển khai các tính năng bổ sung của Giao diện người dùng hệ thống, nhà sản xuất thiết bị nên sử dụng một thành phần duy nhất của Giao diện người dùng hệ thống để theo dõi việc thêm hoặc xoá màn hình và trình bày nội dung phù hợp.
Một thành phần Giao diện người dùng hệ thống hỗ trợ Nhiều màn hình (MD) sẽ xử lý các trường hợp sau:
- Khởi chạy nhiều màn hình khi khởi động
- Hiển thị được thêm vào trong thời gian chạy
- Màn hình bị xoá tại thời gian chạy
Khi Giao diện người dùng hệ thống phát hiện thấy việc thêm một màn hình trước WindowManager, thì điều này sẽ tạo ra một tình trạng xung đột. Bạn có thể tránh điều này bằng cách triển khai một lệnh gọi lại tuỳ chỉnh từ WindowManager đến Giao diện người dùng hệ thống khi một màn hình được thêm vào thay vì đăng ký các sự kiện DisplayManager.DisplayListener
. Để tham khảo cách triển khai, hãy xem CommandQueue.Callbacks#onDisplayAddSystemDecorations
để biết thông tin hỗ trợ thanh điều hướng và WallpaperManagerInternal#onDisplayAddSystemDecorations
để biết thông tin về hình nền.
Ngoài ra, Android 10 còn cung cấp những điểm cập nhật sau:
- Lớp
NavigationBarController
kiểm soát mọi chức năng dành riêng cho thanh điều hướng. - Để xem thanh điều hướng tuỳ chỉnh, hãy xem phần
CarStatusBar
. TYPE_NAVIGATION_BAR
không còn bị giới hạn ở một phiên bản duy nhất và có thể dùng cho mỗi màn hình.IWindowManager#hasNavigationBar()
được cập nhật để chỉ bao gồm tham sốdisplayId
cho Giao diện người dùng hệ thống.
Trình chạy
Trong Android 10, theo mặc định, mỗi màn hình được định cấu hình để hỗ trợ các thành phần trang trí hệ thống đều có một ngăn xếp trang chủ riêng cho các hoạt động của trình chạy có loại WindowConfiguration#ACTIVITY_TYPE_HOME
. Mỗi màn hình sử dụng một phiên bản riêng của hoạt động trình chạy:
Hình 1. Ví dụ về trình chạy nhiều màn hình cho platform/development/samples/MultiDisplay.
Hầu hết trình chạy hiện có đều không hỗ trợ nhiều phiên bản và không được tối ưu hoá cho kích thước màn hình lớn. Ngoài ra, người dùng thường mong đợi một loại trải nghiệm khác trên màn hình phụ/màn hình ngoài. Để cung cấp một hoạt động chuyên biệt cho màn hình phụ, Android 10 đã giới thiệu danh mục SECONDARY_HOME
trong bộ lọc ý định. Các thực thể của hoạt động này được dùng trên tất cả các màn hình hỗ trợ các thành phần trang trí hệ thống, một thực thể cho mỗi màn hình.
<activity> ... <intent-filter> <category android:name="android.intent.category.SECONDARY_HOME" /> ... </intent-filter> </activity>
Hoạt động phải có một chế độ chạy cho phép tồn tại nhiều thực thể và dự kiến sẽ thích ứng với nhiều kích thước màn hình. Chế độ chạy không được là singleInstance
hoặc singleTask
.
Triển khai
Trong Android 10, RootActivityContainer#startHomeOnDisplay()
sẽ tự động chọn thành phần và ý định mong muốn tuỳ thuộc vào màn hình nơi màn hình chính được khởi chạy. RootActivityContainer#resolveSecondaryHomeActivity()
chứa logic để tra cứu thành phần hoạt động của trình chạy tuỳ thuộc vào trình chạy hiện được chọn và có thể sử dụng trình chạy mặc định của hệ thống (nếu cần) (xem ActivityTaskManagerService#getSecondaryHomeIntent()
).
Quy định hạn chế về bảo mật
Ngoài các quy định hạn chế áp dụng cho hoạt động trên màn hình phụ, để tránh trường hợp ứng dụng độc hại tạo màn hình ảo có Phần trang trí hệ thống được bật và đọc thông tin nhạy cảm của người dùng từ màn hình, trình chạy chỉ xuất hiện trên màn hình ảo do hệ thống sở hữu. Trình chạy không hiển thị nội dung trên màn hình ảo không phải là màn hình ảo của hệ thống.
Hình nền
Trong Android 10 trở lên, hình nền được hỗ trợ trên màn hình phụ:
Hình 2. Hình nền động trên màn hình trong (ở trên) và màn hình ngoài (ở dưới).
Nhà phát triển có thể khai báo hỗ trợ tính năng hình nền bằng cách cung cấp android:supportsMultipleDisplays="true"
trong định nghĩa XML WallpaperInfo
. Nhà phát triển hình nền cũng dự kiến sẽ tải các thành phần bằng cách sử dụng bối cảnh hiển thị trong WallpaperService.Engine#getDisplayContext()
.
Khung này tạo một thực thể WallpaperService.Engine
cho mỗi màn hình, vì vậy, mỗi công cụ đều có ngữ cảnh hiển thị và nền tảng riêng. Nhà phát triển cần đảm bảo rằng mỗi công cụ có thể vẽ độc lập, ở các tốc độ khung hình khác nhau, tuân theo VSync.
Chọn hình nền cho từng màn hình
Android 10 không hỗ trợ trực tiếp nền tảng để chọn hình nền cho từng màn hình. Để thực hiện việc này, bạn cần có một mã nhận dạng màn hình ổn định để duy trì các chế độ cài đặt hình nền cho mỗi màn hình.
Display#getDisplayId()
là động, vì vậy, không có gì đảm bảo rằng màn hình thực sẽ có cùng một mã nhận dạng sau khi khởi động lại.
Tuy nhiên, Android 10 đã thêm DisplayInfo.mAddress
, chứa các giá trị nhận dạng ổn định cho màn hình thực và có thể được dùng để triển khai đầy đủ trong tương lai. Rất tiếc, đã quá muộn để triển khai logic cho Android 10. Giải pháp được đề xuất:
- Sử dụng lớp
WallpaperManager
để đặt hình nền.WallpaperManager
được lấy từ một đối tượngContext
và mỗi đối tượngContext
có thông tin về màn hình tương ứng (Context#getDisplay()/getDisplayId()
). Do đó, bạn có thể lấydisplayId
từ một thực thểWallpaperManager
mà không cần thêm phương thức mới. - Về phía khung, hãy dùng
displayId
lấy từ đối tượngContext
rồi ánh xạ đối tượng đó đến một giá trị nhận dạng tĩnh (chẳng hạn như cổng của màn hình thực). Sử dụng giá trị nhận dạng tĩnh để duy trì hình nền đã chọn.
Giải pháp này sử dụng các phương thức triển khai hiện có cho bộ chọn hình nền. Nếu được mở trên một màn hình cụ thể và sử dụng đúng ngữ cảnh, thì khi gọi để đặt hình nền, hệ thống có thể tự động xác định màn hình.
Nếu cần đặt hình nền cho một màn hình khác với màn hình hiện tại, hãy tạo một đối tượng Context
mới cho màn hình đích (Context#createDisplayContext
) và lấy thực thể WallpaperManager
từ màn hình đó.
Quy định hạn chế về bảo mật
Hệ thống sẽ không hiển thị hình nền trên những màn hình ảo mà hệ thống không sở hữu. Lý do là vì vấn đề bảo mật rằng một ứng dụng độc hại có thể tạo màn hình ảo có hỗ trợ trang trí hệ thống và đọc thông tin nhạy cảm của người dùng từ bề mặt (chẳng hạn như ảnh cá nhân).
Triển khai
Trong Android 10, các giao diện IWallpaperConnection#attachEngine()
và IWallpaperService#attach()
chấp nhận tham số displayId
để tạo các kết nối trên mỗi màn hình.
WallpaperManagerService.DisplayConnector
đóng gói một công cụ và kết nối hình nền cho mỗi màn hình. Trong WindowManager, các bộ điều khiển hình nền được tạo cho từng đối tượng DisplayContent
tại cấu trúc thay vì một WallpaperController
duy nhất cho tất cả màn hình.
Một số cách triển khai phương thức WallpaperManager
công khai (chẳng hạn như WallpaperManager#getDesiredMinimumWidth()
) đã được cập nhật để tính toán và cung cấp thông tin cho các màn hình tương ứng.
WallpaperInfo#supportsMultipleDisplays()
và một thuộc tính tài nguyên tương ứng đã được thêm vào, để nhà phát triển ứng dụng có thể báo cáo những hình nền nào đã sẵn sàng cho nhiều màn hình.
Nếu dịch vụ hình nền xuất hiện trên màn hình mặc định không hỗ trợ nhiều màn hình, thì hệ thống sẽ hiển thị hình nền mặc định trên các màn hình phụ:
Hình 3. Logic dự phòng cho hình nền trên màn hình phụ.