Quản lý nhiều người dùng

Hướng dẫn dành cho nhà phát triển này giải thích cách trình kiểm soát chính sách thiết bị (DPC) của bạn có thể quản lý nhiều người dùng Android trên các thiết bị chuyên dụng.

Tổng quan

DPC của bạn có thể giúp nhiều người dùng chung một thiết bị chuyên dụng. DPC của bạn khi chạy trên thiết bị được quản lý hoàn toàn có thể tạo và quản lý hai kiểu người dùng:

  • Người dùng phụ là những người dùng Android đã lưu dữ liệu và ứng dụng riêng biệt giữa các phiên. Bạn quản lý người dùng bằng thành phần quản trị viên. Những người dùng này hữu ích cho trường hợp người dùng nhấc thiết bị lên khi bắt đầu ca làm việc, chẳng hạn như tài xế giao hàng hoặc nhân viên an ninh.
  • Người dùng tạm thời là những người dùng phụ mà hệ thống sẽ xoá khi người dùng đó dừng, chuyển đi hoặc thiết bị khởi động lại. Những người dùng này hữu ích cho các trường hợp trong đó dữ liệu có thể bị xoá sau khi phiên kết thúc, chẳng hạn như quyền truy cập công khai ki-ốt internet.

Bạn sử dụng DPC hiện có để quản lý thiết bị chuyên dụng và người dùng. Một thành phần quản trị trong DPC của bạn sẽ tự đặt làm quản trị viên cho phụ mới khi tạo chúng.

Người dùng chính và 2 người dùng phụ.
Hình 1. Người dùng chính và phụ do quản trị viên quản lý từ cùng một DPC

Quản trị viên của người dùng phụ phải thuộc cùng gói với quản trị viên của thiết bị được quản lý toàn bộ. Để đơn giản hoá quá trình phát triển, bạn nên chia sẻ thông tin về quản trị viên giữa thiết bị và người dùng phụ.

Việc quản lý nhiều người dùng trên các thiết bị chuyên dụng thường yêu cầu Android 9.0, tuy nhiên, một số phương pháp được sử dụng trong hướng dẫn của nhà phát triển này có sẵn trong các phiên bản Android cũ hơn.

Người dùng phụ

Người dùng phụ có thể kết nối với Wi-Fi và có thể định cấu hình mạng mới. Tuy nhiên, chúng không thể chỉnh sửa hoặc xóa mạng, ngay cả những mạng mà các mạng đó đã tạo.

Tạo người dùng

DPC của bạn có thể tạo thêm người dùng trong nền và sau đó có thể chuyển đổi họ lên nền trước. Quá trình này gần giống nhau đối với cả phụ và người dùng tạm thời. Thực hiện các bước sau đây trong phần quản trị của thiết bị được quản lý và người dùng phụ:

  1. Gọi DevicePolicyManager.createAndManageUser(). Để tạo người dùng tạm thời, hãy thêm MAKE_USER_EPHEMERAL trong đối số cờ.
  2. Gọi điện DevicePolicyManager.startUserInBackground() đến khởi động người dùng trong nền. Người dùng bắt đầu chạy nhưng bạn muốn để hoàn tất quá trình thiết lập trước khi đưa người dùng lên nền trước và hiển thị cho người đang sử dụng thiết bị.
  3. Trong quản trị viên của người dùng phụ, hãy gọi DevicePolicyManager.setAffiliationIds() đến liên kết người dùng mới với người dùng chính. Xem Phối hợp DPC bên dưới.
  4. Quay lại phần quản trị của thiết bị được quản lý toàn bộ, gọi DevicePolicyManager.switchUser() để chuyển người dùng sang nền trước.

Mẫu sau đây trình bày cách thêm bước 1 vào DPC:

Kotlin

val dpm = getContext().getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager

// If possible, reuse an existing affiliation ID across the
// primary user and (later) the ephemeral user.
val identifiers = dpm.getAffiliationIds(adminName)
if (identifiers.isEmpty()) {
    identifiers.add(UUID.randomUUID().toString())
    dpm.setAffiliationIds(adminName, identifiers)
}

// Pass an affiliation ID to the ephemeral user in the admin extras.
val adminExtras = PersistableBundle()
adminExtras.putString(AFFILIATION_ID_KEY, identifiers.first())
// Include any other config for the new user here ...

// Create the ephemeral user, using this component as the admin.
try {
    val ephemeralUser = dpm.createAndManageUser(
            adminName,
            "tmp_user",
            adminName,
            adminExtras,
            DevicePolicyManager.MAKE_USER_EPHEMERAL or
                    DevicePolicyManager.SKIP_SETUP_WIZARD)

} catch (e: UserManager.UserOperationException) {
    if (e.userOperationResult ==
            UserManager.USER_OPERATION_ERROR_MAX_USERS) {
        // Find a way to free up users...
    }
}

Java

DevicePolicyManager dpm = (DevicePolicyManager)
    getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);

// If possible, reuse an existing affiliation ID across the
// primary user and (later) the ephemeral user.
Set<String> identifiers = dpm.getAffiliationIds(adminName);
if (identifiers.isEmpty()) {
  identifiers.add(UUID.randomUUID().toString());
  dpm.setAffiliationIds(adminName, identifiers);
}

// Pass an affiliation ID to the ephemeral user in the admin extras.
PersistableBundle adminExtras = new PersistableBundle();
adminExtras.putString(AFFILIATION_ID_KEY, identifiers.iterator().next());
// Include any other config for the new user here ...

// Create the ephemeral user, using this component as the admin.
try {
  UserHandle ephemeralUser = dpm.createAndManageUser(
      adminName,
      "tmp_user",
      adminName,
      adminExtras,
      DevicePolicyManager.MAKE_USER_EPHEMERAL |
          DevicePolicyManager.SKIP_SETUP_WIZARD);

} catch (UserManager.UserOperationException e) {
  if (e.getUserOperationResult() ==
      UserManager.USER_OPERATION_ERROR_MAX_USERS) {
    // Find a way to free up users...
  }
}

Khi tạo hoặc bắt đầu một người dùng mới, bạn có thể kiểm tra lý do dẫn đến lỗi bằng cách phát hiện ngoại lệ UserOperationException và gọi getUserOperationResult(). Vượt quá người dùng hạn mức là các lý do phổ biến gây ra lỗi:

Quá trình tạo người dùng có thể mất chút thời gian. Nếu thường xuyên tạo người dùng, bạn có thể cải thiện trải nghiệm người dùng bằng cách chuẩn bị một người dùng sẵn sàng sử dụng trong nền. Bạn có thể cần cân bằng lợi thế của người dùng đã sẵn sàng với việc số người dùng được phép trên thiết bị.

Phát triển mối đồng cảm

Sau khi tạo người dùng mới, bạn nên tham chiếu đến người dùng này bằng một sê-ri cố định số. Đừng duy trì UserHandle vì hệ thống sẽ tái chế những thành phần này khi bạn tạo và xoá người dùng. Lấy số sê-ri bằng cách gọi điện UserManager.getSerialNumberForUser():

Kotlin

// After calling createAndManageUser() use a device-unique serial number
// (that isn’t recycled) to identify the new user.
secondaryUser?.let {
    val userManager = getContext().getSystemService(UserManager::class.java)
    val ephemeralUserId = userManager!!.getSerialNumberForUser(it)
    // Save the serial number to storage  ...
}

Java

// After calling createAndManageUser() use a device-unique serial number
// (that isn’t recycled) to identify the new user.
if (secondaryUser != null) {
  UserManager userManager = getContext().getSystemService(UserManager.class);
  long ephemeralUserId = userManager.getSerialNumberForUser(secondaryUser);
  // Save the serial number to storage  ...
}

Cấu hình của người dùng

Tuỳ thuộc vào nhu cầu của người dùng, bạn có thể tuỳ chỉnh chế độ thiết lập người dùng. Bạn có thể thêm các cờ sau đây khi gọi createAndManageUser():

SKIP_SETUP_WIZARD
Bỏ qua việc chạy trình hướng dẫn thiết lập người dùng mới để kiểm tra và cài đặt bản cập nhật, nhắc người dùng thêm Tài khoản Google cùng với các dịch vụ của Google và thiết lập một phương thức khoá màn hình. Việc này có thể mất chút thời gian và có thể không áp dụng cho tất cả người dùng—ví dụ: kiosk Internet công cộng.
LEAVE_ALL_SYSTEM_APPS_ENABLED
Luôn bật tất cả ứng dụng hệ thống trong người dùng mới. Nếu không đặt cờ này, người dùng mới chỉ chứa tập hợp ứng dụng tối thiểu mà điện thoại cần hoạt động—thường là một trình duyệt tệp, trình quay số điện thoại, danh bạ và tin nhắn SMS.

