إدارة مستخدمين متعددين

يوضّح دليل المطوِّر هذا كيفية تنفيذ وحدة التحكّم بسياسة الجهاز (DPC) إدارة العديد من مستخدمي Android على أجهزة مخصصة.

نظرة عامة

يمكن أن تساعد وحدة التحكّم بسياسة الجهاز (DPC) عدة مستخدمين في مشاركة جهاز واحد مخصَّص. وحدة التحكّم بسياسة الجهاز (DPC) يمكن أن يؤدي التشغيل على جهاز مُدار بالكامل إلى إنشاء نوعين من المستخدمين وإدارتهم:

  • المستخدمون الثانويون هم مستخدمو Android الذين لديهم تطبيقات وبيانات منفصلة محفوظة. بين الجلسات. ويمكنك إدارة المستخدم من خلال مكوّن مشرف. هؤلاء المستخدمون هم مفيدة للحالات التي يتم فيها التقاط جهاز في بداية المناوبة، مثل لسائقي التوصيل أو موظفي الأمن.
  • المستخدمون المؤقتون هم مستخدمون ثانويون يحذفهم النظام عندما يحذف المستخدم المستخدم. يتوقف أو يتوقف عن التشغيل أو يعيد تشغيل الجهاز. هؤلاء المستخدمون مفيدون للحالات يمكن من خلاله حذف البيانات بعد انتهاء الجلسة، مثل المواقع الإلكترونية المتاحة للجميع وأكشاك الإنترنت.

استخدام وحدة التحكّم بسياسة الجهاز (DPC) الحالية لإدارة الجهاز المخصّص والجهاز الثانوي المستخدمين. يعيّن مكوِّن مشرف في وحدة التحكّم بسياسة الجهاز نفسه كمشرف للأجهزة الثانوية الجديدة المستخدمين عند إنشائها.

مستخدم أساسي ومستخدمان ثانويان.
الشكل 1. المستخدمون الأساسيون والثانويون الذين يديرهم المشرفون من وحدة التحكّم بسياسة الجهاز نفسها

يجب أن ينتمي مشرفو المستخدم الثانوي إلى الحزمة نفسها التي ينتمي إليها مشرف جهاز مُدار بالكامل. لتبسيط عملية التطوير، ننصحك بمشاركة مشرف بين الجهاز والمستخدمين الثانويين.

تتطلب إدارة مستخدمين متعددين على أجهزة مخصصة عادةً استخدام نظام التشغيل Android 9.0، إلا أن بعض الطرق المستخدمة في دليل هذا المطور متوفرة في الإصدارات السابقة من Android.

المستخدمون الثانويون

يمكن للمستخدمين الثانويين الاتصال بشبكة Wi-Fi وإعداد شبكات جديدة. ومع ذلك، لا يمكنهم تعديل الشبكات أو حذفها، ولا حتى الشبكات التي أنشأها.

إنشاء مستخدمين

يمكن لوحدة التحكّم بسياسة الجهاز (DPC) إنشاء مستخدمين إضافيين في الخلفية ثم تبديلهم. إلى المقدمة. هذه العملية مماثلة تقريبًا لكل من المستخدمين المؤقتين. نفِّذ الخطوات التالية على مستوى المشرفين في جهاز مُدار ومستخدم ثانوي:

  1. يمكنك الاتصال بالرقم DevicePolicyManager.createAndManageUser(). لإنشاء مستخدم مؤقت، يجب تضمين MAKE_USER_EPHEMERAL في وسيطة العلامات.
  2. اتصل DevicePolicyManager.startUserInBackground() إلى بدء تشغيل المستخدم في الخلفية. يبدأ المستخدم في التشغيل ولكنك ستحتاج إلى لإنهاء عملية الإعداد قبل توجيه المستخدم إلى المقدّمة وعرضه على للشخص الذي يستخدم الجهاز.
  3. في مشرف المستخدم الثانوي، اطلب DevicePolicyManager.setAffiliationIds() إلى وربط المستخدم الجديد بالمستخدم الأساسي. عرض يُرجى تنسيق وحدة التحكّم بسياسة الجهاز أدناه.
  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 لوحدة التحكّم بسياسة الجهاز:

