Paramétrer les configurations gérées

Si vous développez des applications pour les grandes 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 autorisent l'administrateur informatique à:

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

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

Remarque:Pour des raisons historiques, ces paramètres de configuration sont appelés restrictions. Ils sont implémentés avec des fichiers et des classes qui utilisent ce terme (par exemple,RestrictionsManager). Cependant, 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ée qu'un administrateur informatique peut définir à distance. Il s'agit de paramètres arbitraires pouvant être modifiés par un fournisseur de configuration gérée. Si votre application s'exécute dans un profil professionnel, l'administrateur informatique peut modifier la configuration gérée de votre application.

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, qui, à 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 est réactivée, utilisez l'objet RestrictionsManager pour vérifier les configurations gérées actuelles, et modifier l'interface utilisateur 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 le RestrictionsManager pour connaître les configurations gérées actuelles et apporter les modifications nécessaires au comportement de votre application.

Définir les configurations gérées

Votre application est compatible avec toutes les configurations gérées que vous souhaitez définir. Vous devez déclarer les configurations gérées de l'application dans un fichier de configuration géré et le déclarer dans le fichier manifeste. La création d'un fichier de configuration permet à d'autres applications d'examiner les configurations gérées fournies par votre application. Les partenaires EMM peuvent consulter 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 sur 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 tous les paramètres régionaux.

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

Le fournisseur de configuration gérée peut interroger l'application pour obtenir des détails sur les configurations disponibles pour l'application, 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 autoriser ou interdire le téléchargement de données via une connexion mobile. Votre application peut comporter un élément <restriction> comme celui-ci:

<?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 pouvez utiliser 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 comporter une chaîne de clé unique, et la chaîne ne peut pas être localisée. Elle doit être spécifiée à l'aide d'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és, 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 avec plusieurs options de connexion VPN peut définir chaque configuration de serveur VPN dans un élément bundle, avec plusieurs groupes 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 acceptés 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 standard
TYPE_BOOLEAN "bool" Valeur booléenne, "true" ou "false".
TYPE_STRING "string" Valeur de chaîne, telle qu'un nom.
TYPE_INTEGER "integer" Entier avec une valeur 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 la forme d'une liste à sélection unique.
TYPE_MULTI_SELECT "multi-select" Tableau de chaînes avec des valeurs sélectionnées à partir de android:entryValues. Utilisez cette option 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'interface utilisateur. Stocke une seule valeur de chaîne.
TYPE_BUNDLE_ARRAY "bundle_array" Utilisez cette option pour stocker des tableaux soumis à une restriction bundles. Disponible dans Android 6.0 (niveau d'API 23).

Remarque:Les fichiers android:entryValues sont lisibles par un ordinateur et ne peuvent pas être localisés. Utilisez android:entries pour présenter des valeurs lisibles par l'humain et pouvant être localisées. Chaque entrée doit avoir un index 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. À la place, vous devez vérifier quelles sont les configurations gérées au démarrage ou à la reprise de votre application, 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 moments suivants:

Pour obtenir un objet RestrictionsManager, récupérez 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 d'un espace de stockage de données. Elle doit donc être effectuée avec parcimonie. N'appelez pas cette méthode chaque fois que vous avez besoin de connaître la configuration actuelle. Vous devez 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és. É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ée.

Lire et appliquer les configurations gérées

La méthode getApplicationRestrictions() renvoie un objet 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:Les configurations gérées Bundle contiennent un élément pour chaque configuration explicitement définie par un fournisseur de configurations gérées. Cependant, vous ne pouvez pas supposer qu'une configuration sera présente dans le bundle simplement parce que vous avez défini une valeur par défaut dans le fichier XML des configurations gérées.

Il appartient à votre application de prendre les mesures appropriées en fonction des paramètres de configuration gérée actuels. Par exemple, si votre application dispose d'une configuration spécifiant si elle peut télécharger des données via une connexion mobile et que vous constatez qu'elle 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 illustré 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 comme une 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 connexions 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 la configuration gérée

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 en cas de modification des paramètres de configuration.

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

Le code suivant montre comment enregistrer de manière dynamique 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:Habituellement, votre application n'a pas besoin d'être avertie des modifications de configuration lorsqu'elle est suspendue. Annulez l'enregistrement de votre broadcast receiver lorsque l'application est suspendue. Lorsque l'application redémarre, 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 que vous êtes informé des modifications de configuration qui se produisent lorsque l'application est active.

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

Après avoir appliqué les modifications de configuration gérée à votre application, il est recommandé d'informer les EMM de l'état de ces modifications. Android accepte une fonctionnalité appelée états d'application appariés, que vous pouvez utiliser pour envoyer des commentaires chaque fois que votre application tente d'appliquer des modifications de configuration gérée. Ces commentaires peuvent vous permettre de confirmer que votre application a bien défini des configurations gérées ou d'inclure un message d'erreur si votre application n'a pas appliqué les modifications spécifiées.

Les fournisseurs EMM peuvent récupérer ces commentaires et les afficher dans leur console pour les administrateurs informatiques. Pour en savoir plus à ce sujet, y compris un guide détaillé sur l'ajout de commentaires à votre application, consultez la section Envoyer des commentaires sur les applications aux fournisseurs EMM.

Autres exemples de code

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