สร้างแอปที่รองรับผู้ใช้หลายคน

เมื่ออุปกรณ์รองรับผู้ใช้หลายคน แอปของอุปกรณ์จะต้องรับรู้ถึงผู้ใช้ที่แตกต่างกันเหล่านี้

แอปบางแอปจำเป็นต้องมีคอมโพเนนต์บางอย่างที่ทำงานแบบ 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 ต่อไปนี้เพื่อให้แอปรับรู้ผู้ใช้หลายคน

  1. ดึงข้อมูลแฮนเดิลผู้ใช้จากการเรียก Binder ที่เข้ามา
    • int userHandle = UserHandle.getCallingUserId()
  2. ใช้ 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 เมื่อคุณต้องการส่งการออกอากาศไปยังผู้ใช้ทุกคน
  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. ลงทะเบียนเพื่อฟังผู้ใช้บางรายหรือทั้งหมดและระบบเรียกกลับด้วย 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() เพื่อปิดใช้ทั้งแอปได้ด้วย