ניהול משתמשים מרובים

במדריך למפתחים מוסבר איך בקר מדיניות המכשיר (DPC) יכול לנהל כמה משתמשי Android במכשירים ייעודיים.

סקירה כללית

בקר DPC יכול לעזור לכמה אנשים לחלוק מכשיר ייעודי אחד. בקר ה-DPC שלך במכשיר מנוהל יכולים ליצור ולנהל שני סוגים של משתמשים:

  • משתמשים משניים הם משתמשי Android עם אפליקציות נפרדות ונתונים שמורים בין סשנים. אתם מנהלים את המשתמש באמצעות רכיב אדמין. המשתמשים האלה שימושי במקרים שבהם מרימים את המכשיר בתחילת משמרת, למשל נהגים של משלוחים או עובדי אבטחה.
  • משתמשים זמניים הם משתמשים משניים שהמערכת מוחקת כשהמשתמש יפסיק לפעול, מתנתק או שהמכשיר יופעל מחדש. המשתמשים האלה שימושיים במקרים שבהם ניתן למחוק נתונים לאחר סיום הסשן, למשל, גישה ציבורית "קיוסקים" באינטרנט.

אתם משתמשים בבקר ה-DPC הקיים כדי לנהל את המכשיר הייעודי ואת משתמשים. רכיב אדמין בבקר ה-DPC מגדיר את עצמו כאדמין של רכיב משני חדש המשתמשים כשאתם יוצרים אותם.

משתמש ראשי ושני משתמשים משניים.
איור 1. משתמשים ראשיים ומשניים שמנוהלים על ידי אדמינים מהדומיין אותו בקר DPC

אדמינים של משתמש משני חייבים להשתייך לאותה חבילה כמו האדמין של במכשיר שמנוהל במלואו. כדי לפשט את תהליך הפיתוח, מומלץ לשתף אדמין בין המכשיר למשתמשים המשניים.

כדי לנהל משתמשים מרובים במכשירים ייעודיים בדרך כלל נדרשת גרסת Android 9.0. עם זאת חלק מהשיטות המשמשות במדריך הזה למפתחים זמינות גרסאות קודמות של Android.

משתמשים משניים

משתמשים משניים יכולים להתחבר ל-Wi-Fi ולהגדיר רשתות חדשות. אבל הן כן לא יכולים לערוך או למחוק רשתות, אפילו לא את הרשתות שהן יצרו.

יצירת משתמשים

בקר ה-DPC יכול ליצור משתמשים נוספים ברקע ולאחר מכן להחליף אותם לחזית. התהליך כמעט זהה בחשבונות משניים משתמשים זמניים. יש לבצע את השלבים הבאים באדמינים של מכשיר מנוהל ומשתמש משני:

  1. קוראים לפונקציה DevicePolicyManager.createAndManageUser(). כדי ליצור משתמש זמני, צריך לכלול MAKE_USER_EPHEMERAL בארגומנט הדגלים.
  2. שיחת טלפון DevicePolicyManager.startUserInBackground() עד מפעילים את המשתמש ברקע. המשתמש יתחיל לפעול, אבל תצטרכו כדי לסיים את ההגדרה לפני שמעבירים את המשתמש לחזית ומציגים אותו האדם שמשתמש במכשיר.
  3. לאדמין של המשתמש המשני, קוראים לפונקציה DevicePolicyManager.setAffiliationIds() עד לשייך את המשתמש החדש למשתמש הראשי. צפייה תיאום DPC בהמשך.
  4. האדמין של המכשיר המנוהל במלואו יכול להתקשר DevicePolicyManager.switchUser() כדי להעביר את המשתמש אל את החזית.

בדוגמה הבאה אפשר לראות איך מוסיפים את שלב 1 ל-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...
  }
}

כשיוצרים או מפעילים משתמש חדש, אפשר לבדוק את הסיבה לכישלון של כל משתמש על ידי עיון בחריג UserOperationException והתקשרות getUserOperationResult() חריגה מהמשתמש המגבלות האלה הן סיבות נפוצות לכשל:

יצירת משתמש עשויה להימשך זמן מה. אם אתם יוצרים משתמשים לעיתים קרובות, תוכלו לשפר את חוויית המשתמש על ידי הכנת משתמש מוכן לפעולה ברקע. ייתכן שתצטרכו לאזן בין היתרונות של משתמש מוכן לפעולה עם מספר המשתמשים המותר במכשיר.