onUserStarted()
يتم الاتصال بعد أن يبدأ النظام تشغيل مستخدم. من المحتمل أن هذا المستخدم لا يزال يقوم بإعداد أو قيد التشغيل في الخلفية. يمكنك الوصول إلى المستخدم من خلال startedUser. الوسيطة
onUserSwitched()
يتم استدعاؤه بعد تبديل النظام إلى مستخدم آخر. يمكنك الحصول على المستخدم الجديد التي تعمل الآن في المقدّمة من الوسيطة switchedUser.
onUserStopped()
يتم الاتصال بعد أن يوقف النظام المستخدم بسبب تسجيل خروجه، ثم التبديل إلى مستخدم جديد (إذا كان المستخدم مؤقتًا) أو أوقفت وحدة التحكّم بسياسة الجهاز (DPC) المستخدم. يمكنك الحصول على المستخدم من الوسيطة stoppedUser.
onUserAdded()
يتم الاتصال عندما يضيف النظام مستخدمًا جديدًا. عادةً لا يكون المستخدمون الثانويون بالكامل عندما تتلقّى وحدة التحكّم بسياسة الجهاز (DPC) معاودة الاتصال. يمكنك الوصول إلى المستخدم من الوسيطة 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). التنسيق أدناه.

إدارة المستخدمين

إذا كنت تريد إدارة دورة حياة المستخدم بالكامل، فيمكنك طلب واجهات برمجة التطبيقات التحكّم الدقيق في توقيت التغيير الذي يحدث على الجهاز وطريقة إجراء ذلك. على سبيل المثال، حذف مستخدم إذا لم يتم استخدام الجهاز لفترة زمنية أو يمكنك إرسال أي طلبات غير مُرسَلة إلى خادم قبل انتهاء مناوبة عمل الشخص.

تسجيل الخروج

أضاف Android 9.0 زرًا لتسجيل الخروج إلى شاشة القفل لكي يشعر الشخص الذي يستخدم إنهاء الجلسة. بعد النقر على الزر، يوقف النظام مستخدم ثانوي، ويحذف المستخدم إذا كان مؤقتًا، ويعيد المستخدم الأساسي إلى المقدمة. يخفي Android الزرّ عندما يكون المستخدم الأساسي في في المقدمة لأن المستخدم الأساسي لا يمكنه تسجيل الخروج.

لا يعرض Android زر إنهاء الجلسة تلقائيًا لكنّ المشرف ( جهاز مُدار بالكامل) يمكنه تفعيله من خلال DevicePolicyManager.setLogoutEnabled() إذا كنت بحاجة إلى تأكيد الحالة الحالية للزر، قم باستدعاء DevicePolicyManager.isLogoutEnabled()

يمكن لمشرف المستخدم الثانوي تسجيل خروج المستخدم وإرجاعه آليًا للمستخدم الأساسي. أولاً، تأكد من أن المستخدمين الثانويين والمستخدمين الأساسيين تابع، ثم الاتصال DevicePolicyManager.logoutUser(). في حال حذف أن يكون المستخدم الذي سجّل خروجه مستخدمًا مؤقتًا، يتوقف النظام ثم يحذف المستخدم.

التبديل بين المستخدمين

للتبديل إلى مستخدم ثانوي مختلف، يمكن لمشرف جهاز مُدار بالكامل أن الاتصال بالرقم DevicePolicyManager.switchUser() للراحة، يمكنك يمكنه تمرير null للتبديل إلى المستخدم الأساسي.

إيقاف مستخدم

لإيقاف مستخدم ثانوي، يمكن لوحدة التحكُّم بسياسة الجهاز التي تمتلك جهازًا مُدارًا بالكامل الاتصال بها DevicePolicyManager.stopUser() إذا كان المستخدم المتوقف هو المستخدم المؤقت، يتم إيقاف المستخدم ثم حذفه.

ننصح بإيقاف المستخدمين كلما أمكن ذلك للمساعدة في البقاء أدنى من مستوى الجهاز. الحد الأقصى لعدد المستخدمين قيد التشغيل.

حذف مستخدم

لحذف مستخدم ثانوي نهائيًا، يمكن لوحدة التحكّم بسياسة الجهاز (DPC) استدعاء أحد الخيارات التالية: طريقتان (DevicePolicyManager):

  • يمكن لمشرف جهاز مُدار بالكامل الاتصال بـ removeUser().
  • يمكن لمشرف المستخدم الثانوي الاتصال بـ wipeData().

يحذف النظام المستخدمين المؤقتين عند تسجيل خروجهم أو إيقافهم أو تبديلهم. المشروع.

إيقاف واجهة المستخدم التلقائية

إذا كانت وحدة التحكّم بسياسة الجهاز (DPC) توفّر واجهة مستخدم لإدارة المستخدمين، يمكنك إيقاف واجهة برمجة التطبيقات المدمجة في Android. واجهة متعددة المستخدمين. يمكنك القيام بذلك عن طريق استدعاء 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);

مرِّر null لحذف الرسائل المخصّصة والعودة إلى تطبيق Android التلقائي. الرسائل. إذا كنت بحاجة إلى التحقق من نص الرسالة الحالية، يمكنك الاتصال getStartUserSessionMessage() أو getEndUserSessionMessage()

يجب أن تضبط وحدة التحكّم بسياسة الجهاز الرسائل المترجَمة. للغة المستخدم الحالية. وعليك أيضًا تحديث الرسائل عند التغييرات المحلية للمستخدم:

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) - واحدة يمتلكها الجهاز المُدار بالكامل بينما يمتلك الآخر المستخدم الثانوي. عند الإنشاء مستخدم جديد، يضبط مشرف الجهاز المُدار بالكامل مثيلاً آخر نفسه كمشرف للمستخدم الجديد.

المستخدمون التابعون

لا تعمل بعض واجهات برمجة التطبيقات في دليل المطوِّر هذا إلا عند وصول المستخدمين الثانويين تابعة لك. لأنّ Android يوقِف بعض الميزات (مثل تسجيل بيانات الشبكة) عند إضافة مستخدمين ثانويين جدد غير تابعين إلى الجهاز، فيجب عليك الشركاء التابعين في أقرب وقت ممكن. اطّلِع على المثال في يمكنك الإعداد أدناه.

ضبط إعدادات الجهاز

إعداد مستخدمين ثانويين جدد (من وحدة التحكّم بسياسة الجهاز (DPC) التي تمتلك المستخدم الثانوي) قبل والسماح للأشخاص باستخدامها. يمكنك إجراء هذا الإعداد من DeviceAdminReceiver.onEnabled() معاودة الاتصال. إذا سبق لك ضبط أي ميزات إضافية للمشرف في المكالمة إلى createAndManageUser()، يمكنك الحصول على من الوسيطة intent. يوضّح المثال التالي جهة تابعة لوحدة التحكّم بسياسة الجهاز (DPC) مستخدم ثانوي جديد في معاودة الاتصال:

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) بين وحدات التحكّم بسياسة الجهاز (DPC)

وعلى الرغم من تشغيل المثيلَين لوحدة التحكُّم بسياسة الجهاز (DPC) تحت إدارة مستخدمين منفصلين، لا يمكن استخدام وحدات التحكُّم بسياسة الجهاز (DPC). الذين يملكون الجهاز ويمكن للمستخدمين الثانويين التواصل مع بعضهم البعض. لا يمكن لوحدة التحكّم بسياسة الجهاز (DPC) إجراء ذلك لأنّ الاتصال بخدمة تابعة لوحدة التحكّم بسياسة الجهاز (DPC) أخرى يتجاوز حدود المستخدم. الاتصال بـ bindService() كما تستخدم عادةً في Android للربط بخدمة قيد التشغيل مستخدم آخر، اتصل DevicePolicyManager.bindDeviceAdminServiceAsUser()

مستخدم أساسي ومستخدمان ثانويان تابعان يستدعيان استدعاء إجراء عن بُعد (RPC).
الشكل 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);

مصادر إضافية

لمعرفة المزيد من المعلومات عن الأجهزة المخصّصة، اقرأ المستندات التالية: