مدیریت چند کاربر

این راهنمای توسعه‌دهنده توضیح می‌دهد که چگونه کنترل‌کننده خط‌مشی دستگاه (DPC) شما می‌تواند چندین کاربر Android را در دستگاه‌های اختصاصی مدیریت کند.

نمای کلی

«کنترل‌کننده خط‌مشی دستگاه» شما می‌تواند به چند نفر کمک کند از یک دستگاه اختصاصی به‌طور مشترک استفاده کنند. DPC شما که در دستگاه کاملاً مدیریت‌شده اجرا می‌شود می‌تواند دو نوع کاربر ایجاد و مدیریت کند:

  • کاربران ثانویه کاربران Android هستند که برنامه‌ها و داده‌های جداگانه‌ای دارند که بین جلسه‌ها ذخیره می‌شود. کاربر را با مؤلفه سرپرست مدیریت می‌کنید. این کاربران برای مواردی مفید هستند که دستگاه در شروع شیفت کاری برداشته می‌شود، مثل رانندگان تحویل کالا یا کارکنان امنیتی.
  • کاربران موقت کاربران فرعی هستند که سیستم آن‌ها را وقتی کاربر متوقف می‌شود، تغییر می‌کند، یا دستگاه بازراه‌اندازی می‌شود حذف می‌کند. این کاربران برای مواردی مفید هستند که داده‌ها را می‌توان پس‌از پایان جلسه حذف کرد، مثل کیوسک‌های اینترنت با دسترسی عمومی.

از DPC موجودتان برای مدیریت دستگاه اختصاصی و کاربران فرعی استفاده می‌کنید. یک مؤلفه سرپرست در DPC شما، خودش را به‌عنوان سرپرست برای کاربران ثانویه جدید هنگام ایجاد آن‌ها تنظیم می‌کند.

کاربر اصلی و دو کاربر ثانویه.
شکل ۱. کاربران اصلی و فرعی تحت مدیریت سرپرستان از همان DPC

سرپرستان کاربر فرعی باید به همان بسته‌ای تعلق داشته باشند که سرپرست دستگاه کاملاً مدیریت‌شده به آن تعلق دارد. برای ساده کردن توسعه، توصیه می‌کنیم سرپرستی را بین دستگاه و کاربران ثانویه هم‌رسانی کنید.

مدیریت چند کاربر در دستگاه‌های اختصاصی معمولاً به Android 9.0 نیاز دارد، اما برخی‌از روش‌های استفاده‌شده در این راهنمای توسعه‌دهنده در نسخه‌های قبلی Android دردسترس است.

کاربران فرعی

کاربران فرعی می‌توانند به Wi-Fi متصل شوند و شبکه‌های جدید را پیکربندی کنند. بااین‌حال، نمی‌توانند شبکه‌ها را ویرایش یا حذف کنند، حتی شبکه‌هایی که خودشان ایجاد کرده‌اند.

ایجاد کاربر

DPC شما می‌تواند کاربران بیشتری در پس‌زمینه ایجاد کند و سپس آن‌ها را به پیش‌زمینه منتقل کند. این فرایند برای کاربران ثانویه و گذرا تقریباً یکسان است. مراحل زیر را در سرپرستان دستگاه کاملاً مدیریت‌شده و کاربر ثانویه اجرا کنید:

  1. با DevicePolicyManager.createAndManageUser() تماس بگیرید. برای ایجاد کاربر موقت، MAKE_USER_EPHEMERAL را در متغیر مستقل پرچم‌ها اضافه کنید.
  2. برای راه‌اندازی کاربر در پس‌زمینه، DevicePolicyManager.startUserInBackground() را فراخوانی کنید. کاربر شروع به اجرا می‌کند اما شما می‌خواهید راه‌اندازی را قبل‌از آوردن کاربر به پیش‌زمینه و نشان دادن آن به فردی که از دستگاه استفاده می‌کند تمام کنید.
  3. در سرپرست کاربر ثانویه، DevicePolicyManager.setAffiliationIds() را فراخوانی کنید تا کاربر جدید را به کاربر اصلی وابسته کنید. هماهنگی DPC را در زیر ببینید.
  4. در سرپرست دستگاه کاملاً مدیریت‌شده، DevicePolicyManager.switchUser() را فراخوانی کنید تا کاربر را به پیش‌زمینه منتقل کنید.

نمونه زیر نشان می‌دهد که چگونه می‌توانید مرحله ۱ را به DPC خود اضافه کنید:

کاتلین

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

جاوا

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() دریافت کنید:

کاتلین

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

جاوا

// 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
همه برنامه‌های سیستم را در کاربر جدید فعال نگه می‌دارد. اگر این پرچم را تنظیم نکنید، کاربر جدید فقط شامل حداقل مجموعه برنامه‌هایی است که تلفن برای کار کردن به آن‌ها نیاز دارد—معمولاً مرورگر فایل، شماره‌گیر تلفن، مخاطبین، و پیامک.

دنبال کردن چرخه حیات کاربر

ممکن است برای «کنترل‌کننده خط‌مشی دستگاه» شما (اگر سرپرست دستگاه کاملاً مدیریت‌شده باشد) مفید باشد که بداند کاربران ثانویه چه زمانی تغییر می‌کنند. برای اجرای تکالیف پیگیری پس‌از تغییرات، این روش‌های فراخوانی را در زیرکلاس DeviceAdminReceiver مربوط به DPC خود لغو کنید:

onUserStarted()
پس‌از اینکه سیستم کاربری را راه‌اندازی می‌کند فراخوانی می‌شود. این کاربر ممکن است هنوز درحال راه‌اندازی باشد یا در پس‌زمینه اجرا شود. می‌توانید کاربر را از آرگومان startedUser دریافت کنید.
onUserSwitched()
پس‌از اینکه سیستم به کاربر دیگری تغییر می‌کند فراخوانی می‌شود. می‌توانید کاربر جدیدی را که اکنون در پیش‌زمینه اجرا می‌شود از آرگومان switchedUser دریافت کنید.
onUserStopped()
وقتی سیستم کاربری را به‌دلیل خروج از سیستم، جابه‌جایی به کاربر جدید (اگر کاربر موقت باشد)، یا توقف کاربر توسط DPC شما متوقف می‌کند، فراخوانی می‌شود. می‌توانید کاربر را از آرگومان stoppedUser دریافت کنید.
onUserAdded()
وقتی سیستم کاربر جدیدی اضافه می‌کند، فراخوانی می‌شود. معمولاً وقتی DPC شما فراخوانی برگشتی را دریافت می‌کند، کاربران ثانویه به‌طور کامل راه‌اندازی نشده‌اند. می‌توانید کاربر را از آرگومان newUser دریافت کنید.
onUserRemoved()
پس‌از اینکه سیستم کاربری را حذف می‌کند فراخوانی می‌شود. چون کاربر قبلاً حذف شده است، نمی‌توانید به کاربری که با شناسه removedUser نشان داده شده است دسترسی پیدا کنید.

برای اینکه بدانید سیستم چه زمانی کاربر را به پیش‌زمینه می‌آورد یا کاربر را به پس‌زمینه می‌فرستد، برنامه‌ها می‌توانند گیرنده‌ای را برای همه‌فرستی‌های ACTION_USER_FOREGROUND و ACTION_USER_BACKGROUND ثبت کنند.

کاوش کاربران

برای دریافت همه کاربران ثانویه، سرپرست دستگاه کاملاً مدیریت‌شده می‌تواند DevicePolicyManager.getSecondaryUsers() را فراخوانی کند. نتایج شامل هر کاربر ثانویه یا موقتی است که سرپرست ایجاد کرده است. نتایج همچنین شامل هر کاربر ثانویه (یا کاربر مهمان) که ممکن است فردی که از دستگاه استفاده می‌کند ایجاد کرده باشد می‌شود. نتایج شامل نمایه کاری نمی‌شود زیرا نمایه کاری کاربر فرعی نیست. نمونه زیر نشان می‌دهد که چگونه می‌توانید از این روش استفاده کنید:

کاتلین

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

جاوا

// 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 انجام دهید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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

جاوا

// 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() را همان‌طور که در مثال زیر نشان داده شده است فراخوانی کند:

کاتلین

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

جاوا

// 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 شما باید پیام‌های بومی‌سازی‌شده را برای زبان فعلی کاربر تنظیم کند. همچنین باید پیام‌ها را هنگام تغییر منطقه زبانی کاربر به‌روز کنید:

کاتلین

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

جاوا

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 شما نیاز دارد—یکی که مالک دستگاه کاملاً مدیریت‌شده است و دیگری که مالک کاربر فرعی است. هنگام ایجاد کاربر جدید، سرپرست دستگاه کاملاً مدیریت‌شده نمونه دیگری از خودش را به‌عنوان سرپرست کاربر جدید تنظیم می‌کند.

کاربران وابسته

برخی‌از میاناهای برنامه‌سازی کاربردی در این راهنمای توسعه‌دهنده فقط زمانی کار می‌کنند که کاربران فرعی وابسته باشند. چون وقتی کاربران ثانویه غیروابسته جدیدی به دستگاه اضافه می‌کنید، Android برخی‌از ویژگی‌ها (مثلاً گزارش‌گیری شبکه) را غیرفعال می‌کند، باید در اسرع وقت کاربران را وابسته کنید. نمونه را در راه‌اندازی در زیر ببینید.

راه‌اندازی

کاربران ثانویه جدید را (از DPC که مالک کاربر ثانویه است) قبل‌از اینکه به افراد اجازه دهید از آن‌ها استفاده کنند، راه‌اندازی کنید. می‌توانید این راه‌اندازی را از فراخوانی برگشتی DeviceAdminReceiver.onEnabled() انجام دهید. اگر قبلاً هرگونه موارد اضافی سرپرست را در تماس با createAndManageUser() تنظیم کرده‌اید، می‌توانید مقادیر را از آرگومان intent دریافت کنید. مثال زیر نشان می‌دهد که یک DPC کاربر فرعی جدیدی را در callback وابسته می‌کند:

کاتلین

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

جاوا

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 تماس می‌گیرند.
شکل ۲. سرپرستان کاربران اصلی و فرعی وابسته روش‌های سرویس تماس

DPC شما فقط می‌تواند به سرویس‌هایی متصل شود که در کاربران برگردانده‌شده توسط DevicePolicyManager.getBindDeviceAdminTargetUsers() اجرا می‌شوند. مثال زیر سرپرست کاربر فرعی را نشان می‌دهد که به سرپرست دستگاه کاملاً مدیریت‌شده متصل می‌شود:

کاتلین

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

جاوا

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

منابع بیشتر

برای کسب اطلاعات بیشتر درباره دستگاه‌های اختصاصی، اسناد زیر را بخوانید: