Ce guide du développeur explique comment votre outil de contrôle des règles relatives aux appareils (DPC) peut gérer plusieurs utilisateurs Android sur des appareils dédiés.
Présentation
Votre DPC peut aider plusieurs personnes à partager un même appareil dédié. Votre DPC exécutés sur un appareil entièrement géré peuvent créer et gérer deux types d'utilisateurs:
- Les utilisateurs secondaires sont les utilisateurs Android dont les applications et les données sont enregistrées séparément. entre les sessions. Vous gérez les utilisateurs à l'aide d'un composant d'administration. Ces utilisateurs sont utile dans les cas où un appareil est repris au début d'une journée de travail, par exemple les chauffeurs-livreurs ou les agents de sécurité.
- Les utilisateurs éphémères sont les utilisateurs secondaires que le système supprime lorsqu'ils s'arrête, s'éteint ou redémarre. Ces utilisateurs sont utiles pour les cas où les données peuvent être supprimées une fois la session terminée, telles que l'accès public des kiosques Internet.
Vous utilisez votre DPC existant pour gérer l'appareil dédié et l'appareil secondaire utilisateurs. Un composant d'administration de votre DPC se définit comme l'administrateur de la nouvelle utilisateurs lorsque vous les créez.
Les administrateurs d'un utilisateur secondaire doivent appartenir au même package que l'administrateur du un appareil entièrement géré. Pour simplifier le développement, nous vous recommandons de partager entre l'appareil et les utilisateurs secondaires.
La gestion de plusieurs utilisateurs sur des appareils dédiés nécessite généralement Android 9.0, Cependant, certaines des méthodes utilisées dans ce guide du développeur sont disponibles versions antérieures d'Android.
Utilisateurs secondaires
Les utilisateurs secondaires peuvent se connecter au Wi-Fi et configurer de nouveaux réseaux. Cependant, ils ne peuvent pas modifier ni supprimer des réseaux, pas même les réseaux qu’ils ont créés.
Créer des utilisateurs
Votre DPC peut créer des utilisateurs supplémentaires en arrière-plan, puis les basculer au premier plan. Le processus est presque le même pour les instances secondaires les utilisateurs éphémères. Procédez comme suit dans les administrateurs appareil géré et utilisateur secondaire:
- Appelez
DevicePolicyManager.createAndManageUser()
. Pour créer un utilisateur éphémère, incluezMAKE_USER_EPHEMERAL
dans l'argument "flags". - Appeler
DevicePolicyManager.startUserInBackground()
jusqu'à démarrer l'utilisateur en arrière-plan. L'utilisateur commence à courir, mais vous voudrez pour terminer la configuration avant de placer l'utilisateur au premier plan la personne qui utilise l'appareil. - Dans l'administrateur de l'utilisateur secondaire, appelez
DevicePolicyManager.setAffiliationIds()
jusqu'à associer le nouvel utilisateur à l'utilisateur principal. Voir Coordination DPC ci-dessous. - De retour dans l'administrateur de l'appareil entièrement géré, appelez
DevicePolicyManager.switchUser()
pour basculer l'utilisateur vers au premier plan.
L'exemple suivant montre comment ajouter l'étape 1 à votre DPC:
Kotlin
val dpm = getContext().getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager // If possible, reuse an existing affiliation ID across the // primary user and (later) the ephemeral user. val identifiers = dpm.getAffiliationIds(adminName) if (identifiers.isEmpty()) { identifiers.add(UUID.randomUUID().toString()) dpm.setAffiliationIds(adminName, identifiers) } // Pass an affiliation ID to the ephemeral user in the admin extras. val adminExtras = PersistableBundle() adminExtras.putString(AFFILIATION_ID_KEY, identifiers.first()) // Include any other config for the new user here ... // Create the ephemeral user, using this component as the admin. try { val ephemeralUser = dpm.createAndManageUser( adminName, "tmp_user", adminName, adminExtras, DevicePolicyManager.MAKE_USER_EPHEMERAL or DevicePolicyManager.SKIP_SETUP_WIZARD) } catch (e: UserManager.UserOperationException) { if (e.userOperationResult == UserManager.USER_OPERATION_ERROR_MAX_USERS) { // Find a way to free up users... } }
Java
DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE); // If possible, reuse an existing affiliation ID across the // primary user and (later) the ephemeral user. Set<String> identifiers = dpm.getAffiliationIds(adminName); if (identifiers.isEmpty()) { identifiers.add(UUID.randomUUID().toString()); dpm.setAffiliationIds(adminName, identifiers); } // Pass an affiliation ID to the ephemeral user in the admin extras. PersistableBundle adminExtras = new PersistableBundle(); adminExtras.putString(AFFILIATION_ID_KEY, identifiers.iterator().next()); // Include any other config for the new user here ... // Create the ephemeral user, using this component as the admin. try { UserHandle ephemeralUser = dpm.createAndManageUser( adminName, "tmp_user", adminName, adminExtras, DevicePolicyManager.MAKE_USER_EPHEMERAL | DevicePolicyManager.SKIP_SETUP_WIZARD); } catch (UserManager.UserOperationException e) { if (e.getUserOperationResult() == UserManager.USER_OPERATION_ERROR_MAX_USERS) { // Find a way to free up users... } }
Lorsque vous créez ou démarrez un nouvel utilisateur, vous pouvez vérifier la raison des échecs
en interceptant l'exception UserOperationException
et en appelant
getUserOperationResult()
Dépassement du nombre d'utilisateurs
sont des raisons courantes d'échec:
La création d'un utilisateur peut prendre un certain temps. Si vous créez fréquemment des utilisateurs, vous pouvez améliorer l'expérience utilisateur en préparant un utilisateur prêt à l'emploi en arrière-plan. Vous devrez peut-être concilier les avantages d'un utilisateur prêt à l'emploi et d'utilisateurs autorisés sur un appareil.
Identification
Après avoir créé un utilisateur, vous devez faire référence à celui-ci avec un numéro de série persistant
numéro. Ne conservez pas les UserHandle
, car le système les recycle à mesure que vous
créer et supprimer des utilisateurs. Pour obtenir le numéro de série, appelez
UserManager.getSerialNumberForUser()
:
Kotlin
// After calling createAndManageUser() use a device-unique serial number // (that isn’t recycled) to identify the new user. secondaryUser?.let { val userManager = getContext().getSystemService(UserManager::class.java) val ephemeralUserId = userManager!!.getSerialNumberForUser(it) // Save the serial number to storage ... }
Java
// After calling createAndManageUser() use a device-unique serial number // (that isn’t recycled) to identify the new user. if (secondaryUser != null) { UserManager userManager = getContext().getSystemService(UserManager.class); long ephemeralUserId = userManager.getSerialNumberForUser(secondaryUser); // Save the serial number to storage ... }
Configuration utilisateur
Selon les besoins de vos utilisateurs, vous pouvez personnaliser la configuration
utilisateurs. Vous pouvez inclure les options suivantes lorsque vous appelez createAndManageUser()
:
SKIP_SETUP_WIZARD
- Ignore l'exécution de l'assistant de configuration destiné aux nouveaux utilisateurs, qui recherche et installe des mises à jour. invite l'utilisateur à ajouter un compte Google ainsi que les services Google, et définit le verrouillage de l’écran. Cela peut prendre un certain temps et ne pas s'appliquer à tous les cas (des kiosques Internet publics, par exemple).
LEAVE_ALL_SYSTEM_APPS_ENABLED
- Laisse toutes les applications système activées pour le nouvel utilisateur. Si vous ne le définissez pas, le nouvel utilisateur ne contient que l'ensemble minimal d'applications dont le téléphone a besoin généralement un explorateur de fichiers, un clavier téléphonique, des contacts et des SMS.
Suivre le cycle de vie des utilisateurs
Votre DPC (s'il s'agit d'un administrateur de l'appareil entièrement géré) pourrait trouver utile de
lorsque les utilisateurs secondaires changent. Pour exécuter des tâches de suivi après des modifications, remplacez
ces méthodes de rappel dans la sous-classe DeviceAdminReceiver
de votre DPC:
onUserStarted()
- Appelée après le démarrage d'un utilisateur par le système. Cet utilisateur est peut-être encore
en train de configurer ou
s'exécuter en arrière-plan. Vous pouvez récupérer l'utilisateur à partir de
startedUser
. onUserSwitched()
- Appelée après que le système est passé à un autre utilisateur. Vous pouvez obtenir le nouvel utilisateur
qui s'exécute désormais au premier plan à partir de l'argument
switchedUser
. onUserStopped()
- Appelée après que le système a arrêté un utilisateur, car celui-ci s'est déconnecté, est passé à
nouvel utilisateur (s'il s'agit d'un utilisateur éphémère) ou votre DPC a arrêté l'utilisateur. Vous pouvez obtenir
l'utilisateur à partir de l'argument
stoppedUser
. onUserAdded()
- Appelée lorsque le système ajoute un utilisateur. En général, les utilisateurs
secondaires ne sont pas
entièrement configuré lorsque votre DPC reçoit le rappel. Vous pouvez obtenir
l'utilisateur à partir du
l'argument
newUser
. onUserRemoved()
- Appelée après la suppression d'un utilisateur par le système. Comme cet utilisateur a déjà été supprimé,
vous ne pouvez pas accéder à l'utilisateur représenté par l'argument
removedUser
.
Pour savoir quand le système place un utilisateur au premier plan ou renvoie un utilisateur vers la
en arrière-plan, les applications peuvent enregistrer un récepteur
ACTION_USER_FOREGROUND
et
Annonces ACTION_USER_BACKGROUND
.
Découvrir les utilisateurs
L'administrateur d'un appareil entièrement géré peut appeler tous les utilisateurs secondaires
DevicePolicyManager.getSecondaryUsers()
Résultats
inclure tous les utilisateurs secondaires
ou éphémères créés par l'administrateur. Les résultats ont également
tout utilisateur secondaire (ou invité) qu'une personne utilisant l'appareil pourrait
que vous avez créés. Les résultats n'incluent pas les profils professionnels, car ils ne le sont pas
les utilisateurs secondaires. L'exemple suivant montre comment utiliser cette méthode:
Kotlin
// The device is stored for the night. Stop all running secondary users. dpm.getSecondaryUsers(adminName).forEach { dpm.stopUser(adminName, it) }
Java
// The device is stored for the night. Stop all running secondary users. for (UserHandle user : dpm.getSecondaryUsers(adminName)) { dpm.stopUser(adminName, user); }
Voici d'autres méthodes que vous pouvez appeler pour connaître l'état des utilisateurs secondaires:
DevicePolicyManager.isEphemeralUser()
- Appelez cette méthode depuis l'administrateur d'un utilisateur secondaire pour savoir s'il s'agit d'un utilisateur éphémère.
DevicePolicyManager.isAffiliatedUser()
- Appelez cette méthode depuis l'administrateur d'un utilisateur secondaire pour savoir si cet utilisateur est affilié à l'utilisateur principal. Pour en savoir plus sur l'affiliation, consultez la page DPC. coordination ci-dessous.
Gestion des utilisateurs
Si vous souhaitez gérer entièrement le cycle de vie des utilisateurs, vous pouvez appeler des API de contrôler précisément quand et comment l'appareil change d'utilisateur. Par exemple : supprimer un compte utilisateur lorsqu'un appareil n'a pas été utilisé pendant un certain temps ou vous pouvez envoyer les commandes non envoyées à un serveur avant la fin de la journée de travail d'une personne.
Se déconnecter
Android 9.0 a ajouté un bouton de déconnexion à l'écran de verrouillage afin qu'une personne utilisant le l'appareil peut mettre fin à sa session. Lorsque vous appuyez sur le bouton, le système arrête l'utilisateur secondaire, supprime l'utilisateur s'il est éphémère, tandis que l'utilisateur principal revient au premier plan. Android masque le bouton lorsque l'utilisateur principal se trouve dans le au premier plan, car l'utilisateur principal ne peut pas se déconnecter.
Android n'affiche pas le bouton "Terminer la session" par défaut, mais votre administrateur (d'un
entièrement géré) peuvent l'activer en appelant
DevicePolicyManager.setLogoutEnabled()
Si vous avez besoin de
confirmer l'état actuel du bouton, appeler
DevicePolicyManager.isLogoutEnabled()
L'administrateur d'un utilisateur secondaire peut déconnecter l'utilisateur et renvoyer
à l'utilisateur principal. Vérifiez tout d'abord que l'utilisateur secondaire et l'utilisateur principal
puis appelez DevicePolicyManager.logoutUser()
. Si
si l'utilisateur déconnecté est un utilisateur éphémère, le système s'arrête, puis supprime
utilisateur.
Changer d'utilisateur
Pour passer à un autre utilisateur secondaire, l'administrateur d'un appareil entièrement géré peut
appelez DevicePolicyManager.switchUser()
. Pour plus de commodité,
peut transmettre null
pour passer à l'utilisateur principal.
Arrêter un utilisateur
Pour arrêter un utilisateur secondaire, un DPC qui possède un appareil entièrement géré peut appeler
DevicePolicyManager.stopUser()
Si l'utilisateur arrêté est un
utilisateur éphémère, l'utilisateur est arrêté, puis supprimé.
Dans la mesure du possible, nous vous recommandons d'arrêter les utilisateurs afin de rester en dessous de la le nombre maximal d'utilisateurs en cours d'exécution.
Supprimer un espace utilisateur
Pour supprimer définitivement un utilisateur secondaire, un DPC peut appeler l'un des éléments suivants
Méthodes DevicePolicyManager
:
- Un administrateur d'un appareil entièrement géré peut appeler
removeUser()
. - Un administrateur de l'utilisateur secondaire peut appeler
wipeData()
.
Le système supprime les utilisateurs éphémères lorsqu'ils sont déconnectés, arrêtés ou basculent à l'écart.
Désactiver l'interface utilisateur par défaut
Si votre DPC fournit une interface utilisateur pour gérer les utilisateurs, vous pouvez désactiver l'application intégrée d'Android
une interface multi-utilisateur. Pour ce faire, appelez
DevicePolicyManager.setLogoutEnabled()
et en ajoutant la
Restriction DISALLOW_USER_SWITCH
telle qu'indiquée dans les
l'exemple suivant:
Kotlin
// Explicitly disallow logging out using Android UI (disabled by default). dpm.setLogoutEnabled(adminName, false) // Disallow switching users in Android's UI. This DPC can still // call switchUser() to manage users. dpm.addUserRestriction(adminName, UserManager.DISALLOW_USER_SWITCH)
Java
// Explicitly disallow logging out using Android UI (disabled by default). dpm.setLogoutEnabled(adminName, false); // Disallow switching users in Android's UI. This DPC can still // call switchUser() to manage users. dpm.addUserRestriction(adminName, UserManager.DISALLOW_USER_SWITCH);
La personne qui utilise l'appareil ne peut pas ajouter d'utilisateurs secondaires avec l'interface utilisateur intégrée d'Android
car les administrateurs d'appareils entièrement gérés ajoutent automatiquement
Restriction utilisateur DISALLOW_ADD_USER
.
Messages de session
Lorsque la personne qui utilise un appareil passe à un nouvel utilisateur, Android affiche un panneau pour mettez l'interrupteur en surbrillance. Android affiche les messages suivants:
- Message "Start-user-session" qui s'affiche lorsque l'appareil passe à un appareil secondaire de l'utilisateur principal.
- Message de session utilisateur final affiché lorsque l'appareil revient à l'utilisateur principal d'un utilisateur secondaire.
Le système n'affiche pas ces messages lorsqu'il passe d'un compte utilisateur secondaire à un autre.
Étant donné que les messages peuvent ne pas convenir à toutes les situations, vous pouvez modifier le texte de ces messages. Par exemple, si votre solution utilise des clés de chiffrement session, vous pouvez le refléter dans des messages de type: Arrêt du navigateur session et suppression des données personnelles...
Le système affiche le message pendant quelques secondes seulement, de sorte que chaque message
doit être une phrase courte et claire. Pour personnaliser les messages, votre administrateur peut appeler
les méthodes DevicePolicyManager
.
setStartUserSessionMessage()
et
setEndUserSessionMessage()
, comme indiqué dans
l'exemple suivant:
Kotlin
// Short, easy-to-read messages shown at the start and end of a session. // In your app, store these strings in a localizable resource. internal val START_USER_SESSION_MESSAGE = "Starting guest session…" internal val END_USER_SESSION_MESSAGE = "Stopping & clearing data…" // ... dpm.setStartUserSessionMessage(adminName, START_USER_SESSION_MESSAGE) dpm.setEndUserSessionMessage(adminName, END_USER_SESSION_MESSAGE)
Java
// Short, easy-to-read messages shown at the start and end of a session. // In your app, store these strings in a localizable resource. private static final String START_USER_SESSION_MESSAGE = "Starting guest session…"; private static final String END_USER_SESSION_MESSAGE = "Stopping & clearing data…"; // ... dpm.setStartUserSessionMessage(adminName, START_USER_SESSION_MESSAGE); dpm.setEndUserSessionMessage(adminName, END_USER_SESSION_MESSAGE);
Transmettez null
pour supprimer vos messages personnalisés et revenir aux paramètres par défaut d'Android
messages. Pour vérifier le texte du message actuel, appelez
getStartUserSessionMessage()
ou
getEndUserSessionMessage()
Votre DPC doit définir des messages localisés. pour les paramètres régionaux actuels de l'utilisateur. Vous devez également modifier les messages modifications des paramètres régionaux de l'utilisateur:
Kotlin
override fun onReceive(context: Context?, intent: Intent?) { // Added the <action android:name="android.intent.action.LOCALE_CHANGED" /> // intent filter for our DeviceAdminReceiver subclass in the app manifest file. if (intent?.action === ACTION_LOCALE_CHANGED) { // Android's resources return a string suitable for the new locale. getManager(context).setStartUserSessionMessage( getWho(context), context?.getString(R.string.start_user_session_message)) getManager(context).setEndUserSessionMessage( getWho(context), context?.getString(R.string.end_user_session_message)) } super.onReceive(context, intent) }
Java
public void onReceive(Context context, Intent intent) { // Added the <action android:name="android.intent.action.LOCALE_CHANGED" /> // intent filter for our DeviceAdminReceiver subclass in the app manifest file. if (intent.getAction().equals(ACTION_LOCALE_CHANGED)) { // Android's resources return a string suitable for the new locale. getManager(context).setStartUserSessionMessage( getWho(context), context.getString(R.string.start_user_session_message)); getManager(context).setEndUserSessionMessage( getWho(context), context.getString(R.string.end_user_session_message)); } super.onReceive(context, intent); }
Coordination DPC
La gestion des utilisateurs secondaires a généralement besoin de deux instances de votre DPC, une qui possède l'appareil entièrement géré, tandis que l'autre possède l'utilisateur secondaire. Lors de la création d'un nouvel utilisateur, l'administrateur de l'appareil entièrement géré définit une autre instance en tant qu'administrateur du nouvel utilisateur.
Utilisateurs affiliés
Certaines des API présentées dans ce guide du développeur ne fonctionnent que lorsque les utilisateurs secondaires sont affiliés ; Comme Android désactive certaines fonctionnalités, (journalisation réseau, par exemple) lorsque vous ajoutez des utilisateurs secondaires non affiliés à l'appareil, vous devez affilier les utilisateurs dès que possible. Consultez l'exemple dans Configuration ci-dessous.
Configuration
Configurez de nouveaux utilisateurs secondaires (à partir du DPC qui possède l'utilisateur secondaire) avant
permettant aux gens de les utiliser. Vous pouvez effectuer cette configuration depuis la
Rappel DeviceAdminReceiver.onEnabled()
. Si vous aviez déjà
définir des extras d'administrateur dans l'appel à createAndManageUser()
, vous pouvez obtenir
de l'argument intent
. L'exemple suivant montre une affiliation DPC
un nouvel utilisateur secondaire dans le rappel:
Kotlin
override fun onEnabled(context: Context?, intent: Intent?) { super.onEnabled(context, intent) // Get the affiliation ID (our DPC previously put in the extras) and // set the ID for this new secondary user. intent?.getStringExtra(AFFILIATION_ID_KEY)?.let { val dpm = getManager(context) dpm.setAffiliationIds(getWho(context), setOf(it)) } // Continue setup of the new secondary user ... }
Java
public void onEnabled(Context context, Intent intent) { // Get the affiliation ID (our DPC previously put in the extras) and // set the ID for this new secondary user. String affiliationId = intent.getStringExtra(AFFILIATION_ID_KEY); if (affiliationId != null) { DevicePolicyManager dpm = getManager(context); dpm.setAffiliationIds(getWho(context), new HashSet<String>(Arrays.asList(affiliationId))); } // Continue setup of the new secondary user ... }
RPC entre les DPC
Même si les deux instances DPC s'exécutent sous des utilisateurs distincts, les DPC
qui possèdent l’appareil et les utilisateurs
secondaires peuvent communiquer entre eux.
Étant donné que l'appel d'un autre service DPC dépasse les limites de l'utilisateur, votre DPC ne peut pas
appelez bindService()
comme vous le feriez normalement
Android. Pour s'associer à un service exécuté dans
un autre utilisateur, appeler
DevicePolicyManager.bindDeviceAdminServiceAsUser()
Votre DPC ne peut être lié qu'à des services exécutés dans les utilisateurs renvoyés par
DevicePolicyManager.getBindDeviceAdminTargetUsers()
L'exemple suivant montre comment l'administrateur d'une liaison d'utilisateur secondaire est lié à l'administrateur
de l'appareil entièrement géré:
Kotlin
// From a secondary user, the list contains just the primary user. dpm.getBindDeviceAdminTargetUsers(adminName).forEach { // Set up the callbacks for the service connection. val intent = Intent(mContext, FullyManagedDeviceService::class.java) val serviceconnection = object : ServiceConnection { override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) { // Call methods on service ... } override fun onServiceDisconnected(componentName: ComponentName) { // Clean up or reconnect if needed ... } } // Bind to the service as the primary user [it]. val bindSuccessful = dpm.bindDeviceAdminServiceAsUser(adminName, intent, serviceconnection, Context.BIND_AUTO_CREATE, it) }
Java
// From a secondary user, the list contains just the primary user. List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(adminName); if (targetUsers.isEmpty()) { // If the users aren't affiliated, the list doesn't contain any users. return; } // Set up the callbacks for the service connection. Intent intent = new Intent(mContext, FullyManagedDeviceService.class); ServiceConnection serviceconnection = new ServiceConnection() { @Override public void onServiceConnected( ComponentName componentName, IBinder iBinder) { // Call methods on service ... } @Override public void onServiceDisconnected(ComponentName componentName) { // Clean up or reconnect if needed ... } }; // Bind to the service as the primary user. UserHandle primaryUser = targetUsers.get(0); boolean bindSuccessful = dpm.bindDeviceAdminServiceAsUser( adminName, intent, serviceconnection, Context.BIND_AUTO_CREATE, primaryUser);
Ressources supplémentaires
Pour en savoir plus sur les appareils dédiés, consultez les documents suivants:
- La présentation des appareils dédiés présente les appareils dédiés.
- La section Mode tâches verrouillées explique comment effectuer les actions suivantes : verrouiller un appareil dédié sur une seule application ou un seul ensemble d'applications.
- Livre de recettes pour les appareils dédiés avec Autres exemples pour limiter l'utilisation d'appareils dédiés et améliorer l'expérience utilisateur expérience.