Theo dõi vòng đời của người dùng

DPC của bạn (nếu là quản trị viên của thiết bị được quản lý hoàn toàn) có thể thấy hữu ích khi biết khi nào người dùng thứ hai thay đổi. Để chạy các tác vụ tiếp theo sau khi thay đổi, hãy ghi đè các phương thức gọi lại này trong lớp con DeviceAdminReceiver của DPC:

onUserStarted()
Được gọi sau khi hệ thống khởi động một người dùng. Người dùng này có thể vẫn đang thiết lập hoặc đang chạy trong nền. Bạn có thể tải người dùng này qua startedUser đối số.
onUserSwitched()
Được gọi sau khi hệ thống chuyển sang một người dùng khác. Bạn có thể thu hút người dùng mới hiện đang chạy ở nền trước từ đối số switchedUser.
onUserStopped()
Được gọi sau khi hệ thống dừng một người dùng vì họ đã đăng xuất, chuyển sang người dùng mới (nếu người dùng tạm thời) hoặc DPC của bạn đã dừng người dùng. Bạn có thể tải người dùng qua đối số stoppedUser.
onUserAdded()
Được gọi khi hệ thống thêm một người dùng mới. Thông thường, người dùng phụ thiết lập đầy đủ khi DPC của bạn nhận lệnh gọi lại. Bạn có thể lấy người dùng từ Đối số newUser.
onUserRemoved()
Được gọi sau khi hệ thống xoá một người dùng. Vì người dùng đó đã bị xoá, bạn không thể truy cập vào người dùng mà đối số removedUser đại diện.

Để biết khi nào hệ thống đưa người dùng lên nền trước hoặc gửi người dùng đến ở chế độ nền, ứng dụng có thể đăng ký dịch vụ nhận cho ACTION_USER_FOREGROUNDACTION_USER_BACKGROUND thông báo.

Khám phá người dùng

Để có tất cả người dùng phụ, quản trị viên của thiết bị được quản lý toàn diện có thể gọi DevicePolicyManager.getSecondaryUsers(). Kết quả bao gồm mọi người dùng phụ hoặc người dùng tạm thời do quản trị viên tạo. Kết quả cũng bao gồm bất kỳ người dùng phụ nào (hoặc người dùng khách) mà một người sử dụng thiết bị có thể đã tạo. Kết quả không bao gồm hồ sơ công việc vì chúng không phải là người dùng phụ. Mẫu sau đây cho thấy cách bạn có thể sử dụng phương thức này:

Kotlin

// The device is stored for the night. Stop all running secondary users.
dpm.getSecondaryUsers(adminName).forEach {
    dpm.stopUser(adminName, it)
}

Java

// The device is stored for the night. Stop all running secondary users.
for (UserHandle user : dpm.getSecondaryUsers(adminName)) {
  dpm.stopUser(adminName, user);
}

Dưới đây là các phương thức khác mà bạn có thể gọi để tìm hiểu trạng thái của người dùng phụ:

DevicePolicyManager.isEphemeralUser()
Gọi phương thức này từ quản trị viên của một người dùng phụ để tìm hiểu xem đây có phải là người dùng tạm thời.
DevicePolicyManager.isAffiliatedUser()
Gọi phương thức này từ quản trị viên của một người dùng phụ để tìm hiểu xem người dùng này có được liên kết với người dùng chính. Để tìm hiểu thêm về đơn vị liên kết, hãy xem DPC bên dưới.

Quản lý người dùng

Nếu muốn quản lý hoàn toàn vòng đời của người dùng, bạn có thể gọi API cho kiểm soát chi tiết thời điểm và cách thiết bị thay đổi người dùng. Ví dụ: bạn có thể xóa người dùng khi thiết bị không được sử dụng trong một khoảng thời gian hoặc bạn có thể gửi mọi đơn đặt hàng chưa được gửi tới máy chủ trước khi ca của một người kết thúc.

Đăng xuất

Android 9.0 thêm một nút đăng xuất vào màn hình khoá để người dùng thiết bị nào có thể kết thúc phiên của họ. Sau khi người dùng nhấn vào nút này, hệ thống sẽ dừng người dùng phụ, xoá người dùng nếu người dùng tạm thời và người dùng chính quay lại lên nền trước. Android ẩn nút này khi người dùng chính đang ở ở chế độ nền trước vì người dùng chính không thể đăng xuất.

Theo mặc định, Android không hiển thị nút kết thúc phiên nhưng hiển thị quản trị viên (của thiết bị được quản lý hoàn toàn) có thể bật tính năng này bằng cách gọi DevicePolicyManager.setLogoutEnabled(). Nếu bạn cần xác nhận trạng thái hiện tại của nút, gọi DevicePolicyManager.isLogoutEnabled().

Quản trị viên của người dùng phụ có thể đăng xuất người dùng rồi quay lại theo phương thức lập trình đối với người dùng chính. Trước tiên, hãy xác nhận người dùng phụ và người dùng chính là được liên kết, sau đó gọi DevicePolicyManager.logoutUser(). Nếu người dùng đã đăng xuất là người dùng tạm thời, hệ thống sẽ dừng rồi xoá người dùng.

Chuyển đổi người dùng

Để chuyển sang người dùng phụ khác, quản trị viên của một thiết bị được quản lý toàn diện có thể gọi DevicePolicyManager.switchUser(). Để thuận tiện, bạn có thể truyền null để chuyển sang người dùng chính.

Dừng một người dùng

Để dừng người dùng phụ, DPC sở hữu thiết bị được quản lý hoàn toàn có thể gọi DevicePolicyManager.stopUser(). Nếu người dùng bị dừng là người dùng tạm thời, người dùng sẽ dừng lại, sau đó bị xoá.

Bất cứ khi nào có thể, bạn nên dừng người dùng để giúp thiết bị không vượt quá số người dùng đang chạy tối đa.

Xóa người dùng

Để xoá vĩnh viễn người dùng phụ, DPC có thể gọi một trong các lệnh sau DevicePolicyManager phương thức:

  • Quản trị viên của một thiết bị được quản lý toàn diện có thể gọi hàm removeUser().
  • Quản trị viên của người dùng phụ có thể gọi wipeData().

Hệ thống sẽ xoá người dùng tạm thời khi họ đăng xuất, dừng hoặc chuyển đổi xa.

Vô hiệu hoá giao diện người dùng mặc định

Nếu DPC của bạn cung cấp giao diện người dùng để quản lý người dùng, bạn có thể tắt các tính năng giao diện nhiều người dùng. Bạn có thể thực hiện việc này bằng cách gọi DevicePolicyManager.setLogoutEnabled() rồi thêm tham số DISALLOW_USER_SWITCH như minh hoạ trong ví dụ sau:

Kotlin

// Explicitly disallow logging out using Android UI (disabled by default).
dpm.setLogoutEnabled(adminName, false)

// Disallow switching users in Android's UI. This DPC can still
// call switchUser() to manage users.
dpm.addUserRestriction(adminName, UserManager.DISALLOW_USER_SWITCH)

Java

// Explicitly disallow logging out using Android UI (disabled by default).
dpm.setLogoutEnabled(adminName, false);

// Disallow switching users in Android's UI. This DPC can still
// call switchUser() to manage users.
dpm.addUserRestriction(adminName, UserManager.DISALLOW_USER_SWITCH);

Người sử dụng thiết bị không thể thêm người dùng phụ bằng giao diện người dùng tích hợp sẵn của Android vì quản trị viên của các thiết bị được quản lý toàn bộ sẽ tự động thêm Giới hạn người dùng DISALLOW_ADD_USER.

Thông báo trong phiên

Khi một người đang sử dụng một thiết bị chuyển sang một người dùng mới, Android sẽ hiển thị một bảng điều khiển để đánh dấu nút chuyển. Android hiện các thông báo sau:

  • Thông báo bắt đầu phiên hoạt động của người dùng xuất hiện khi thiết bị chuyển sang người dùng khỏi người dùng chính.
  • Thông báo trong phiên hoạt động của người dùng cuối xuất hiện khi thiết bị quay lại người dùng chính từ một người dùng phụ.

Hệ thống sẽ không hiện thông báo khi chuyển đổi giữa hai người dùng phụ.

