Profils professionnels

La plate-forme Android permet aux appareils de disposer de profils professionnels (parfois appelés profils gérés). Un profil professionnel est contrôlé par un administrateur informatique et les fonctionnalités qui lui sont disponibles sont définies séparément de celles du profil principal de l'utilisateur. Cette approche permet aux organisations de contrôler l'environnement dans lequel les applications et les données spécifiques à l'entreprise s'exécutent sur l'appareil d'un utilisateur, tout en laissant celui-ci utiliser ses applications et profils personnels.

Cette leçon vous explique comment modifier votre application pour qu'elle fonctionne de manière fiable sur un appareil doté d'un profil professionnel. Vous n'avez rien d'autre à faire que les bonnes pratiques ordinaires de développement d'applications. Cependant, certaines de ces bonnes pratiques deviennent particulièrement importantes sur les appareils dotés de profils professionnels. Ce document met en évidence les problèmes dont vous devez être conscient.

Présentation

Souvent, les utilisateurs souhaitent utiliser leurs appareils personnels dans un environnement d'entreprise. Cette situation peut exposer les entreprises à un dilemme. Si l'utilisateur peut utiliser son propre appareil, l'organisation doit s'inquiéter que des informations confidentielles (telles que les e-mails et les contacts des employés) se trouvent sur un appareil qu'elle ne contrôle pas.

Pour remédier à cette situation, Android 5.0 (niveau d'API 21) permet aux organisations de configurer des profils professionnels. Si un appareil dispose d'un profil professionnel, les paramètres de ce profil sont contrôlés par l'administrateur informatique. L'administrateur informatique peut choisir les applications autorisées pour ce profil et contrôler uniquement les fonctionnalités de l'appareil disponibles pour le profil.

Si un appareil dispose d'un profil professionnel, cela a des conséquences pour les applications qui s'y exécutent, quel que soit le profil sous lequel l'application s'exécute:

  • Par défaut, la plupart des intents ne passent pas d'un profil à l'autre. Si une application exécutée sur un profil déclenche un intent, il n'existe aucun gestionnaire pour cet intent sur ce profil et l'intent n'est pas autorisé à passer à l'autre profil en raison de restrictions liées au profil. La requête échoue et l'application peut s'arrêter de manière inattendue.
  • L'administrateur informatique du profil peut limiter les applications système disponibles dans le profil professionnel. Cette restriction peut également entraîner l'absence de gestionnaire pour certains intents courants sur le profil professionnel.
  • Étant donné que les profils personnel et professionnel ont des zones de stockage distinctes, un URI de fichier valide sur un profil ne l'est pas sur l'autre. Tout intent déclenché sur un profil peut être géré sur l'autre (en fonction des paramètres du profil). Il est donc dangereux de joindre des URI de fichiers à des intents.

Empêcher les intents ayant échoué

Sur un appareil doté d'un profil professionnel, des restrictions s'appliquent à la possibilité de passer d'un profil à un autre pour les intents. Dans la plupart des cas, lorsqu'un intent est déclenché, il est géré sur le profil où il est déclenché. S'il n'existe aucun gestionnaire pour l'intent sur ce profil, l'intent n'est pas géré et l'application qui l'a déclenché peut s'arrêter de manière inattendue, même s'il existe un gestionnaire pour l'intent sur l'autre profil.

L'administrateur de profil peut choisir les intents autorisés à passer d'un profil à un autre. Étant donné que l'administrateur informatique prend cette décision, vous n'avez aucun moyen de savoir à l'avance quels intents sont autorisés à dépasser cette limite. L'administrateur informatique définit cette règle et peut la modifier à tout moment.

Avant que votre application ne démarre une activité, vous devez vérifier que la résolution est appropriée. Vous pouvez vérifier qu'il existe une résolution acceptable en appelant Intent.resolveActivity(). S'il n'existe aucun moyen de résoudre l'intent, la méthode renvoie null. Si la méthode renvoie une valeur non nulle, il existe au moins une façon de résoudre l'intent, qui peut être déclenché sans risque. Dans ce cas, l'intent peut être résolu soit parce qu'il existe un gestionnaire dans le profil actuel, soit parce qu'il est autorisé à passer à un gestionnaire de l'autre profil. (Pour en savoir plus sur la résolution des intents, consultez la section Intents courants.)

Par exemple, si votre application doit définir des minuteurs, elle doit vérifier qu'il existe un gestionnaire valide pour l'intent ACTION_SET_TIMER. Si l'application ne peut pas résoudre l'intent, elle doit prendre les mesures appropriées (par exemple, afficher un message d'erreur).

Kotlin

fun startTimer(message: String, seconds: Int) {

    // Build the "set timer" intent
    val timerIntent = Intent(AlarmClock.ACTION_SET_TIMER).apply {
        putExtra(AlarmClock.EXTRA_MESSAGE, message)
        putExtra(AlarmClock.EXTRA_LENGTH, seconds)
        putExtra(AlarmClock.EXTRA_SKIP_UI, true)
    }

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(packageManager) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent)

    }
}

