إنشاء تطبيقات تتيح استخدامها لعدة مستخدمين

عندما يتيح الجهاز استخدام حسابات متعددة، يجب إعلام تطبيقاته بهذه الحسابات.

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

هذه المرافق:

  • الحفاظ على الموارد
  • يحدّد مرجعًا واحدًا أو أكثر مشترَكًا بين المستخدمين
  • تقليل عبء الشبكة باستخدام اتصال خادم واحد

اطّلِع على الرسم البياني أدناه للاطّلاع على وصف لتدفق الأذونات مع مستخدمين متعدّدين.

مسار أذونات المستخدمين المتعدّدين

الشكل 1: أذونات مستخدمين متعدّدين

تفعيل مكوّن وحيد

لتحديد تطبيق على أنّه مثيل وحيد، أضِف android:singleUser="true" إلى خدمتك أو المستلِم أو المزوِّد في بيان Android.

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

لا يزال يتم تشغيل الأنشطة في حِزمك في عملية منفصلة لكل مستخدم، مع أنّ المعرّف الفريد للمستخدم يقع ضمن نطاق المعرّفات الفريدة لهذا المستخدم (مثل 1010034).

التفاعل مع المستخدمين

تعيين الأذونات

يجب الحصول على الأذونات التالية:

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

استخدام واجهات برمجة التطبيقات

استخدِم واجهات برمجة التطبيقات التالية لإعلام التطبيقات بوجود مستخدمين متعدّدين.

  1. استخراج الاسم المعرِّف للمستخدم من طلبات Binder الواردة:
    • int userHandle = UserHandle.getCallingUserId()
  2. استخدام واجهات برمجة تطبيقات جديدة ومحمية لبدء الخدمات والأنشطة والبث على حساب مستخدم معيّن:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    يمكن أن يكون UserHandle مستخدمًا محدّدًا أو أحد الأسماء المعرِّفة الخاصة: UserHandle.CURRENT أو UserHandle.ALL. يشير الرمز CURRENT إلى المستخدم الذي يظهر حاليًا في المقدّمة. استخدِم ALL عندما تريد إرسال بث إلى جميع المستخدمين.
  3. التواصل مع المكوّنات في تطبيقك: (INTERACT_ACROSS_USERS) أو مع المكوّنات في تطبيقات أخرى: (INTERACT_ACROSS_USERS_FULL)
  4. قد تحتاج إلى إنشاء مكونات وكيلة يتم تشغيلها في عملية المستخدم التي ثم تصل إلى عنصر singleUser في المستخدم 0.
  5. يمكنك طلب معلومات عن المستخدمين وأسماء حساباتهم باستخدام خدمة النظام الجديدة UserManager:
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle): رقم لم تتم إعادة تدويره ويرتبط باسم حساب مستخدم
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() - لعرض مجموعة الملفات الشخصية المُدارة والملفات الشخصية الذاتية، إن وجدت
  6. يمكنك التسجيل للاستماع إلى مستخدمين محدّدين أو جميع المستخدمين وعمليات تسجيل الإحالات الناجحة باستخدام واجهات برمجة تطبيقات جديدة في ContentObserver وPackageMonitor وBroadcastReceiver التي تقدّم معلومات إضافية عن المستخدم الذي أجرى تسجيل الإحالة الناجحة.

الخدمات في مستخدمين أو ملفات شخصية متعددة

لا تحتاج بعض الخدمات إلى تشغيل مثيل في ملف شخصي آخر للمستخدم أو للعمل. إذا كانت خدمة النظام تحتاج فقط إلى التشغيل باسم المستخدم 0، أوقِف مكونات الخدمة عند تشغيلها باسم مستخدمين آخرين لمساعدة في الحفاظ على الموارد. يوضّح المثال التالي كيفية إجراء ذلك عند نقاط دخول خدمتك:

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

يمكن أن يستخدم المثال أيضًا PackageManager.setApplicationEnabledSetting() لإيقاف التطبيق بأكمله.