זיהוי

לאחר יצירת משתמש חדש, יש להפנות את המשתמש עם מספר סידורי קבוע מספר. אל תשמרו את UserHandle כי המערכת תמחזר אותם כמו שאתם ליצור ולמחוק משתמשים. קבלת המספר הסידורי על ידי התקשרות 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  ...
}

הגדרות משתמש

בהתאם לצרכים של המשתמשים, אפשר להתאים אישית את ההגדרה של משתמשים. ניתן לכלול את הדגלים הבאים כשקוראים לפונקציה createAndManageUser():

SKIP_SETUP_WIZARD
מדלג על הפעלת אשף ההגדרה למשתמש חדש שבודק אם יש עדכונים ומתקין אותם, מבקשת מהמשתמש להוסיף חשבון Google יחד עם שירותי Google נעילת מסך. הפעולה הזו עשויה להימשך זמן מה, וייתכן שהיא לא תהיה רלוונטית לכולם משתמשים - מכשירי קיוסק אינטרנט ציבוריים, לדוגמה.
LEAVE_ALL_SYSTEM_APPS_ENABLED
כל אפליקציות המערכת יישארו מופעלות אצל המשתמש החדש. אם לא מגדירים את הסימון הזה, המשתמש החדש מכיל את האפליקציות המינימליות שדרושות לטלפון פועלות - בדרך כלל דפדפן קבצים, חייגן טלפון, אנשי קשר והודעות SMS.

מעקב אחר מחזור החיים של המשתמש

ה-DPC (אם מדובר בתפקיד של אדמין של המכשיר המנוהל) יכול לעזור לדעת מתי משתמשים משניים משתנים. כדי להריץ משימות המשך אחרי שינויים, צריך לשנות את ברירת המחדל השיטות הבאות להתקשרות חזרה במחלקה DeviceAdminReceiver של בקר ה-DPC:

onUserStarted()
התקשרות אחרי שהמערכת מפעילה משתמש. ייתכן שהמשתמש הזה עדיין בתהליך הגדרה או פועלות ברקע. אפשר לקבל את שם המשתמש מstartedUser ארגומנט.
onUserSwitched()
נקראת אחרי שהמערכת עוברת למשתמש אחר. אפשר לקבל את המשתמש החדש שרצה עכשיו בחזית מהארגומנט switchedUser.
onUserStopped()
נקראת אחרי שהמערכת מפסיקה את המשתמש כי הוא התנתק, ועבר משתמש חדש (אם המשתמש זמני), או שה-DPC הפסיק את המשתמש. אפשר לקבל המשתמש מהארגומנט stoppedUser.
onUserAdded()
נשלחת כשהמערכת מוסיפה משתמש חדש. בדרך כלל, משתמשים משניים לא מוגדר במלואו כשה-DPC מקבל את הקריאה החוזרת (callback). אפשר לקבל את המשתמש ארגומנט newUser.
onUserRemoved()
נקראת אחרי שהמערכת מוחקת משתמש. מאחר שהמשתמש כבר נמחק, אין לך גישה למשתמש שמיוצג על ידי הארגומנט removedUser.

לדעת מתי המערכת מעבירה את המשתמש לחזית או שולחת אותו אל ברקע, האפליקציות יכולות לרשום מקלט ACTION_USER_FOREGROUND ו- ACTION_USER_BACKGROUND שידורים.

גילוי משתמשים

כדי להגיע לכל המשתמשים המשניים, אדמין של מכשיר מנוהל יכול להתקשר DevicePolicyManager.getSecondaryUsers() התוצאות לכלול משתמשים משניים או זמניים שהאדמין יצר. התוצאות גם לכלול משתמשים משניים (או משתמש אורח) שמשתמש במכשיר עשוי נוצרו. התוצאות לא כוללות פרופילים של עבודה, כי הם לא משתמשים משניים. הדוגמה הבאה מראה איך אפשר להשתמש בשיטה הזו:

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);
}

ריכזנו כאן עוד שיטות לבדיקת הסטטוס של משתמשים משניים:

DevicePolicyManager.isEphemeralUser()
כדאי להפעיל את השיטה הזו מהאדמין של משתמש משני כדי לברר אם מדובר משתמש זמני.
DevicePolicyManager.isAffiliatedUser()
כדאי להפעיל את השיטה הזו מהאדמין של משתמש משני כדי לברר אם המשתמש הזה שמשויך למשתמש הראשי. אפשר לקרוא מידע נוסף על שיוך נתונים בקטע DPC בהתאמה שלמטה.

ניהול משתמשים

אם ברצונך לנהל את מחזור החיים של המשתמש באופן מלא, אפשר לקרוא לממשקי ה-API שליטה פרטנית בזמנים ובאופן שבהם המכשיר משנה משתמשים. לדוגמה, יכולים למחוק משתמש כשלא נעשה שימוש במכשיר במשך פרק זמן מסוים, או: לשלוח לשרת את כל ההזמנות שלא נשלחו לפני שהמשמרת של אותו אדם מסתיימת.

יציאה

מערכת Android 9.0 הוסיפה לחצן התנתקות למסך הנעילה, כך שאדם שמשתמש יכול לסיים את הסשן. לאחר הקשה על הלחצן, המערכת מפסיקה את משתמש משני, מוחק את המשתמש אם הוא זמני והמשתמש הראשי חוזר לחזית. מערכת Android מסתירה את הלחצן כשהמשתמש הראשי נמצא בחזית כי המשתמש הראשי לא יכול להתנתק.

כברירת מחדל, הלחצן של סיום הסשן לא מוצג ב-Android, אבל מנהל המערכת (מכשיר מנוהל) יכול להפעיל אותו על ידי התקשרות DevicePolicyManager.setLogoutEnabled() אם צריך עליך לאשר את המצב הנוכחי של הלחצן, להתקשר DevicePolicyManager.isLogoutEnabled()

האדמין של משתמש משני יכול באופן פרוגרמטי לנתק את המשתמש ולחזור למשתמש הראשי. קודם כול, מוודאים שהמשתמשים המשניים והמשתמשים הראשיים משויך, ואז קריאה ל-DevicePolicyManager.logoutUser(). אם המיקום המשתמש המנותק הוא משתמש זמני, המערכת מפסיקה ואז מוחקת את משתמש.

החלפת משתמשים

כדי לעבור למשתמש משני אחר, האדמין של מכשיר מנוהל יכול קוראים לפונקציה DevicePolicyManager.switchUser(). לנוחיותכם, יכול להעביר את null כדי לעבור למשתמש הראשי.

עצירת משתמש

כדי לעצור משתמש משני, בקר DPC שבבעלותו מכשיר מנוהל יכול לבצע קריאה DevicePolicyManager.stopUser() אם המשתמש שעצר הוא משתמש זמני, נעצר ואז נמחק.

מומלץ לעצור את המשתמשים ככל האפשר כדי להישאר מתחתיו המספר המקסימלי של משתמשים פעילים.

מחיקת משתמש

כדי למחוק באופן סופי משתמש משני, בקר DPC יכול לבצע אחת מהפעולות הבאות DevicePolicyManager אמצעי תשלום:

  • אדמין של מכשיר מנוהל יכול להתקשר למספר removeUser().
  • אדמין של המשתמש המשני יכול להתקשר למספר wipeData().

המערכת מוחקת משתמשים זמניים כשהם לא מחוברים לחשבון, כשהם עוצרים או עוברים לא בקרבת מקום.

השבתה של ממשק המשתמש שמוגדר כברירת מחדל

אם בקר ה-DPC מספק ממשק משתמש לניהול המשתמשים, אפשר להשבית את וממשק מרובה-משתמשים. אפשר לעשות זאת באמצעות שיחת טלפון DevicePolicyManager.setLogoutEnabled() ומוסיפים את הפקודה ההגבלה על DISALLOW_USER_SWITCH, כפי שמוצג בדוגמה הבאה:

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);

מי שמשתמש במכשיר לא יכול להוסיף משתמשים משניים באמצעות ממשק המשתמש המובנה של Android. מכיוון שאדמינים של מכשירים מנוהלים מוסיפים באופן אוטומטי את DISALLOW_ADD_USER הגבלת משתמשים.

הודעות סשן

כשמי שמשתמש במכשיר עובר למשתמש חדש, מערכת Android מציגה חלונית אל להדגיש את המתג. ב-Android מוצגות ההודעות הבאות:

  • הודעה על התחלת סשן של משתמש שמוצגת כשהמכשיר עובר למינוי משני מהמשתמש הראשי.
  • הודעה על סשן של משתמש קצה שמוצגת כשהמכשיר חוזר למשתמש הראשי ממשתמש משני.

המערכת לא מציגה את ההודעות במעבר בין שני משתמשים משניים.

מאחר שההודעות לא מתאימות לכל המצבים, ניתן לשנות בטקסט של ההודעות האלה. לדוגמה, אם הפתרון משתמש במשתמש זמני אפשר לשקף זאת בהודעות כמו: עצירת הדפדפן סשן מתבצעת מחיקה של המידע האישי...

המערכת מציגה את ההודעה למשך כמה שניות בלבד, כך שכל הודעה צריך להיות ביטוי קצר וברור. כדי להתאים אישית את ההודעות, האדמין יכול להתקשר השיטות DevicePolicyManager setStartUserSessionMessage() וגם setEndUserSessionMessage() כפי שמוצג בדוגמה הבאה:

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);

כדי למחוק את ההודעות המותאמות אישית ולחזור לברירת המחדל של Android, מעבירים את null הודעות. אם אתה צריך לבדוק את הטקסט של ההודעה הנוכחית, התקשר getStartUserSessionMessage() או getEndUserSessionMessage()

בקר ה-DPC צריך להגדיר הודעות מקומיות ללוקאל הנוכחי של המשתמש. צריך גם לעדכן את ההודעות כאשר שינויים באזור של המשתמש:

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);
}

תיאום בקר DPC

בדרך כלל, כדי לנהל משתמשים משניים צריך ליצור שני מופעים של בקר ה-DPC – מופע אחד שבבעלותו המכשיר המנוהל במלואו ואילו המכשיר האחר הוא הבעלים המשני. במהלך היצירה משתמש חדש, האדמין של המכשיר המנוהל הגדיר מופע נוסף של עצמו כאדמין של המשתמש החדש.

משתמשים משויכים

חלק מממשקי ה-API במדריך למפתחים פועלים רק כאשר המשתמשים המשניים הם משויכים. כי מערכת Android משביתה חלק מהתכונות (למשל, רישום ביומן ברשת) כשמוסיפים משתמשים משניים חדשים לא משויכים במכשיר, עליך לשייך משתמשים בהקדם האפשרי. אפשר לראות את הדוגמה ב- הגדרה בהמשך.

הגדרה

לפני ההגדרה של משתמשים משניים חדשים (מה-DPC שהוא הבעלים של המשתמש המשני), צריך להגדיר לאפשר לאנשים להשתמש בהם. אפשר לבצע את ההגדרה דרך DeviceAdminReceiver.onEnabled() קריאה חוזרת (callback). אם בעבר להגדיר תוספות אדמין בשיחה ל-createAndManageUser(), כדי לקבל מהארגומנט intent. בדוגמה הבאה מוצג בקר DPC משויך משתמש משני חדש בקריאה החוזרת (callback):

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 ...
}

RPCs בין בקרי DPC

שתי מכונות ה-DPC פועלות אצל משתמשים נפרדים, אבל בקרי ה-DPC שהם הבעלים של המכשיר והמשתמשים המשניים יכולים לתקשר זה עם זה. קריאה לשירות של בקר DPC אחר חוצה את גבולות המשתמשים, ולכן ה-DPC לא יכול להתקשר אל bindService() כמו בדרך כלל Android. קישור לשירות שפועל ב- משתמש נוסף, התקשרות DevicePolicyManager.bindDeviceAdminServiceAsUser()

משתמש ראשי ושני משתמשים משניים משויכים שקוראים ל-RPCs.
איור 2. אדמינים של משתמשים ראשיים ומשניים משויכים שיטות שירות הקריאה

בקר ה-DPC יכול לקשר רק לשירותים שפועלים אצל המשתמשים שהוחזרו על ידי DevicePolicyManager.getBindDeviceAdminTargetUsers() בדוגמה הבאה מוצג האדמין של משתמש משני שמקשר לאדמין של המכשיר המנוהל:

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);

מקורות מידע נוספים

כדי לקבל מידע נוסף על מכשירים ייעודיים, כדאי לקרוא את המסמכים הבאים: