פיתוח אפליקציות שמותאמות למספר משתמשים

כשמכשיר תומך במספר משתמשים, צריך להודיע לאפליקציות במכשיר על המשתמשים הנפרדים האלה.

באפליקציות מסוימות, חלק מהרכיבים צריכים לפעול כרכיבים יחידים (singletons) ולקבל בקשות מכל משתמש. בשלב הזה, רק אפליקציות מערכת יכולות להשתמש בתכונה הזו.

המתקן הזה:

  • חיסכון במשאבים
  • בוררות בין משתמשים לגבי משאב משותף אחד או יותר
  • הפחתת העומס ברשת באמצעות חיבור לשרת יחיד

בתרשים הבא מתואר תהליך העברת ההרשאות עם כמה משתמשים.

תהליך הענקת הרשאות למספר משתמשים

איור 1. הרשאות של משתמשים מרובים

הפעלת רכיב יחיד (singleton)

כדי לזהות אפליקציה כ-singleton, מוסיפים את הערך android:singleUser="true" לשירות, למקלט או לספק במניפסט של 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. שימוש בממשקי 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. יכול להיות שתצטרכו ליצור רכיבי proxy שפועלים בתהליך של המשתמש, ואז ניגשים לרכיב singleUser במשתמש 0.
  5. שולחים שאילתה על משתמשים ועל הכינויים שלהם באמצעות שירות המערכת החדש UserManager:
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle) – מספר שלא עובר מיחזור ותואם לכינוי משתמש.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() – מחזירה את האוסף של הפרופילים שלכם ושל הפרופילים המנוהלים, אם יש כאלה.
  6. הרשמה להאזנה למשתמשים ספציפיים או לכל המשתמשים ולקריאות החזרה (callbacks) באמצעות ממשקי 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() כדי להשבית את האפליקציה כולה.