Créer des applications multi-utilisateurs

Lorsqu'un appareil est compatible avec plusieurs utilisateurs, ses applications doivent être informées de ces utilisateurs distincts.

Certaines applications doivent exécuter certains composants en tant que singleton et peuvent accepter les requêtes de n'importe quel utilisateur. Seules les applications système peuvent actuellement utiliser cette fonctionnalité.

Cette installation:

  • Conserve les ressources
  • Arbitrage d'une ou de plusieurs ressources partagées entre les utilisateurs
  • Réduit les coûts réseau en utilisant une seule connexion de serveur

Le diagramme ci-dessous illustre le flux d'autorisations avec plusieurs utilisateurs.

Flux d'autorisations pour plusieurs utilisateurs

Figure 1 : Autorisations pour plusieurs utilisateurs

Activer un composant singleton

Pour identifier une application comme singleton, ajoutez android:singleUser="true" à votre service, votre broadcast receiver ou votre fournisseur dans le fichier manifeste Android.

Le système instancie ce composant dans le processus exécuté en tant qu'utilisateur 0 uniquement. Toutes les requêtes de connexion à ce fournisseur ou service, ou de diffusion à ce récepteur, de la part de n'importe quel utilisateur sont acheminées vers le processus de l'utilisateur 0. S'il s'agit du seul composant de votre application, une seule instance de votre application s'exécute.

Les activités de votre package sont toujours lancées dans un processus distinct pour chaque utilisateur, et l'UID se trouve dans la plage d'UID de cet utilisateur (par exemple, 1010034).

Interagir avec les utilisateurs

Définir les autorisations

Ces autorisations sont requises:

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

Utiliser des API

Utilisez les API suivantes pour que les applications soient conscientes de la présence de plusieurs utilisateurs.

  1. Extrayez le handle utilisateur des appels Binder entrants :
    • int userHandle = UserHandle.getCallingUserId()
  2. Utilisez de nouvelles API protégées pour démarrer des services, des activités et des diffusions sur un utilisateur spécifique :
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    UserHandle peut être un utilisateur explicite ou l'un des identifiants spéciaux : UserHandle.CURRENT ou UserHandle.ALL. CURRENT indique l'utilisateur actuellement au premier plan. Utilisez ALL lorsque vous souhaitez envoyer une diffusion à tous les utilisateurs.
  3. Communiquez avec les composants de votre propre application : (INTERACT_ACROSS_USERS) Ou avec les composants d'autres applications : (INTERACT_ACROSS_USERS_FULL)
  4. Vous devrez peut-être créer des composants proxy qui s'exécutent dans le processus de l'utilisateur, qui accèdent ensuite au composant singleUser dans l'utilisateur 0.
  5. Interrogez les utilisateurs et leurs identifiants avec le nouveau service système UserManager :
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle) : numéro non recyclé correspondant à un identifiant utilisateur.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() : renvoie la collection de profils autogérés et gérés, le cas échéant.
  6. Inscrivez-vous pour écouter des utilisateurs spécifiques ou tous les utilisateurs et les rappels avec de nouvelles API sur ContentObserver, PackageMonitor et BroadcastReceiver qui fournissent des informations supplémentaires sur l'utilisateur à l'origine du rappel.

Services dans plusieurs utilisateurs ou profils

Tous les services n'ont pas besoin d'exécuter une instance dans un autre profil utilisateur ou professionnel. Si votre service système ne doit s'exécuter qu'en tant qu'utilisateur 0, désactivez les composants du service lorsqu'il s'exécute sous d'autres utilisateurs pour préserver les ressources. L'exemple suivant montre comment procéder aux points d'entrée de votre service:

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

L'exemple peut également utiliser PackageManager.setApplicationEnabledSetting() pour désactiver l'ensemble de l'application.