Java

public void startTimer(String message, int seconds) {

    // Build the "set timer" intent
    Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(getPackageManager()) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent);

    }
}

Partager des fichiers entre plusieurs profils

Parfois, une application doit permettre à d'autres applications d'accéder à ses propres fichiers. Par exemple, une application de galerie d'images peut vouloir partager ses images avec des éditeurs d'images. Il existe deux façons de partager habituellement un fichier: avec un URI de fichier ou un URI de contenu.

Un URI de fichier commence par le préfixe file:, suivi du chemin absolu du fichier dans l'espace de stockage de l'appareil. Toutefois, comme le profil professionnel et le profil personnel utilisent des espaces de stockage distincts, un URI de fichier valide sur un profil ne l'est pas sur l'autre. Cela signifie que si vous associez un URI de fichier à un intent et que cet intent est géré sur l'autre profil, le gestionnaire ne peut pas accéder au fichier.

Vous devez partager les fichiers avec des URI de contenu. Les URI de contenu identifient le fichier d'une manière plus sécurisée et plus facile à partager. L'URI de contenu contient le chemin d'accès au fichier, mais également l'autorité qui fournit le fichier, et un numéro d'identification qui identifie le fichier. Vous pouvez générer un ID de contenu pour n'importe quel fichier à l'aide d'un FileProvider. Vous pouvez ensuite partager cet ID de contenu avec d'autres applications (même sur l'autre profil). Le destinataire peut utiliser Content ID pour accéder au fichier.

Par exemple, voici comment obtenir l'URI de contenu pour un URI de fichier spécifique:

Kotlin

// Open File object from its file URI
val fileToShare = File(fileUriToShare)

val contentUriToShare: Uri = FileProvider.getUriForFile(
        context,
        "com.example.myapp.fileprovider",
        fileToShare
)

Java

// Open File object from its file URI
File fileToShare = new File(fileUriToShare);

Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
        "com.example.myapp.fileprovider", fileToShare);

Lorsque vous appelez la méthode getUriForFile(), vous devez inclure l'autorité du fournisseur de fichiers (dans cet exemple, "com.example.myapp.fileprovider"), qui est spécifiée dans l'élément <provider> du fichier manifeste de votre application. Pour en savoir plus sur le partage de fichiers avec des URI de contenu, consultez la section Partager des fichiers.

Écouter les notifications

Une application fournit généralement une sous-classe NotificationListenerService pour recevoir des rappels du système concernant les modifications apportées aux notifications. Les appareils dotés de profils professionnels peuvent affecter le fonctionnement de NotificationListenerService avec votre application.

Dans un profil professionnel

Vous ne pouvez pas utiliser de NotificationListenerService à partir d'une application exécutée dans le profil professionnel. Lorsque votre application s'exécute dans un profil professionnel, le système ignore le NotificationListenerService de votre application. Toutefois, les applications exécutées dans le profil personnel peuvent écouter les notifications.

Dans un profil personnel

