Dưới đây là nội dung cập nhật đối với các khu vực dành riêng cho màn hình này:
Trang trí hệ thống
Android 10 hỗ trợ thêm tính năng định cấu hình màn hình phụ để hiển thị một số phần trang trí hệ thống nhất định, 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 hiển thị tất cả các phần trang trí hệ thống và màn hình phụ hiển thị các phần trang trí được bật tuỳ ý. Bạn có thể thiết lập tính năng hỗ trợ 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í hệ thống khác.
Sử dụng DisplayWindowSettings#setShouldShowSystemDecorsLocked()
để thêm tính năng hỗ trợ cho các 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 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 ý định bật các 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á các cửa sổ trang trí đó nếu trước đó có. Trong hầu hết trường hợp, thay đổi về tính năng hỗ trợ trang trí hệ thống chỉ có hiệu lực đầy đủ sau khi khởi động lại thiết bị.
Việc kiểm tra tính năng hỗ trợ trang trí hệ thống trong cơ sở mã WindowManager thường trải qua DisplayContent#supportsSystemDecorations()
trong khi kiểm tra các 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ó xuất hiện hay không) sử dụng WindowManager#shouldShowSystemDecors()
.
Để hiểu chế độ cài đặt này kiểm soát điều gì, hãy khám phá các điểm gọi của các phương thức này.
Cửa sổ trang trí giao diện người dùng hệ thống
Android 10 thêm tính năng hỗ trợ cửa sổ trang trí hệ thống chỉ cho thanh điều hướng, vì thanh điều hướng là yếu tố 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 hiển thị các chức năng Quay lại và Trang chủ. Thuộc tính này chỉ được đưa vào nếu màn hình mục tiêu hỗ trợ 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ì nó cũng chứa Ngăn thông báo, 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à khoá phím đầy đủ chỉ có trên màn hình chính.
Cửa sổ hệ thống Overview/Recents (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 trên tất cả màn hình. Theo mặc định, khi được chạy từ phần Gần đây, 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 ứng dụng xuất hiện trên các 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 Giao diện người dùng hệ thống duy nhất để theo dõi việc thêm/xoá màn hình và hiển thị nội dung phù hợp.
Thành phần giao diện người dùng hệ thống hỗ trợ Nhiều màn hình (MD) phải xử lý các trường hợp sau:
- Khởi chạy nhiều màn hình khi khởi động
- Màn hình được thêm vào thời gian chạy
- Đã xoá màn hình trong thời gian chạy
Khi phát hiện thấy việc thêm màn hình trước WindowManager, Giao diện người dùng hệ thống sẽ tạo ra một điều kiện tương tranh. Bạn có thể tránh điều này bằng cách triển khai lệnh gọi lại tuỳ chỉnh từ WindowManager đến Giao diện người dùng hệ thống khi thêm màn hình thay vì đăng ký các sự kiện DisplayManager.DisplayListener
. Để tham khảo cách triển khai, hãy xem CommandQueue.Callbacks#onDisplayReady
để hỗ trợ thanh điều hướng và WallpaperManagerInternal#onDisplayReady
để hỗ trợ hình nền.
Ngoài ra, Android 10 còn cung cấp các bản 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
CarStatusBar
. TYPE_NAVIGATION_BAR
không còn bị giới hạn ở một thực thể duy nhất và có thể được sử 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.
Súng phóng lựu
Trong Android 10, theo mặc định, mỗi màn hình được định cấu hình để hỗ trợ trang trí hệ thống đều có một ngăn xếp trang chủ chuyên dụ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 thực thể 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ó 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 bên ngoài. Để cung cấp hoạt động riêng 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 sử 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 không ngăn chặn 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, đồng thời có thể sử dụng chế độ 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 hạn chế áp dụng cho các hoạt động trên màn hình phụ, để tránh khả năng ứng dụng độc hại tạo màn hình ảo khi bật Trang trí hệ thống và đọc thông tin nhạy cảm của người dùng trên nền tảng, 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 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 nội bộ (bên trên) và màn hình ngoài (bên 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ó bề mặt và ngữ cảnh hiển thị riêng. Nhà phát triển cần đảm bảo rằng mỗi công cụ có thể vẽ một cách độ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ợ nền tảng trực tiếp để chọn hình nền cho từng màn hình. Để làm được điều này, bạn cần có một giá trị nhận dạng màn hình ổn định để lưu giữ chế độ cài đặt hình nền cho mỗi màn hình.
Display#getDisplayId()
có thuộc tính động nên không thể đảm bảo rằng màn hình thực sẽ có cùng mã nhận dạng sau khi khởi động lại.
Tuy nhiên, Android 10 đã thêm DisplayInfo.mAddress
, chứa 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:
- Dùng API
WallpaperManager
để đặt hình nền. WallpaperManager
được lấy 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 sử dụng
displayId
thu được từ đối tượngContext
và á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 ứng dụng này đượ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 mục tiêu (Context#createDisplayContext
) và lấy thực thể WallpaperManager
từ màn hình đó.
Hạn chế về bảo mật
Hệ thống sẽ không hiển thị hình nền trên màn hình ảo mà hệ thống không sở hữu. Điều này là do mối lo ngại về 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ừ giao diện (chẳng hạn như ảnh cá nhân).
Triển khai
Trong Android 10, 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 công cụ hình nền cho mỗi màn hình và kết nối. Trong WindowManager, trình điều khiển hình nền được tạo cho từng đối tượng DisplayContent
tại thời điểm tạo thay vì một WallpaperController
duy nhất cho tất cả màn hình.
Một số phương thức triển khai 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 màn hình tương ứng.
Chúng tôi đã thêm WallpaperInfo#supportsMultipleDisplays()
và một thuộc tính tài nguyên tương ứng để 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 hiển thị 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 màn hình phụ.
Hình 3. Logic dự phòng hình nền cho màn hình phụ