Mehrfachnutzer-Apps entwickeln

Wenn ein Gerät mehrere Nutzer unterstützt, müssen die Apps auf diese verschiedenen Nutzer aufmerksam gemacht werden.

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

Diese Einrichtung:

  • Ressourcenschonend
  • Eine oder mehrere freigegebene Ressourcen für Nutzer verwalten
  • Reduziert den Netzwerkoverhead durch Verwendung einer einzelnen Serververbindung

Im Diagramm unten ist der Berechtigungsfluss mit mehreren Nutzern dargestellt.

Ablauf für Berechtigungen für mehrere Nutzer

Abbildung 1: Berechtigungen für mehrere Nutzer

Singleton-Komponente aktivieren

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

Das System erstellt diese Komponente nur im Prozess, der als Nutzer 0 ausgeführt wird. Alle Anfragen von Nutzern, eine Verbindung zu diesem Anbieter oder Dienst herzustellen oder an diesen Empfänger zu senden, werden an den Prozess in Nutzer 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 Nutzer in einem separaten Prozess gestartet. Die UID muss sich dabei im UID-Bereich für diesen Nutzer befinden (z. B. 1010034).

Mit Nutzern interagieren

Berechtigungen festlegen

Folgende Berechtigungen sind erforderlich:

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

APIs verwenden

Mit den folgenden APIs können Sie Apps auf mehrere Nutzer aufmerksam machen.

  1. Nutzer-Handle aus eingehenden Binder-Aufrufen extrahieren:
    • int userHandle = UserHandle.getCallingUserId()
  2. Mit neuen, geschützten APIs können Sie Dienste, Aktivitäten und Übertragungen für einen bestimmten Nutzer starten:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    UserHandle kann ein expliziter Nutzer oder einer der speziellen Aliasse sein: UserHandle.CURRENT oder UserHandle.ALL. CURRENT steht für den Nutzer, der sich gerade im Vordergrund befindet. Verwenden Sie ALL, wenn Sie eine Nachricht an alle Nutzer senden möchten.
  3. Kommunikation 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 Proxykomponenten erstellen, die im Prozess des Nutzers ausgeführt werden und dann auf die singleUser-Komponente in Nutzer 0 zugreifen.
  5. Nutzer und ihre Aliasse mit dem neuen UserManager-Systemdienst abfragen:
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle) – eine nicht wiederverwendete Nummer, die einem Nutzer-Alias entspricht.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() – gibt die Sammlung der selbst erstellten und verwalteten Profile zurück, sofern vorhanden.
  6. Registrieren Sie sich, um bestimmte oder alle Nutzer und die Rückrufe mit neuen APIs auf ContentObserver, PackageMonitor und BroadcastReceiver zu überwachen, die zusätzliche Informationen dazu liefern, welcher Nutzer den Rückruf verursacht hat.

Dienste für mehrere Nutzer oder Profile

Nicht alle Dienste müssen eine Instanz in einem anderen Nutzer- oder Arbeitsprofil ausführen. Wenn Ihr Systemdienst nur als Nutzer 0 ausgeführt werden muss, deaktivieren Sie die Komponenten des Dienstes, wenn er unter anderen Nutzern ausgeführt wird, um Ressourcen zu sparen. 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);
}

Im Beispiel könnte PackageManager.setApplicationEnabledSetting() auch verwendet werden, um die gesamte App zu deaktivieren.