Lorsque votre application s'exécute dans le profil personnel, vous ne recevrez peut-être pas de notifications pour les applications exécutées dans le profil professionnel. Par défaut, toutes les applications de profil personnel reçoivent des rappels, mais un administrateur informatique peut ajouter une ou plusieurs applications de profil personnel à la liste d'autorisation et les autoriser à écouter les modifications des notifications. Le système bloque ensuite les applications non autorisées. Sous Android 8.0 (niveau d'API 26) ou version ultérieure, un outil de contrôle des règles relatives aux appareils (DPC) qui gère un profil professionnel peut empêcher votre application d'écouter les notifications de ce profil à l'aide de la méthode DevicePolicyManager setPermittedCrossProfileNotificationListeners(). Votre application reçoit toujours des rappels concernant les notifications publiées dans le profil personnel.

Tester la compatibilité de votre application avec les profils professionnels

Nous vous recommandons de tester votre application dans un environnement de profil professionnel pour détecter les problèmes qui entraîneraient l'échec de votre application sur un appareil doté de profils professionnels. En particulier, les tests sur un appareil avec profil professionnel permettent de s'assurer que votre application gère correctement les intents: ne déclenchez pas d'intents qui ne peuvent pas être gérés, n'associez pas d'URI qui ne fonctionnent pas entre les profils, etc.

Nous avons fourni une application exemple, TestDPC, que vous pouvez utiliser pour configurer un profil professionnel sur un appareil Android équipé d'Android 5.0 (niveau d'API 21) ou version ultérieure. Cette application vous offre un moyen simple de tester votre application dans un environnement de profil professionnel. Vous pouvez également utiliser cette application pour configurer le profil professionnel comme suit:

  • Spécifier les applications par défaut disponibles sur le profil géré
  • Configurer les intents autorisés à passer d'un profil à l'autre

Si vous installez manuellement une application sur un appareil disposant d'un profil professionnel via un câble USB, elle est installée à la fois sur le profil personnel et sur le profil professionnel. Une fois l'application installée, vous pouvez la tester dans les conditions suivantes:

  • Si un intent est normalement géré par une application par défaut (par exemple, l'application d'appareil photo), essayez de désactiver cette application par défaut sur le profil professionnel, puis vérifiez qu'elle gère cela de manière appropriée.
  • Si vous déclenchez un intent s'attendant à être géré par une autre application, essayez d'activer et de désactiver l'autorisation de cet intent pour passer d'un profil à un autre. Vérifiez que l'application se comporte correctement dans les deux cas. Si l'intent n'est pas autorisé à traverser des profils, vérifiez le comportement de l'application à la fois lorsqu'il existe un gestionnaire approprié sur le profil de l'application et lorsqu'il n'y en a pas. Par exemple, si votre application déclenche un intent lié à une carte, essayez chacun des scénarios suivants :
    • L'appareil permet aux intents de carte de passer d'un profil à l'autre, et il existe un gestionnaire approprié sur l'autre profil (le profil sur lequel l'application n'est pas exécutée).
    • L'appareil n'autorise pas les intents de carte à croiser entre les profils, mais il existe un gestionnaire approprié sur le profil de l'application.
    • L'appareil n'autorise pas le croisement des intents de carte entre les profils, et il n'existe aucun gestionnaire approprié pour les intents de carte sur le profil de l'appareil.
  • Si vous associez du contenu à un intent, vérifiez qu'il se comporte correctement lorsqu'il est géré dans le profil de l'application et lorsqu'il passe d'un profil à l'autre.

Tester les profils professionnels: conseils et astuces

Voici quelques astuces qui peuvent vous être utiles lors des tests sur un appareil avec un profil professionnel.

  • Comme indiqué, lorsque vous chargez une application indépendamment sur un appareil de profil professionnel, elle est installée sur les deux profils. Si vous le souhaitez, vous pouvez supprimer l'application d'un profil et la laisser de l'autre.
  • La plupart des commandes du gestionnaire d'activités disponibles dans l'interface système Android Debug Bridge (adb) prennent en charge l'indicateur --user, qui vous permet de spécifier l'utilisateur sous lequel vous souhaitez exécuter l'application. En spécifiant un utilisateur, vous pouvez choisir d'exécuter l'application en tant qu'utilisateur principal non géré ou en tant que profil professionnel. Pour en savoir plus, consultez la section Commandes shell ADB.
  • Pour rechercher les utilisateurs actifs sur un appareil, exécutez la commande list users du gestionnaire de packages adb. Le premier chiffre de la chaîne de sortie est l'ID utilisateur, que vous pouvez utiliser avec l'option --user. Pour en savoir plus, consultez la section Commandes shell ADB.

Par exemple, pour trouver les utilisateurs d'un appareil, exécutez la commande suivante:

$ adb shell pm list users
UserInfo{0:Drew:13} running
UserInfo{10:Work profile:30} running

Dans ce cas, l'utilisateur principal("Drew") a l'ID utilisateur 0, et le profil professionnel a l'ID utilisateur 10. Pour exécuter une application dans le profil professionnel, utilisez une commande comme celle-ci:

$ adb shell am start --user 10 \
-n "com.example.myapp/com.example.myapp.testactivity" \
-a android.intent.action.MAIN -c android.intent.category.LAUNCHER