اعتبارًا من 27 آذار (مارس) 2025، ننصحك باستخدام android-latest-release
بدلاً من aosp-main
لإنشاء AOSP والمساهمة فيه. لمزيد من المعلومات، يُرجى الاطّلاع على التغييرات في AOSP.
إنشاء تطبيقات تتيح استخدامها لعدة مستخدمين
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
عندما يتيح الجهاز استخدام حسابات متعددة، يجب إعلام تطبيقاته
بهذه الحسابات.
تحتاج بعض التطبيقات إلى تشغيل بعض المكوّنات كعناصر فردية ويمكنها قبول
الطلبات من أي مستخدم. يمكن حاليًا لتطبيقات النظام فقط استخدام هذه الميزة.
هذه المرافق:
- الحفاظ على الموارد
- يحدّد مرجعًا واحدًا أو أكثر مشترَكًا بين المستخدمين
- تقليل عبء الشبكة باستخدام اتصال خادم واحد
اطّلِع على الرسم البياني أدناه للاطّلاع على وصف لتدفق الأذونات مع مستخدمين متعدّدين.
الشكل 1: أذونات مستخدمين متعدّدين
تفعيل مكوّن وحيد
لتحديد تطبيق على أنّه مثيل وحيد، أضِف android:singleUser="true"
إلى خدمتك أو
المستلِم أو المزوِّد في بيان Android.
ينشئ النظام مثيلًا لهذا المكوّن في العملية التي تعمل باسم المستخدم 0
فقط. يتم توجيه أي طلبات للاتصال بهذا الموفِّر أو الخدمة أو للبث إلى هذا المُستلِم من
أي مستخدم إلى العملية في المستخدم 0. إذا كان هذا هو المكوّن الوحيد في تطبيقك،
يتم تشغيل مثيل واحد فقط من تطبيقك.
لا يزال يتم تشغيل الأنشطة في حِزمك في عملية منفصلة لكل مستخدم، مع أنّ المعرّف الفريد للمستخدم يقع ضمن نطاق المعرّفات الفريدة لهذا المستخدم (مثل 1010034).
التفاعل مع المستخدمين
تعيين الأذونات
يجب الحصول على الأذونات التالية:
INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)
استخدام واجهات برمجة التطبيقات
استخدِم واجهات برمجة التطبيقات التالية لإعلام التطبيقات بوجود مستخدمين متعدّدين.
- استخراج الاسم المعرِّف للمستخدم من طلبات Binder الواردة:
int userHandle = UserHandle.getCallingUserId()
- استخدام واجهات برمجة تطبيقات جديدة ومحمية لبدء الخدمات والأنشطة والبث على حساب
مستخدم معيّن:
Context.startActivityAsUser(Intent, UserHandle)
Context.bindServiceAsUser(Intent, …, UserHandle)
Context.sendBroadcastAsUser(Intent, … , UserHandle)
Context.startServiceAsUser(Intent, …, UserHandle)
يمكن أن يكون UserHandle
مستخدمًا محدّدًا أو أحد الأسماء المعرِّفة الخاصة:
UserHandle.CURRENT
أو UserHandle.ALL
. يشير الرمز CURRENT
إلى المستخدم الذي يظهر حاليًا في المقدّمة. استخدِم ALL
عندما تريد
إرسال بث إلى جميع المستخدمين.
- التواصل مع المكوّنات في تطبيقك:
(INTERACT_ACROSS_USERS)
أو مع المكوّنات في تطبيقات أخرى:
(INTERACT_ACROSS_USERS_FULL)
- قد تحتاج إلى إنشاء مكونات وكيلة يتم تشغيلها في عملية المستخدم التي
ثم تصل إلى عنصر
singleUser
في المستخدم 0.
- يمكنك طلب معلومات عن المستخدمين وأسماء حساباتهم باستخدام خدمة النظام الجديدة
UserManager
:
UserManager.getUsers()
UserManager.getUserInfo()
UserManager.supportsMultipleUsers()
UserManager.getUserSerialNumber(int userHandle)
: رقم لم تتم إعادة تدويره ويرتبط
باسم حساب مستخدم
UserManager.getUserHandle(int serialNumber)
-
UserManager.getUserProfiles()
- لعرض مجموعة الملفات الشخصية المُدارة والملفات الشخصية الذاتية، إن وجدت
- يمكنك التسجيل للاستماع إلى مستخدمين محدّدين أو جميع المستخدمين وعمليات تسجيل الإحالات الناجحة باستخدام واجهات برمجة تطبيقات جديدة في
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()
لإيقاف
التطبيق بأكمله.
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-27 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["# Build multiuser-aware apps\n\nWhen a device supports [multiple users](/docs/devices/admin/multi-user), its apps must be\nmade aware of these distinct users.\n\nCertain apps need to have some components run as singletons and can accept\nrequests from any user. Only system apps can currently use this feature.\n\nThis facility:\n\n- Conserves resources\n- Arbitrates one or more shared resources across users\n- Reduces network overhead by using a single server connection\n\nSee the diagram below for a depiction of permissions flow with multiple users.\n\n\n**Figure 1.** Multiple users permissions\n\nEnable a singleton component\n----------------------------\n\nTo identify an app as a singleton, add `android:singleUser=\"true\"` to your service,\nreceiver, or provider in the Android manifest.\n\nThe system instantiates that component in the process running as user 0\nonly. Any requests to connect to that provider or service, or to broadcast to that receiver, from\nany user is routed to the process in user 0. If this is the only component in your app,\nonly one instance of your app runs.\n\nActivities in your package are still launched in a separate process for\neach user, with the UID being in the UID range for that user (such as 1010034).\n\nInteract with users\n-------------------\n\n### Set permissions\n\nThese permissions are required: \n\n```\nINTERACT_ACROSS_USERS (signature|system)\nINTERACT_ACROSS_USERS_FULL (signature)\n```\n\n### Employ APIs\n\nUse the following APIs to make apps aware of multiple users.\n\n1. Extract the user handle from incoming Binder calls:\n - `int userHandle = UserHandle.getCallingUserId()`\n2. Use new, protected APIs to start services, activities, broadcasts on a specific user:\n - `Context.startActivityAsUser(Intent, UserHandle)`\n - `Context.bindServiceAsUser(Intent, ..., UserHandle)`\n - `Context.sendBroadcastAsUser(Intent, ... , UserHandle)`\n - `Context.startServiceAsUser(Intent, ..., UserHandle)`\n\n `UserHandle` can be an explicit user or one of the special handles: `UserHandle.CURRENT` or `UserHandle.ALL`. `CURRENT` indicates the user that is currently in the foreground. Use `ALL` when you want to send a broadcast to all users.\n3. Communicate with components in your own app: `(INTERACT_ACROSS_USERS)` Or with components in other apps: `(INTERACT_ACROSS_USERS_FULL)`\n4. You might need to create proxy components that run in the user's process that then access the `singleUser` component in user 0.\n5. Query users and their handles with the new `UserManager` system service:\n - `UserManager.getUsers()`\n - `UserManager.getUserInfo()`\n - `UserManager.supportsMultipleUsers()`\n - `UserManager.getUserSerialNumber(int userHandle)` - a nonrecycled number that corresponds to a user handle.\n - `UserManager.getUserHandle(int serialNumber)`\n - `UserManager.getUserProfiles()` - returns the collection of self and managed profiles, if any.\n6. Register to listen to specific or all users and the callbacks with new APIs on ContentObserver, PackageMonitor, BroadcastReceiver that provide additional information about which user has caused the callback.\n\n### Services in multiple users or profiles\n\nNot all services need to run an instance in another user or work profile. If your system service\nonly needs to run as user 0, disable the service's components when running under other users to\nhelp preserve resources. The following example shows how you might do this at your service's entry\npoints: \n\n```\n// Add on all entry points such as boot_completed or other manifest-listed receivers and providers\nif (!UserManager.isSystemUser()) {\n // Disable the service\n ComponentName targetServiceName = new ComponentName(this, TargetService.class);\n context.getPackageManager().setComponentEnabledSetting(\n targetServiceName, COMPONENT_ENABLED_STATE_DISABLED, 0);\n}\n```\n\nThe example could also use `PackageManager.setApplicationEnabledSetting()` to disable\nthe entire app."]]