Do các thông báo có thể không phù hợp với mọi tình huống nên bạn có thể thay đổi nội dung của các thư này. Ví dụ: nếu giải pháp của bạn sử dụng người dùng tạm thời bạn có thể phản ánh điều này trong các thông báo như: Dừng trình duyệt buổi tập & đang xoá dữ liệu cá nhân...

Hệ thống hiển thị thông báo chỉ trong vài giây, nên mỗi thông báo phải là một cụm từ ngắn gọn, rõ ràng. Để tuỳ chỉnh tin nhắn, quản trị viên có thể gọi phương thức DevicePolicyManager setStartUserSessionMessage()setEndUserSessionMessage() như minh hoạ trong ví dụ sau:

Kotlin

// Short, easy-to-read messages shown at the start and end of a session.
// In your app, store these strings in a localizable resource.
internal val START_USER_SESSION_MESSAGE = "Starting guest session…"
internal val END_USER_SESSION_MESSAGE = "Stopping & clearing data…"

// ...
dpm.setStartUserSessionMessage(adminName, START_USER_SESSION_MESSAGE)
dpm.setEndUserSessionMessage(adminName, END_USER_SESSION_MESSAGE)

Java

// Short, easy-to-read messages shown at the start and end of a session.
// In your app, store these strings in a localizable resource.
private static final String START_USER_SESSION_MESSAGE = "Starting guest session…";
private static final String END_USER_SESSION_MESSAGE = "Stopping & clearing data…";

// ...
dpm.setStartUserSessionMessage(adminName, START_USER_SESSION_MESSAGE);
dpm.setEndUserSessionMessage(adminName, END_USER_SESSION_MESSAGE);

Truyền null để xoá thông điệp tuỳ chỉnh của bạn và quay lại chế độ mặc định của Android tin nhắn. Nếu bạn cần kiểm tra nội dung tin nhắn hiện tại, hãy gọi getStartUserSessionMessage() hoặc getEndUserSessionMessage().

DPC của bạn phải đặt thông báo đã bản địa hoá cho ngôn ngữ hiện tại của người dùng. Bạn cũng cần cập nhật thông báo khi thay đổi ngôn ngữ của người dùng:

Kotlin

override fun onReceive(context: Context?, intent: Intent?) {
    // Added the <action android:name="android.intent.action.LOCALE_CHANGED" />
    // intent filter for our DeviceAdminReceiver subclass in the app manifest file.
    if (intent?.action === ACTION_LOCALE_CHANGED) {

        // Android's resources return a string suitable for the new locale.
        getManager(context).setStartUserSessionMessage(
                getWho(context),
                context?.getString(R.string.start_user_session_message))

        getManager(context).setEndUserSessionMessage(
                getWho(context),
                context?.getString(R.string.end_user_session_message))
    }
    super.onReceive(context, intent)
}

Java

public void onReceive(Context context, Intent intent) {
  // Added the <action android:name="android.intent.action.LOCALE_CHANGED" />
  // intent filter for our DeviceAdminReceiver subclass in the app manifest file.
  if (intent.getAction().equals(ACTION_LOCALE_CHANGED)) {

    // Android's resources return a string suitable for the new locale.
    getManager(context).setStartUserSessionMessage(
        getWho(context),
        context.getString(R.string.start_user_session_message));

    getManager(context).setEndUserSessionMessage(
        getWho(context),
        context.getString(R.string.end_user_session_message));
  }
  super.onReceive(context, intent);
}

Điều phối DPC

Việc quản lý người dùng phụ thường cần đến hai phiên bản DPC, trong đó một phiên bản sở hữu thiết bị được quản lý toàn bộ trong khi thiết bị còn lại sở hữu người dùng phụ. Khi tạo một người dùng mới, quản trị viên của thiết bị được quản lý toàn bộ sẽ đặt một phiên bản khác của bản thân nó dưới vai trò quản trị viên của người dùng mới.

Người dùng liên kết

Một số API trong hướng dẫn của nhà phát triển này chỉ hoạt động khi người dùng phụ được liên kết. Vì Android tắt một số tính năng (ví dụ: ghi nhật ký mạng) khi bạn thêm người dùng phụ mới chưa liên kết vào thiết bị đó, bạn nên liên kết người dùng càng sớm càng tốt. Xem ví dụ trong Thiết lập ở bên dưới.

Thiết lập

Thiết lập người dùng phụ mới (từ DPC sở hữu người dùng phụ) trước đó cho phép mọi người sử dụng chúng. Bạn có thể thực hiện thiết lập này từ Lệnh gọi lại DeviceAdminReceiver.onEnabled(). Nếu trước đây đặt bất kỳ phần bổ sung quản trị nào trong lệnh gọi tới createAndManageUser(), bạn có thể lấy hàm các giá trị từ đối số intent. Ví dụ sau đây thể hiện một đơn vị liên kết DPC một người dùng phụ mới trong lệnh gọi lại:

Kotlin

override fun onEnabled(context: Context?, intent: Intent?) {
    super.onEnabled(context, intent)

    // Get the affiliation ID (our DPC previously put in the extras) and
    // set the ID for this new secondary user.
    intent?.getStringExtra(AFFILIATION_ID_KEY)?.let {
        val dpm = getManager(context)
        dpm.setAffiliationIds(getWho(context), setOf(it))
    }
    // Continue setup of the new secondary user ...
}

Java

public void onEnabled(Context context, Intent intent) {
  // Get the affiliation ID (our DPC previously put in the extras) and
  // set the ID for this new secondary user.
  String affiliationId = intent.getStringExtra(AFFILIATION_ID_KEY);
  if (affiliationId != null) {
    DevicePolicyManager dpm = getManager(context);
    dpm.setAffiliationIds(getWho(context),
        new HashSet<String>(Arrays.asList(affiliationId)));
  }
  // Continue setup of the new secondary user ...
}

RPC giữa các DPC

Mặc dù hai phiên bản DPC đang chạy dưới những người dùng riêng biệt, DPC sở hữu thiết bị và người dùng phụ có thể giao tiếp với nhau. Do việc gọi dịch vụ của DPC khác vượt qua ranh giới của người dùng, DPC của bạn không thể gọi bindService() như bạn thường làm Android. Để liên kết với một dịch vụ đang chạy trong một người dùng khác, hãy gọi DevicePolicyManager.bindDeviceAdminServiceAsUser().

Người dùng chính và 2 người dùng phụ được liên kết đang gọi RPC.
Hình 2. Quản trị viên của người dùng chính và phụ đã liên kết phương thức dịch vụ gọi

DPC của bạn chỉ có thể liên kết với các dịch vụ đang chạy trong người dùng được trả về bởi DevicePolicyManager.getBindDeviceAdminTargetUsers(). Ví dụ sau đây cho thấy quản trị viên của một người dùng phụ liên kết với quản trị viên của thiết bị được quản lý hoàn toàn:

Kotlin

// From a secondary user, the list contains just the primary user.
dpm.getBindDeviceAdminTargetUsers(adminName).forEach {

    // Set up the callbacks for the service connection.
    val intent = Intent(mContext, FullyManagedDeviceService::class.java)
    val serviceconnection = object : ServiceConnection {
        override fun onServiceConnected(componentName: ComponentName,
                                        iBinder: IBinder) {
            // Call methods on service ...
        }
        override fun onServiceDisconnected(componentName: ComponentName) {
            // Clean up or reconnect if needed ...
        }
    }

    // Bind to the service as the primary user [it].
    val bindSuccessful = dpm.bindDeviceAdminServiceAsUser(adminName,
            intent,
            serviceconnection,
            Context.BIND_AUTO_CREATE,
            it)
}

Java

// From a secondary user, the list contains just the primary user.
List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(adminName);
if (targetUsers.isEmpty()) {
  // If the users aren't affiliated, the list doesn't contain any users.
  return;
}

// Set up the callbacks for the service connection.
Intent intent = new Intent(mContext, FullyManagedDeviceService.class);
ServiceConnection serviceconnection = new ServiceConnection() {
  @Override
  public void onServiceConnected(
      ComponentName componentName, IBinder iBinder) {
    // Call methods on service ...
  }

  @Override
  public void onServiceDisconnected(ComponentName componentName) {
    // Clean up or reconnect if needed ...
  }
};

// Bind to the service as the primary user.
UserHandle primaryUser = targetUsers.get(0);
boolean bindSuccessful = dpm.bindDeviceAdminServiceAsUser(
    adminName,
    intent,
    serviceconnection,
    Context.BIND_AUTO_CREATE,
    primaryUser);

Tài nguyên khác

Để tìm hiểu thêm về các thiết bị chuyên dụng, hãy đọc các tài liệu sau: