Hỗ trợ phần trang trí hệ thống

Dưới đây là nội dung cập nhật cho các khu vực hiển thị cụ thể này:

Trang trí hệ thống

Android 10 hỗ trợ thêm tính năng định cấu hình phụ màn hình để 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 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 màn hình được bật (không bắt buộc). Hỗ trợ cho Trình chỉnh sửa phương thức nhập (IME) có thể được đặt riêng biệt với các thành phần trang trí hệ thống khác.

Sử dụng DisplayWindowSettings#setShouldShowSystemDecorsLocked() để hỗ trợ thêm cho phần trang trí hệ thống trên một màn hình cụ thể hoặc cung cấp một giá trị mặc định trong /data/system/display_settings.xml. Ví dụ: xem phần Cài đặt cửa sổ hiển thị.

Triển khai

DisplayWindowSettings#setShouldShowSystemDecorsLocked() cũng được hiển thị ở WindowManager#setShouldShowSystemDecors() để kiểm thử. Kích hoạt phương thức này nhằm cho phép trang trí hệ thống không thêm cửa sổ trang trí thiếu trước đó hoặc xoá nếu chúng đã xuất hiện trước đó. Trong hầu hết trong trường hợp khác, việc thay đổi hỗ trợ thành phần trang trí hệ thống chỉ có hiệu lực hoàn toàn sau khởi động lại thiết bị.

Kiểm tra khả năng hỗ trợ thành phần 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 sẽ xuất hiện) hãy sử dụng WindowManager#shouldShowSystemDecors(). Để biết những yếu tố do chế độ cài đặt này kiểm soát, 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 bổ sung 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à 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 tương tác Quay lại và Trang chủ. Thông tin 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ì thanh này 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à tính năng bảo vệ bàn 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) chưa được hỗ trợ trên cửa sổ phụ màn hình. Trong Android 10, AOSP chỉ hiển thị mục Recents (Gần đây) trên màn hình mặc định và chứa hoạt động từ mọi màn hình. Khi khởi chạy từ Gần đây, một hoạt động trên màn hình phụ sẽ được đưa lên phía trước trên màn hình đó, theo mặc định. Phương pháp này có một số vấn đề đã biết, chẳng hạn như cập nhật ngay lập tức khi các ứ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 thành phần giao diện người dùng hệ thống duy nhất theo dõi việc bổ sung/loại bỏ màn hình và trình bày 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 tạo nhiều màn hình khi khởi động
  • Đã thêm màn hình trong thời gian chạy
  • Đã xoá màn hình trong thời gian chạy

Khi giao diện người dùng hệ thống phát hiện việc thêm một màn hình trước WindowManager, giao diện người dùng sẽ tạo một tình huống 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 cho 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. Để triển khai tham chiếu, xem CommandQueue.Callbacks#onDisplayReady để biết thông tin hỗ trợ về thanh điều hướng và WallpaperManagerInternal#onDisplayReady để tạo 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 một thanh điều hướng tuỳ chỉnh, hãy xem CarStatusBar.
  • TYPE_NAVIGATION_BAR không còn bị hạn chế ở một miền nào thực thể và có thể dùng trên mỗi màn hình.
  • IWindowManager#hasNavigationBar() được cập nhật để bao gồm Tham số displayId chỉ cho Giao diện người dùng hệ thống.

Súng phóng lựu

Trong Android 10, từng màn hình được định cấu hình để hỗ trợ trang trí hệ thống có ngăn xếp nhà riêng cho các hoạt động của trình chạy cùng với kiểu WindowConfiguration#ACTIVITY_TYPE_HOME, theo mặc định. Mỗi màn hình sử dụng một thực thể riêng biệt của hoạt động của 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 thực thể và không được tối ưu hoá cho kích thước màn hình lớn. Ngoài ra, một loại trải nghiệm khác thường được mong đợi trên màn hình phụ/màn hình ngoài. Để cung cấp một hoạt động riêng cho Android 10 ra mắt danh mục SECONDARY_HOME trong ý định bộ lọc. Các thực thể của hoạt động này được dùng trên tất cả màn hình hỗ trợ hệ thống trang trí, một trang trí 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ó chế độ chạy không ngăn chặn nhiều và cần phải 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() 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 đã chọn và có thể sử dụng chế độ mặc định của hệ thống, nếu cần (xem ActivityTaskManagerService#getSecondaryHomeIntent()).

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 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 sẽ 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 ngoài hệ thống.

Hình nền

Trên 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 trong nội bộ (bên trên) và bên ngoài màn hình (bên dưới)

Nhà phát triển có thể khai báo việc hỗ trợ cho 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 sẽ tải thành phần bằng cách sử dụng ngữ cảnh hiển thị trong WallpaperService.Engine#getDisplayContext().

Khung này sẽ tạo một thực thể WallpaperService.Engine trên mỗi màn hình, vì vậy, mỗi công cụ đều có bối cảnh giao diện và bối cảnh riêng. Chiến lược phát hành đĩa đơn 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, tôn trọng 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. Để thực hiện điều này, giá trị nhận dạng màn hình ổn định là cần thiết để duy trì cài đặt hình nền trên mỗi màn hình. Display#getDisplayId() là biến động, vì vậy không có gì đả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 các giá trị nhận dạng ổn định cho màn hình thực tế và có thể dùng cho trong tương lai. Rất tiếc, vẫn còn quá muộn để triển khai logic cho Android 10. Giải pháp được đề xuất:

  1. Dùng API WallpaperManager để đặt hình nền.
  2. WallpaperManager lấy từ Context và mỗi đối tượng Context đều có thông tin về màn hình (Context#getDisplay()/getDisplayId()). Do đó, bạn có thể lấy displayId qua một thực thể WallpaperManager mà không cần thêm phương thức mới.
  3. Về phía khung, hãy sử dụng displayId lấy từ một Context và ánh xạ đối tượng đó với một giá trị nhận dạng tĩnh (chẳng hạn như một cổng của một màn hình thực). Hãy 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 pháp 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 lệnh 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 màn hình mục tiêu, sau đó tạo một đối tượng Context mới cho màn hình mục tiêu (Context#createDisplayContext) và nhận Thực thể WallpaperManager qua 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 những màn hình ảo mà hệ thống không sở hữu. Nguyên nhân là do lo ngại về bảo mật rằng một ứng dụng độc hại có thể tạo tệp ảo màn hình có hỗ trợ các thành phần trang trí hệ thống và đọc thông báo nhạy cảm với người dùng thông tin khỏi nền tảng (chẳng hạn như ảnh cá nhân).

Triển khai

Trong Android 10, IWallpaperConnection#attachEngine() và giao diện IWallpaperService#attach() chấp nhận displayId để tạo kết nối trên mỗi màn hình. WallpaperManagerService.DisplayConnector đóng gói mỗi màn hình công cụ hình nền và kết nối. Trong WindowManager, bộ điều khiển hình nền được tạo cho từng đối tượng DisplayContent khi tạo thay vì WallpaperController duy nhất cho mọi 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 để điện toán và cung cấp thông tin để hiển thị tương ứng. WallpaperInfo#supportsMultipleDisplays() và một tham số tương ứng được thêm vào, để nhà phát triển ứng dụng có thể báo cáo hình nền đã sẵn sàng cho nhiều màn hình.

Nếu dịch vụ hình nề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 hình nền mặc định trên màn hình phụ màn hình.

Hình 3. Logic dự phòng hình nền cho màn hình phụ