ตั้งแต่วันที่ 27 มีนาคม 2025 เป็นต้นไป เราขอแนะนำให้ใช้ android-latest-release
แทน aosp-main
เพื่อสร้างและมีส่วนร่วมใน AOSP โปรดดูข้อมูลเพิ่มเติมที่หัวข้อการเปลี่ยนแปลงใน AOSP
สร้างแอปที่รองรับผู้ใช้หลายคน
จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน
บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ
เมื่ออุปกรณ์รองรับผู้ใช้หลายคน แอปของอุปกรณ์จะต้องรับรู้ถึงผู้ใช้ที่แตกต่างกันเหล่านี้
แอปบางแอปจำเป็นต้องมีคอมโพเนนต์บางอย่างที่ทำงานแบบ Singleton และยอมรับคำขอจากผู้ใช้ทุกคนได้ ปัจจุบันมีเพียงแอประบบเท่านั้นที่ใช้ฟีเจอร์นี้ได้
สิ่งอำนวยความสะดวกนี้
- ประหยัดทรัพยากร
- ระงับทรัพยากรที่แชร์อย่างน้อย 1 รายการในหมู่ผู้ใช้
- ลดค่าใช้จ่ายเพิ่มเติมของเครือข่ายโดยใช้การเชื่อมต่อเซิร์ฟเวอร์เดียว
ดูภาพแผนภาพด้านล่างเพื่อดูภาพขั้นตอนของสิทธิ์ที่มีผู้ใช้หลายคน
รูปที่ 1 สิทธิ์ของผู้ใช้หลายคน
เปิดใช้คอมโพเนนต์แบบ Singleton
หากต้องการระบุว่าแอปเป็นแบบ Singleton ให้เพิ่ม android:singleUser="true"
ลงในบริการ ผู้รับ หรือผู้ให้บริการในไฟล์ Manifest ของ Android
ระบบจะสร้างอินสแตนซ์ของคอมโพเนนต์นั้นในกระบวนการที่ทำงานในฐานะผู้ใช้ 0 เท่านั้น คำขอเชื่อมต่อกับผู้ให้บริการหรือบริการนั้น หรือเพื่อออกอากาศไปยังผู้รับนั้นจากผู้ใช้รายใดก็ตามจะส่งไปยังกระบวนการในผู้ใช้ 0 หากคอมโพเนนต์นี้เป็นคอมโพเนนต์เดียวในแอป แอปจะทํางานเพียงอินสแตนซ์เดียว
กิจกรรมในแพ็กเกจจะยังคงเปิดขึ้นในกระบวนการแยกต่างหากสําหรับผู้ใช้แต่ละราย โดยมี UID อยู่ในช่วง UID ของผู้ใช้รายนั้น (เช่น 1010034)
โต้ตอบกับผู้ใช้
ตั้งค่าสิทธิ์
ต้องมีสิทธิ์ต่อไปนี้
INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)
ใช้ API
ใช้ API ต่อไปนี้เพื่อให้แอปรับรู้ผู้ใช้หลายคน
- ดึงข้อมูลแฮนเดิลผู้ใช้จากการเรียก Binder ที่เข้ามา
int userHandle = UserHandle.getCallingUserId()
- ใช้ Protected API ใหม่เพื่อเริ่มบริการ กิจกรรม การออกอากาศในผู้ใช้ที่เฉพาะเจาะจง โดยทำดังนี้
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()
- แสดงรายการโปรไฟล์ของคุณเองและโปรไฟล์ที่มีการจัดการ (หากมี)
- ลงทะเบียนเพื่อฟังผู้ใช้บางรายหรือทั้งหมดและระบบเรียกกลับด้วย API ใหม่ใน 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 UTC
[[["เข้าใจง่าย","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 UTC"],[],[],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."]]