Hỗ trợ trang trí hệ thống

Các cập nhật được thực hiện cho các khu vực dành riêng cho màn hình này được cung cấp bên dưới:

Hệ thống trang trí

Android 10 bổ sung hỗ trợ định cấu hình màn hình phụ để hiển thị một số 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 khởi chạy. Theo mặc định, màn hình chính hiển thị tất cả các trang trí hệ thống và màn hình phụ hiển thị những trang trí được bật tùy chọn. Hỗ trợ cho Trình chỉnh sửa phương thức nhập liệu (IME) có thể được đặt riêng biệt với các trang trí hệ thống khác.

Sử dụng DisplayWindowSettings#setShouldShowSystemDecorsLocked() để thêm hỗ trợ cho 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 Cài đặt cửa sổ hiển thị .

Thực hiện

DisplayWindowSettings#setShouldShowSystemDecorsLocked() cũng được hiển thị trong WindowManager#setShouldShowSystemDecors() để thử nghiệm. Việc kích hoạt phương pháp này với mục đích kích hoạt các kiểu dáng hệ thống sẽ không thêm các cửa sổ trang trí bị thiếu trước đó hoặc xóa chúng nếu chúng đã có trước đây. Trong hầu hết các trường hợp, việc thay đổi 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 sự hỗ trợ của trang trí hệ thống trong cơ sở mã WindowManager thường đi qua DisplayContent#supportsSystemDecorations() trong khi kiểm tra các dịch vụ bên ngoài (chẳng hạn như System UI để kiểm tra xem thanh điều hướng có được hiển thị hay không) sử dụng WindowManager#shouldShowSystemDecors() . Để hiểu cài đặt này kiểm soát những gì, hãy khám phá điểm gọi của các phương pháp này.

Cửa sổ trang trí giao diện người dùng hệ thống

Android 10 chỉ bổ sung hỗ trợ cửa sổ trang trí hệ thống cho thanh điều hướng vì thanh điều hướng rất cần thiết để điều hướng giữa các hoạt động và ứng dụng. Theo mặc định, thanh điều hướng hiển thị khả năng chi trả cho Trở về và Nhà. Điều này chỉ được bao gồm 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 Bóng thông báo, Cài đặt nhanh và Màn hình khóa. 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, cài đặt và bàn phím đầy đủ chỉ khả dụng 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ị Gần đây trên màn hình mặc định và chứa các hoạt động từ tất cả các màn hình. Theo mặc định, khi được 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 đó. Cách tiếp cận này có một số vấn đề đã biết, chẳng hạn như không cập nhật ngay lập tức khi ứng dụng xuất hiện trên các màn hình khác.

Thực hiện

Để triển khai các tính năng UI hệ thống bổ sung, nhà sản xuất thiết bị nên sử dụng một thành phần UI hệ thống duy nhất để lắng nghe việc thêm/xóa 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ợ Đa màn hình (MD) sẽ xử lý các trường hợp sau:

  • Khởi tạo nhiều màn hình khi khởi động
  • Hiển thị được thêm vào khi chạy
  • Hiển thị bị xóa khi chạy

Khi Giao diện người dùng hệ thống phát hiện việc bổ sung màn hình trước WindowManager, nó 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 tùy chỉnh từ WindowManager đến Giao diện người dùng hệ thống khi màn hình được thêm vào thay vì đăng ký các sự kiện DisplayManager .DisplayListener . Để biết cách triển khai tham khảo, hãy xem CommandQueue.Callbacks#onDisplayReady để biết hỗ trợ thanh điều hướng và WallpaperManagerInternal#onDisplayReady để biết 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 tất cả chức năng dành riêng cho thanh điều hướng.
  • Để xem thanh điều hướng tùy chỉnh, hãy xem 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ể được sử dụng trên 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 khởi chạy

Trong Android 10, 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ủ dành riêng cho các hoạt động của trình khởi chạy với loại WindowConfiguration#ACTIVITY_TYPE_HOME theo mặc định. Mỗi màn hình sử dụng một phiên bản hoạt động của trình khởi chạy riêng biệt.

Hình 1. Ví dụ về trình khởi chạy đa màn hình cho platform/development/samples/MultiDisplay

Hầu hết các trình khởi chạy hiện tại không hỗ trợ nhiều phiên bản và không được tối ưu hóa cho kích thước màn hình lớn. Ngoài ra, người ta thường mong đợi một loại trải nghiệm khác trên màn hình phụ/bên ngoài. Để cung cấp hoạt động dành 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 phiên bản của hoạt động này được sử dụng trên tất cả các màn hình hỗ trợ trang trí hệ thống, mỗi màn hình một 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ế độ khởi chạy không ngăn chặn nhiều phiên bản và phải thích ứng với các kích thước màn hình khác nhau. Chế độ khởi chạy không được là singleInstance hoặc singleTask .

Thực hiện

Trong Android 10, RootActivityContainer#startHomeOnDisplay() tự động chọn thành phần và mục đích mong muốn tùy 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 khởi chạy tùy thuộc vào trình khởi chạy hiện được chọn và có thể sử dụng mặc định của hệ thống, nếu cần (xem ActivityTaskManagerService#getSecondaryHomeIntent() ).

Hạn chế 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 với trang trí Hệ thống được bật và đọc thông tin nhạy cảm của người dùng từ bề mặt, trình khởi chạy chỉ xuất hiện trên màn hình ảo do hệ thống sở hữu. Trình khởi chạy không hiển thị nội dung trên màn hình ảo phi 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 bên trong (trên) và màn hình ngoài (bên dưới)

Nhà phát triển có thể tuyên bố 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 . Các nhà phát triển hình nền cũng phải tải nội dung bằng cách sử dụng ngữ cảnh hiển thị trong WallpaperService.Engine#getDisplayContext() .

Khung này tạo một phiên bản WallpaperService.Engine trên mỗi màn hình, do đó, mỗi công cụ có bối cảnh hiển thị và bề mặt 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, tôn trọng VSYNC.

Chọn hình nền cho từng màn hình

Android 10 không cung cấp 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, cần có mã nhận dạng màn hình ổn định để duy trì cài đặt hình nền trên mỗi màn hình. Display#getDisplayId() là động nên không có gì đảm bảo rằng màn hình vật lý sẽ có cùng ID sau khi khởi động lại.

Tuy nhiên, Android 10 đã thêm DisplayInfo.mAddress , chứa các mã nhận dạng ổn định cho màn hình vật lý và có thể được sử dụng để triển khai đầy đủ trong tương lai. Thật không may, đã quá muộn để triển khai logic cho Android 10. Giải pháp được đề xuất:

  1. Sử dụng API WallpaperManager để đặt hình nền.
  2. WallpaperManager được lấy từ một đối tượng Context và mỗi đối tượng Context có thông tin về màn hình tương ứng ( Context#getDisplay()/getDisplayId() ). Do đó, bạn có thể lấy displayId từ phiên bản WallpaperManager mà không cần thêm phương thức mới.
  3. Về phía khung, sử dụng displayId thu được từ một đối tượng Context và ánh xạ nó tới một mã định danh tĩnh (chẳng hạn như cổng của màn hình vật lý). Sử dụng mã định danh tĩnh để duy trì hình nền đã chọn.

Cách giải quyết này sử dụng các triển khai hiện có cho bộ chọn hình nền. Nếu nó được mở trên một màn hình cụ thể và sử dụng đúng ngữ cảnh thì khi nó gọi để đặt hình nền, hệ thống có thể tự động nhận dạng 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, thì hãy tạo một đối tượng Context mới cho màn hình đích ( Context#createDisplayContext ) và lấy phiên bản WallpaperManager từ màn hình đó.

Hạn chế 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à nó không sở hữu. Điều này là do lo ngại về bảo mật rằng một ứng dụng độc hại có thể tạo một màn hình ảo có hỗ trợ trang trí hệ thống được bật và đọc thông tin nhạy cảm với người dùng từ bề mặt (chẳng hạn như ảnh cá nhân).

Thực hiện

Trong Android 10, giao diện IWallpaperConnection#attachEngine()IWallpaperService#attach() chấp nhận tham số displayId để tạo kết nối trên mỗi màn hình. WallpaperManagerService.DisplayConnector đóng gói công cụ và kết nối hình nền trên mỗi màn hình. Trong WindowManager, bộ điều khiển hình nền được tạo cho từng đối tượng DisplayContent khi xây dựng thay vì một WallpaperController duy nhất cho tất cả các màn hình.

Một số 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à 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 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ụ