Các phương pháp được đề xuất

Trang này trình bày các đề xuất để làm việc với nhiều màn hình.

Ứng dụng cho thiết bị có thể gập lại và thiết bị có nhiều màn hình

Nhìn chung, các ứng dụng không nên dựa vào giá trị nhận dạng tĩnh hoặc logic phụ thuộc vào một số mã nhận dạng hiển thị. Trong hầu hết các trường hợp, ứng dụng sẽ đổi kích thước và hoạt động trên nhiều màn hình, đồng thời hệ thống sẽ kiểm soát vị trí đặt ứng dụng. Ví dụ: để tạo trải nghiệm mới và độc đáo cho thiết bị có thể gập lại và chạy một ứng dụng đặc biệt trên màn hình ngoài khi thiết bị được gập lại.

Trong trường hợp này, Giao diện người dùng hệ thống hoặc một thành phần hệ thống khác sẽ phát hiện nếp gấp, xác định xem có nên thực hiện một thao tác hay không, sau đó khởi chạy hoạt động đích và chỉ định một mã nhận dạng màn hình ngoài làm đích khởi chạy. Ứng dụng không được phát hiện hành động này hoặc thực hiện bất kỳ hành động nào để phản hồi, sau đó thực hiện thao tác khởi chạy trên một màn hình cụ thể. Vì vậy, đừng cho rằng những gì hoạt động trên một thiết bị sẽ hoạt động trên các thiết bị khác. Nói tóm lại, mã dành riêng cho thiết bị làm tăng sự phân mảnh.

Hạn chế quyền truy cập vào màn hình

Nếu cấu hình thiết bị yêu cầu hạn chế quyền truy cập vào một hoặc nhiều màn hình, bạn nên dùng cờ Display#FLAG_PRIVATE để chỉ định màn hình là riêng tư. Chỉ chủ sở hữu mới có thể thêm nội dung vào màn hình. Nếu người nào đó không phải là chủ sở hữu cố gắng khởi chạy một hoạt động hoặc thêm một cửa sổ, thì thao tác này sẽ kích hoạt SecurityException. Nếu hệ thống sở hữu màn hình, thì hệ thống có thể thêm các cửa sổ và khởi chạy các hoạt động.

Ngoài ra, các thực thể được đặt trên màn hình luôn có thể truy cập vào màn hình đó. Nếu chủ sở hữu chạy một hoạt động trên một màn hình, thì hoạt động đó có thể chạy các hoạt động khác trên màn hình này. Do đó, chủ sở hữu có trách nhiệm hạn chế quyền truy cập và chỉ cho phép các ứng dụng đáng tin cậy.

Ngoài ra, có thêm nhiều hạn chế đối với màn hình ảo vì mọi ứng dụng đều có thể tạo một màn hình ảo mà không cần hiển thị cho người dùng. Nếu hệ thống không sở hữu màn hình ảo, thì chỉ những hoạt động có allowEmbedded mới được phép và phương thức gọi phải có quyền ACTIVITY_EMBEDDING.

Để biết thêm thông tin, hãy xem trang web sau đây:

  • ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay
  • ActivityDisplay#isUidPresent
  • DisplayManagerService#isUidPresentOnDisplay

Để kiểm soát có điều kiện các lần khởi chạy hoạt động, hãy dùng LaunchParamsController. Lớp này sẽ chặn tất cả các lần khởi chạy hoạt động và cho phép một thành phần hệ thống sửa đổi các tham số dùng cho lần khởi chạy. Tính năng này có ở system_server.

Định cấu hình chế độ cài đặt cửa sổ hiển thị và các thành phần trang trí hệ thống

Bạn có thể định cấu hình thành phần trang trí hệ thống cho mỗi màn hình trong DisplayWindowSettings. Một chế độ triển khai thiết bị có thể cung cấp cấu hình mặc định trong /data/system/display_settings.xml.

Giá trị này xác định xem các thành phần trang trí hệ thống (trình chạy, hình nền, thanh điều hướng và các cửa sổ trang trí khác) và IME có xuất hiện trên màn hình hay không. Để biết thông tin chi tiết, hãy xem DisplayWindowSettings#shouldShowSystemDecorsLockedDisplayWindowSettings#shouldShowImeLocked.

Để xác định màn hình, hãy dùng mã nhận dạng duy nhất (mã nhận dạng mặc định này dùng DisplayInfo#uniqueId) hoặc mã nhận dạng cổng vật lý cho màn hình phần cứng (xem DisplayInfo#address).

Ví dụ: ví dụ về cấu hình màn hình sau đây cho phép các thành phần trang trí hệ thống và IME trên màn hình mô phỏng:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<display-settings>
<config identifier="0" />
<display
  name="overlay:1"
  shouldShowSystemDecors="true"
  shouldShowIme="true" />
</display-settings>

Trong ví dụ trên, uniqueId được dùng để nhận dạng màn hình trong thuộc tính tên. Đối với màn hình mô phỏng, thuộc tính này là overlay:1. Đối với màn hình tích hợp, giá trị mẫu có thể là "local:45354385242535243453". Một lựa chọn khác là sử dụng thông tin về cổng phần cứng và đặt identifier="1" tương ứng với DisplayWindowSettings#IDENTIFIER_PORT, sau đó cập nhật tên để sử dụng định dạng "port:<port_id>":

<?xmlversion='1.0' encoding='utf-8' standalone='yes' ?>
<display-settings>
<config identifier="1" />
<display
  name="port:12345"
  shouldShowSystemDecors="true"
  shouldShowIme="true" />
</display-settings>

Để biết thông tin chi tiết, hãy xem phần Giá trị nhận dạng hiển thị tĩnh.

Để biết thêm thông tin, hãy xem trang web sau đây:

Chuyển đổi màn hình giữa các tác vụ phản chiếu và lưu trữ

Trong Android 17 trở lên, DisplayManager dùng cờ FLAG_ALLOWS_CONTENT_MODE_SWITCH để kiểm soát việc màn hình chuyển đổi giữa các tác vụ phản chiếu và lưu trữ trong thời gian chạy. Theo mặc định, cờ này được bật cho màn hình ngoài và tắt cho tất cả các màn hình khác.

Khi FLAG_ALLOWS_CONTENT_MODE_SWITCH xuất hiện, DisplayManager sẽ giám sát chế độ cài đặt bảo mật android.provider.Settings.Secure.MIRROR_BUILT_IN_DISPLAY để xác định xem có nên phản chiếu hay lưu trữ các tác vụ hay không. Mặc dù đây là logic mặc định, nhưng các OEM có thể tuỳ chỉnh hành vi này.

Hiển thị cấu trúc liên kết và chuyển động của con trỏ

Trong Android 17 trở lên, cấu trúc liên kết màn hình xác định vị trí tương đối của màn hình và hạn chế chuyển động của con trỏ chuột đối với một nhóm màn hình cụ thể trong cấu trúc liên kết.

WindowManager quyết định đưa một màn hình vào cấu trúc liên kết và gọi DisplayManagerInternal.onDisplayBelongToTopologyChanged. DisplayManagerkiểm tra DisplayTopologyCoordinator.isDisplayAllowedInTopology trước khi thêm màn hình. Theo mặc định, nếu màn hình tại địa phương có thể lưu trữ các tác vụ, hệ thống sẽ thêm các tác vụ đó.

Nếu có nhiều màn hình công cộng có thể lưu trữ các tác vụ, thì quyết định đưa màn hình mặc định vào sẽ do trình cung cấp boolean shouldIncludeDefaultDisplayInTopology được truyền đến DisplayTopologyCoordinator xử lý. Nếu màn hình mặc định là màn hình công khai duy nhất có thể lưu trữ các tác vụ, thì màn hình này luôn nằm trong cấu trúc liên kết. Trong AOSP, trình cung cấp boolean chỉ trả về true nếu màn hình mặc định hỗ trợ tính năng cửa sổ kiểu máy tính hoặc nếu chế độ cài đặt bảo mật Settings.Secure.INCLUDE_DEFAULT_DISPLAY_IN_TOPOLOGYtrue.

Các ứng dụng truy vấn cấu trúc liên kết hiện tại bằng cách sử dụng DisplayManager.getDisplayTopology và phản ứng với các thay đổi đối với cấu trúc liên kết bằng cách đăng ký một trình nghe với DisplayManager.registerTopologyListener.