Erstellen von Multiuser-fähigen Apps

Wenn ein Gerät mehrere Benutzer unterstützt, müssen seine Apps auf diese unterschiedlichen Benutzer aufmerksam gemacht werden.

Bei bestimmten Apps müssen einige Komponenten als Singletons ausgeführt werden und können Anfragen von jedem Benutzer annehmen. Derzeit können nur System-Apps diese Funktion nutzen.

Diese Einrichtung:

  • Schont Ressourcen
  • Vermittelt eine oder mehrere gemeinsam genutzte Ressourcen zwischen Benutzern
  • Reduziert den Netzwerkaufwand durch die Verwendung einer einzigen Serververbindung

Im folgenden Diagramm finden Sie eine Darstellung des Berechtigungsflusses bei mehreren Benutzern.

Es fließen mehrere Benutzerberechtigungen

Abbildung 1. Mehrere Benutzerberechtigungen

Aktivieren einer Singleton-Komponente

Um eine App als Singleton zu identifizieren, fügen Sie android:singleUser="true" zu Ihrem Dienst, Empfänger oder Anbieter im Android-Manifest hinzu.

Das System instanziiert diese Komponente nur im Prozess, der als Benutzer 0 ausgeführt wird. Alle Anfragen eines Benutzers, eine Verbindung zu diesem Anbieter oder Dienst herzustellen oder an diesen Empfänger zu senden, werden an den Prozess in Benutzer 0 weitergeleitet. Wenn dies die einzige Komponente in Ihrer App ist, wird nur eine Instanz Ihrer App ausgeführt.

Aktivitäten in Ihrem Paket werden weiterhin für jeden Benutzer in einem separaten Prozess gestartet, wobei die UID im UID-Bereich für diesen Benutzer liegt (z. B. 1010034).

Interaktion mit Benutzern

Berechtigungen festlegen

Diese Berechtigungen sind erforderlich

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

Nutzen Sie APIs

Verwenden Sie die folgenden APIs, um Apps auf mehrere Benutzer aufmerksam zu machen.

  1. Extrahieren Sie das Benutzerhandle aus eingehenden Binder-Aufrufen:
    • int userHandle = UserHandle.getCallingUserId()
  2. Verwenden Sie neue, geschützte APIs, um Dienste, Aktivitäten und Broadcasts für einen bestimmten Benutzer zu starten:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    UserHandle kann ein expliziter Benutzer oder eines der speziellen Handles sein: UserHandle.CURRENT oder UserHandle.ALL . CURRENT gibt den Benutzer an, der sich gerade im Vordergrund befindet. Verwenden Sie ALL , wenn Sie eine Übertragung an alle Benutzer senden möchten.
  3. Kommunizieren Sie mit Komponenten in Ihrer eigenen App: (INTERACT_ACROSS_USERS) Oder mit Komponenten in anderen Apps: (INTERACT_ACROSS_USERS_FULL)
  4. Möglicherweise müssen Sie Proxy-Komponenten erstellen, die im Prozess des Benutzers ausgeführt werden und dann auf die singleUser Komponente in Benutzer 0 zugreifen.
  5. Fragen Sie Benutzer und ihre Handles mit dem neuen UserManager -Systemdienst ab:
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle) – eine nicht recycelte Zahl, die einem Benutzerhandle entspricht.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() – gibt die Sammlung von selbst- und verwalteten Profilen zurück, falls vorhanden.
  6. Registrieren Sie sich, um bestimmte oder alle Benutzer und die Rückrufe mit neuen APIs auf ContentObserver, PackageMonitor und BroadcastReceiver abzuhören, die zusätzliche Informationen darüber bereitstellen, welcher Benutzer den Rückruf verursacht hat.

Dienste in mehreren Benutzern oder Profilen

Nicht alle Dienste müssen eine Instanz in einem anderen Benutzer- oder Arbeitsprofil ausführen. Wenn Ihr Systemdienst nur als Benutzer 0 ausgeführt werden muss, deaktivieren Sie die Komponenten des Dienstes, wenn er unter anderen Benutzern ausgeführt wird, um Ressourcen zu schonen. Das folgende Beispiel zeigt, wie Sie dies an den Einstiegspunkten Ihres Dienstes tun können:

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

Das Beispiel könnte auch PackageManager.setApplicationEnabledSetting() verwenden, um die gesamte App zu deaktivieren.