Xây dựng ứng dụng nhận biết nhiều người dùng

Khi một thiết bị hỗ trợ nhiều người dùng , các ứng dụng của thiết bị đó phải nhận biết được những người dùng riêng biệt này.

Một số ứng dụng nhất định cần có một số thành phần chạy dưới dạng đơn lẻ và có thể chấp nhận yêu cầu từ bất kỳ người dùng nào. Hiện chỉ có các ứng dụng hệ thống mới có thể sử dụng tính năng này.

Cơ sở này:

  • Bảo tồn tài nguyên
  • Phân xử một hoặc nhiều tài nguyên được chia sẻ giữa những người dùng
  • Giảm chi phí mạng bằng cách sử dụng một kết nối máy chủ duy nhất

Xem sơ đồ bên dưới để biết mô tả về luồng quyền với nhiều người dùng.

Luồng quyền của nhiều người dùng

Hình 1. Quyền của nhiều người dùng

Kích hoạt một thành phần đơn lẻ

Để xác định một ứng dụng là một ứng dụng đơn lẻ, hãy thêm android:singleUser="true" vào dịch vụ, người nhận hoặc nhà cung cấp của bạn trong tệp kê khai Android.

Hệ thống sẽ khởi tạo thành phần đó trong quá trình chỉ chạy với tư cách là người dùng 0. Mọi yêu cầu kết nối với nhà cung cấp hoặc dịch vụ đó hoặc phát sóng tới bộ thu đó từ bất kỳ người dùng nào sẽ được chuyển đến quy trình trong người dùng 0. Nếu đây là thành phần duy nhất trong ứng dụng của bạn thì chỉ một phiên bản ứng dụng của bạn sẽ chạy.

Các hoạt động trong gói của bạn sẽ vẫn được khởi chạy trong một quy trình riêng cho từng người dùng, với UID nằm trong phạm vi UID cho người dùng đó (chẳng hạn như 1010034).

Tương tác với người dùng

Đặt quyền

Những quyền này là bắt buộc

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

Sử dụng API

Sử dụng các API sau để giúp ứng dụng nhận biết được nhiều người dùng.

  1. Trích xuất tay cầm người dùng từ các cuộc gọi Binder đến:
    • int userHandle = UserHandle.getCallingUserId()
  2. Sử dụng các API mới, được bảo vệ để bắt đầu các dịch vụ, hoạt động, chương trình phát sóng trên một người dùng cụ thể:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    UserHandle có thể là người dùng rõ ràng hoặc một trong các tay cầm đặc biệt: UserHandle.CURRENT hoặc UserHandle.ALL . CURRENT cho biết người dùng hiện đang ở nền trước. Sử dụng ALL khi bạn muốn gửi một thông báo tới tất cả người dùng.
  3. Giao tiếp với các thành phần trong ứng dụng của riêng bạn: (INTERACT_ACROSS_USERS) Hoặc với các thành phần trong ứng dụng khác: (INTERACT_ACROSS_USERS_FULL)
  4. Bạn có thể cần tạo các thành phần proxy chạy trong quy trình của người dùng, sau đó truy cập thành phần singleUser trong người dùng 0.
  5. Truy vấn người dùng và tay cầm của họ bằng dịch vụ hệ thống UserManager mới:
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle) - một số không được tái chế tương ứng với tên người dùng.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() - trả về tập hợp các hồ sơ tự và được quản lý, nếu có.
  6. Đăng ký để lắng nghe ý kiến ​​cụ thể hoặc tất cả người dùng và lệnh gọi lại bằng các API mới trên ContentObserver, PackageMonitor, BroadcastReceiver để cung cấp thêm thông tin về người dùng nào đã gây ra lệnh gọi lại.

Dịch vụ trong nhiều người dùng hoặc hồ sơ

Không phải tất cả các dịch vụ đều cần chạy phiên bản trong hồ sơ công việc hoặc người dùng khác. Nếu dịch vụ hệ thống của bạn chỉ cần chạy với tư cách người dùng 0, hãy tắt các thành phần của dịch vụ khi chạy dưới quyền của những người dùng khác để giúp bảo toàn tài nguyên. Ví dụ sau đây cho thấy cách bạn có thể thực hiện việc này tại các điểm đầu vào của dịch vụ:

// Add on all entry points such as boot_completed or other manifest-listed receivers and providers
if (!UserManager.isSystemUser()) {
    // Disable the service
    ComponentName targetServiceName = new ComponentName(this, TargetService.class);
    context.getPackageManager().setComponentEnabledSetting(
        targetServiceName, COMPONENT_ENABLED_STATE_DISABLED, 0);
}

Ví dụ này cũng có thể sử dụng PackageManager.setApplicationEnabledSetting() để tắt toàn bộ ứng dụng.