Lorsqu'un appareil prend en charge plusieurs utilisateurs , ses applications doivent connaître ces utilisateurs distincts.
Certaines applications doivent avoir certains composants exécutés en tant que singletons et peuvent accepter les demandes de n'importe quel utilisateur. Seules les applications système peuvent actuellement utiliser cette fonctionnalité.
Cette installation :
- Préserve les ressources
- Arbitre une ou plusieurs ressources partagées entre les utilisateurs
- Réduit la surcharge du réseau en utilisant une connexion à un seul serveur
Consultez le diagramme ci-dessous pour une représentation du flux d’autorisations avec plusieurs utilisateurs.
Activation d'un composant singleton
Pour identifier une application en tant que singleton, ajoutez android:singleUser="true"
à votre service, récepteur ou fournisseur dans le manifeste Android.
Le système instanciera ce composant dans le processus exécuté en tant qu'utilisateur 0 uniquement. Toute demande de connexion à ce fournisseur ou service, ou de diffusion vers ce récepteur, émanant de n'importe quel utilisateur sera acheminée 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écutera.
Les activités de votre package seront toujours lancées dans un processus distinct pour chaque utilisateur, l'UID étant dans la plage 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 rendre les applications conscientes de plusieurs utilisateurs.
- Extrayez le descripteur utilisateur des appels Binder entrants :
-
int userHandle = UserHandle.getCallingUserId()
-
- Utilisez de nouvelles API protégées pour démarrer des services, des activités, 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 handles spéciaux :UserHandle.CURRENT
ouUserHandle.ALL
.CURRENT
indique l'utilisateur qui est actuellement au premier plan. UtilisezALL
lorsque vous souhaitez envoyer une diffusion à tous les utilisateurs. -
- Communiquez avec des composants de votre propre application :
(INTERACT_ACROSS_USERS)
Ou avec des composants d'autres applications :(INTERACT_ACROSS_USERS_FULL)
- Vous devrez peut-être créer des composants proxy qui s'exécutent dans le processus de l'utilisateur et qui accèdent ensuite au composant
singleUser
de l'utilisateur 0. - Interrogez les utilisateurs et leurs identifiants avec le nouveau service système
UserManager
:-
UserManager.getUsers()
-
UserManager.getUserInfo()
-
UserManager.supportsMultipleUsers()
-
UserManager.getUserSerialNumber(int userHandle)
- un numéro non recyclé qui correspond à un identifiant utilisateur. -
UserManager.getUserHandle(int serialNumber)
-
UserManager.getUserProfiles()
- renvoie la collection de profils autonomes et gérés, le cas échéant.
-
- Inscrivez-vous pour écouter des utilisateurs spécifiques ou tous et les rappels avec de nouvelles API sur ContentObserver, PackageMonitor, BroadcastReceiver qui fournissent des informations supplémentaires sur l'utilisateur qui a provoqué le rappel.
Services dans plusieurs utilisateurs ou profils
Tous les services n'ont pas besoin d'exécuter une instance dans un autre utilisateur ou profil professionnel. Si votre service système doit uniquement être exécuté en tant qu'utilisateur 0, désactivez les composants du service lors de son exécution sous d'autres utilisateurs pour contribuer à 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 pourrait également utiliser PackageManager.setApplicationEnabledSetting()
pour désactiver l'intégralité de l'application.