Paramétrer les configurations gérées

Si vous développez des applications pour le marché des entreprises, vous devrez peut-être répondre à des exigences particulières définies par les règles d'une organisation. Les configurations gérées, auparavant appelées restrictions d'application, permettent à l'administrateur informatique de l'organisation de spécifier à distance les paramètres des applications. Cette fonctionnalité est particulièrement utile pour les applications approuvées par l'organisation qui sont déployées dans un profil professionnel.

Par exemple, une organisation peut exiger que les applications approuvées permettent à l'administrateur informatique de:

  • Autoriser ou bloquer des URL pour un navigateur Web
  • Indiquez si une application est autorisée à synchroniser du contenu via le réseau mobile ou uniquement via le Wi-Fi.
  • Configurer les paramètres de messagerie de l'application

Ce guide explique comment implémenter des paramètres de configuration gérée dans votre application. Pour afficher des exemples d'applications avec une configuration gérée, consultez ManagedConfigurations. Si vous êtes développeur de solutions de gestion de la mobilité en entreprise (EMM), consultez le guide de l'API Android Management.

Remarque:Pour des raisons historiques, ces paramètres de configuration sont appelés restrictions et sont implémentés avec des fichiers et des classes qui utilisent ce terme (comme RestrictionsManager). Toutefois, ces restrictions peuvent en réalité implémenter un large éventail d'options de configuration, et pas seulement des restrictions sur les fonctionnalités de l'application.

Présentation de la configuration à distance

Les applications définissent les options de configuration gérées qui peuvent être définies à distance par un administrateur informatique. Il s'agit de paramètres arbitraires qui peuvent être modifiés par un fournisseur de configuration géré. Si votre application s'exécute dans un profil professionnel, l'administrateur informatique peut modifier sa configuration gérée.

Le fournisseur de configurations gérées est une autre application exécutée sur le même appareil. Cette application est généralement contrôlée par l'administrateur informatique. L'administrateur informatique communique les modifications de configuration à l'application du fournisseur de configuration gérée. Cette application, à son tour, modifie les configurations de votre application.

Pour fournir des configurations gérées en externe:

  • Déclarez les configurations gérées dans le fichier manifeste de votre application. Cela permet à l'administrateur informatique de lire les configurations de l'application via les API Google Play.
  • Chaque fois que l'application reprend, utilisez l'objet RestrictionsManager pour vérifier les configurations gérées actuelles, et modifiez l'UI et le comportement de votre application pour qu'ils soient conformes à ces configurations.
  • Écoutez l'intent ACTION_APPLICATION_RESTRICTIONS_CHANGED. Lorsque vous recevez cette diffusion, vérifiez RestrictionsManager pour connaître les configurations gérées actuelles et apportez les modifications nécessaires au comportement de votre application.

Définir des configurations gérées

Votre application peut prendre en charge n'importe quelle configuration gérée que vous souhaitez définir. Vous déclarez les configurations gérées de l'application dans un fichier de configurations gérées, puis déclarez le fichier de configurations dans le fichier manifeste. La création d'un fichier de configuration permet aux autres applications d'examiner les configurations gérées fournies par votre application. Les partenaires EMM peuvent lire les configurations de votre application à l'aide des API Google Play.

Pour définir les options de configuration à distance de votre application, placez l'élément suivant dans l'élément <application> de votre fichier manifeste:

<meta-data android:name="android.content.APP_RESTRICTIONS"
    android:resource="@xml/app_restrictions" />

Créez un fichier nommé app_restrictions.xml dans le répertoire res/xml de votre application. La structure de ce fichier est décrite dans la documentation de référence de RestrictionsManager. Le fichier comporte un seul élément <restrictions> de premier niveau, qui contient un élément enfant <restriction> pour chaque option de configuration de l'application.

Remarque:Ne créez pas de versions localisées du fichier de configuration géré. Votre application ne peut avoir qu'un seul fichier de configuration géré. Les configurations seront donc cohérentes pour votre application dans toutes les langues.

Dans un environnement d'entreprise, un EMM utilise généralement le schéma de configuration gérée pour générer une console à distance pour les administrateurs informatiques, afin qu'ils puissent configurer votre application à distance.

Le fournisseur de configuration géré peut interroger l'application pour obtenir des informations sur les configurations disponibles, y compris leur texte de description. Le fournisseur de configurations et l'administrateur informatique peuvent modifier les configurations gérées de votre application à tout moment, même lorsque l'application n'est pas en cours d'exécution.

Par exemple, supposons que votre application puisse être configurée à distance pour lui permettre ou non de télécharger des données via une connexion mobile. Votre application peut comporter un élément <restriction> comme suit:

<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">

  <restriction
    android:key="downloadOnCellular"
    android:title="@string/download_on_cell_title"
    android:restrictionType="bool"
    android:description="@string/download_on_cell_description"
    android:defaultValue="true" />

</restrictions>

Vous utilisez l'attribut android:key de chaque configuration pour lire sa valeur à partir d'un bundle de configuration géré. C'est pourquoi chaque configuration doit avoir une chaîne de clé unique, et cette chaîne ne peut pas être localisée. Il doit être spécifié avec un littéral de chaîne.

Remarque:Dans une application de production, android:title et android:description doivent être extraits d'un fichier de ressources localisé, comme décrit dans la section Localiser avec des ressources.

Une application définit des restrictions à l'aide de bundles dans un bundle_array. Par exemple, une application proposant plusieurs options de connexion VPN peut définir chaque configuration de serveur VPN dans un bundle, avec plusieurs bundles regroupés dans un tableau de bundles:

<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android" >

  <restriction
    android:key="vpn_configuration_list"
    android:restrictionType="bundle_array">
    <restriction
      android:key="vpn_configuration"
      android:restrictionType="bundle">
      <restriction
        android:key="vpn_server"
        android:restrictionType="string"/>
      <restriction
        android:key="vpn_username"
        android:restrictionType="string"/>
      <restriction
        android:key="vpn_password"
        android:restrictionType="string"/>
    </restriction>
  </restriction>

</restrictions>

Les types compatibles pour l'élément android:restrictionType sont répertoriés dans le tableau 1 et documentés dans la documentation de référence pour RestrictionsManager et RestrictionEntry.

Tableau 1. Types d'entrées de restriction et utilisation

Type android:restrictionType Utilisation type
TYPE_BOOLEAN "bool" Valeur booléenne (vrai ou faux).
TYPE_STRING "string" Valeur de chaîne, telle qu'un nom.
TYPE_INTEGER "integer" Entier dont la valeur est comprise entre MIN_VALUE et MAX_VALUE.
TYPE_CHOICE "choice" Valeur de chaîne sélectionnée dans android:entryValues, généralement présentée sous forme de liste à sélection unique.
TYPE_MULTI_SELECT "multi-select" Tableau de chaînes avec des valeurs sélectionnées dans android:entryValues. Utilisez-le pour présenter une liste à sélection multiple dans laquelle plusieurs entrées peuvent être sélectionnées, par exemple pour choisir des titres spécifiques à ajouter à la liste d'autorisation.
TYPE_NULL "hidden" Type de restriction masqué. Utilisez ce type pour les informations qui doivent être transférées, mais qui ne doivent pas être présentées à l'utilisateur dans l'UI. Stocke une seule valeur de chaîne.
TYPE_BUNDLE_ARRAY "bundle_array" Utilisez-le pour stocker des tableaux de restriction bundles. Disponible dans Android 6.0 (niveau d'API 23).

Remarque:Les android:entryValues sont lisibles par machine et ne peuvent pas être localisés. Utilisez android:entries pour présenter des valeurs lisibles qui peuvent être localisées. Chaque entrée doit avoir un indice correspondant dans android:entryValues.

Vérifier les configurations gérées

Votre application n'est pas automatiquement avertie lorsque d'autres applications modifient ses paramètres de configuration. Vous devez plutôt vérifier quelles sont les configurations gérées lorsque votre application démarre ou reprend, et écouter un intent système pour savoir si les configurations changent pendant l'exécution de votre application.

Pour connaître les paramètres de configuration actuels, votre application utilise un objet RestrictionsManager. Votre application doit rechercher les configurations gérées actuelles aux heures suivantes:

Pour obtenir un objet RestrictionsManager, obtenez l'activité actuelle avec getActivity(), puis appelez la méthode Activity.getSystemService() de cette activité:

Kotlin

var myRestrictionsMgr =
        activity?.getSystemService(Context.RESTRICTIONS_SERVICE) as RestrictionsManager

Java

RestrictionsManager myRestrictionsMgr =
    (RestrictionsManager) getActivity()
        .getSystemService(Context.RESTRICTIONS_SERVICE);

Une fois que vous disposez d'un RestrictionsManager, vous pouvez obtenir les paramètres de configuration actuels en appelant sa méthode getApplicationRestrictions():

Kotlin

var appRestrictions: Bundle = myRestrictionsMgr.applicationRestrictions

Java

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

Remarque:Pour plus de commodité, vous pouvez également récupérer les configurations actuelles avec un UserManager en appelant UserManager.getApplicationRestrictions(). Cette méthode se comporte exactement de la même manière que RestrictionsManager.getApplicationRestrictions().

La méthode getApplicationRestrictions() nécessite la lecture à partir du stockage de données. Elle doit donc être utilisée avec parcimonie. N'appelez pas cette méthode chaque fois que vous devez connaître la configuration actuelle. Vous devez plutôt l'appeler une fois au démarrage ou à la reprise de votre application, et mettre en cache le bundle de configurations gérées récupéré. Écoutez ensuite l'intent ACTION_APPLICATION_RESTRICTIONS_CHANGED pour savoir si la configuration change lorsque votre application est active, comme décrit dans la section Écouter les modifications de configuration gérées.

Lire et appliquer des configurations gérées

La méthode getApplicationRestrictions() renvoie un Bundle contenant une paire clé-valeur pour chaque configuration définie. Les valeurs sont toutes de type Boolean, int, String et String[]. Une fois que vous disposez des configurations gérées Bundle, vous pouvez vérifier les paramètres de configuration actuels à l'aide des méthodes Bundle standards pour ces types de données, telles que getBoolean() ou getString().

Remarque:La Bundle des configurations gérées contient un élément pour chaque configuration définie explicitement par un fournisseur de configurations gérées. Toutefois, vous ne pouvez pas supposer qu'une configuration sera présente dans le groupe simplement parce que vous avez défini une valeur par défaut dans le fichier XML des configurations gérées.

C'est à votre application de prendre les mesures appropriées en fonction des paramètres de configuration gérés actuels. Par exemple, si votre application dispose d'une configuration indiquant si elle peut télécharger des données via une connexion mobile et que vous constatez que la configuration est définie sur false, vous devez désactiver le téléchargement de données, sauf lorsque l'appareil est connecté au Wi-Fi, comme indiqué dans l'exemple de code suivant:

Kotlin

val appCanUseCellular: Boolean =
        if (appRestrictions.containsKey("downloadOnCellular")) {
            appRestrictions.getBoolean("downloadOnCellular")
        } else {
            // cellularDefault is a boolean using the restriction's default value
            cellularDefault
        }

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}

Java

boolean appCanUseCellular;

if (appRestrictions.containsKey("downloadOnCellular")) {
    appCanUseCellular = appRestrictions.getBoolean("downloadOnCellular");
} else {
    // cellularDefault is a boolean using the restriction's default value
    appCanUseCellular = cellularDefault;
}

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}

Pour appliquer plusieurs restrictions imbriquées, lisez l'entrée de restriction bundle_array en tant que collection d'objets Parcelable et castez-la en tant que Bundle. Dans cet exemple, les données de configuration de chaque VPN sont analysées et utilisées pour créer une liste de choix de connexion au serveur:

Kotlin

// VpnConfig is a sample class used store config data, not defined
val vpnConfigs = mutableListOf<VpnConfig>()

val parcelables: Array<out Parcelable>? =
        appRestrictions.getParcelableArray("vpn_configuration_list")

if (parcelables?.isNotEmpty() == true) {
    // iterate parcelables and cast as bundle
    parcelables.map { it as Bundle }.forEach { vpnConfigBundle ->
        // parse bundle data and store in VpnConfig array
        vpnConfigs.add(VpnConfig()
                .setServer(vpnConfigBundle.getString("vpn_server"))
                .setUsername(vpnConfigBundle.getString("vpn_username"))
                .setPassword(vpnConfigBundle.getString("vpn_password")))
    }
}

if (vpnConfigs.isNotEmpty()) {
    // ...choose a VPN configuration or prompt user to select from list
}

Java

// VpnConfig is a sample class used store config data, not defined
List<VpnConfig> vpnConfigs = new ArrayList<>();

Parcelable[] parcelables =
    appRestrictions.getParcelableArray("vpn_configuration_list");

if (parcelables != null && parcelables.length > 0) {
    // iterate parcelables and cast as bundle
    for (int i = 0; i < parcelables.length; i++) {
        Bundle vpnConfigBundle = (Bundle) parcelables[i];
        // parse bundle data and store in VpnConfig array
        vpnConfigs.add(new VpnConfig()
            .setServer(vpnConfigBundle.getString("vpn_server"))
            .setUsername(vpnConfigBundle.getString("vpn_username"))
            .setPassword(vpnConfigBundle.getString("vpn_password")));
    }
}

if (!vpnConfigs.isEmpty()) {
    // ...choose a VPN configuration or prompt user to select from list
}

Écouter les modifications de configuration gérées

Chaque fois que les configurations gérées d'une application sont modifiées, le système déclenche l'intent ACTION_APPLICATION_RESTRICTIONS_CHANGED. Votre application doit écouter cet intent afin que vous puissiez modifier son comportement lorsque les paramètres de configuration changent.

Remarque:L'intent ACTION_APPLICATION_RESTRICTIONS_CHANGED n'est envoyé qu'aux écouteurs enregistrés de manière dynamique, et non aux écouteurs déclarés dans le fichier manifeste de l'application.

Le code suivant montre comment enregistrer dynamiquement un broadcast receiver pour cet intent:

Kotlin

val restrictionsFilter = IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED)

val restrictionsReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {

        // Get the current configuration bundle
        val appRestrictions = myRestrictionsMgr.applicationRestrictions

        // Check current configuration settings, change your app's UI and
        // functionality as necessary.
    }
}

registerReceiver(restrictionsReceiver, restrictionsFilter)

Java

IntentFilter restrictionsFilter =
    new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);

BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
  @Override public void onReceive(Context context, Intent intent) {

    // Get the current configuration bundle
    Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

    // Check current configuration settings, change your app's UI and
    // functionality as necessary.
  }
};

registerReceiver(restrictionsReceiver, restrictionsFilter);

Remarque:En règle générale, votre application n'a pas besoin d'être avertie des modifications de configuration lorsqu'elle est mise en veille. Vous devez plutôt annuler l'enregistrement de votre broadcast receiver lorsque l'application est mise en pause. Lorsque l'application reprend, vous devez d'abord vérifier les configurations gérées actuelles (comme indiqué dans la section Vérifier les configurations gérées), puis enregistrer votre broadcast receiver pour vous assurer d'être informé des modifications de configuration qui se produisent lorsque l'application est active.

Envoyer des commentaires sur la configuration gérée aux fournisseurs EMM

Une fois que vous avez appliqué des modifications de configuration gérées à votre application, il est recommandé d'en informer les EMM. Android est compatible avec une fonctionnalité appelée états d'application avec clé, que vous pouvez utiliser pour envoyer des commentaires chaque fois que votre application tente d'appliquer des modifications de configuration gérées. Ces commentaires peuvent servir de confirmation que votre application a défini des configurations gérées avec succès ou peuvent inclure un message d'erreur si votre application n'a pas réussi à appliquer les modifications spécifiées.

Les fournisseurs EMM peuvent récupérer ces commentaires et les afficher dans leurs consoles pour que les administrateurs informatiques puissent les consulter. Pour en savoir plus sur ce sujet, consultez Envoyer des commentaires sur l'application aux fournisseurs EMM, qui inclut un guide détaillé sur l'ajout de la fonctionnalité d'envoi de commentaires à votre application.

Autres exemples de code

L'exemple ManagedConfigurations illustre davantage l'utilisation des API abordées sur cette page.

Ajouter des applications à la liste d'autorisation/de blocage dans le profil personnel

Les plates-formes de téléchargement d'applications tierces peuvent souhaiter utiliser des configurations gérées pour disposer d'un moyen fiable d'appliquer une liste de blocage ou d'autorisation d'applications à la fois au profil personnel et à la fonctionnalité grand public Espace privé, qui est un espace personnel supplémentaire dans lequel les utilisateurs peuvent conserver leurs applications sensibles. Si vous développez une plate-forme de téléchargement d'applications pour les entreprises et que vous souhaitez utiliser cette fonctionnalité, remplissez ce formulaire pour manifester votre intérêt et sélectionnez Intérêt pour la liste d'autorisation de plate-forme de téléchargement d'applications tierce comme Motif de la réponse.