Architecture de l’information

Android 8.0 a introduit une nouvelle architecture des informations pour l'application Paramètres afin de simplifier l'organisation des paramètres et de permettre aux utilisateurs de trouver plus rapidement les paramètres permettant de personnaliser leurs appareils Android. Android 9 a apporté des améliorations pour offrir davantage de fonctionnalités de paramètres et faciliter l'implémentation.

Exemples et source

Actuellement, la plupart des pages des paramètres sont implémentées à l'aide du nouveau framework. DisplaySettings en est un bon exemple : packages/apps/Settings/src/com/android/settings/DisplaySettings.java

Les chemins d'accès aux fichiers des composants importants sont indiqués ci-dessous:

  • CategoryKey: packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
  • DashboardFragmentRegistry: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
  • DashboardFragment: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
  • AbstractPreferenceController: frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
  • BasePreferenceController (introduit dans Android 9) : packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

Implémentation

Les fabricants d'appareils sont encouragés à adapter l'architecture des informations existante des paramètres et à insérer des pages de paramètres supplémentaires si nécessaire pour intégrer les fonctionnalités spécifiques aux partenaires. Il peut être compliqué de transférer des préférences d'une ancienne page (implémentée en tant que SettingsPreferencePage) vers une nouvelle page (implémentée à l'aide de DashboardFragment). La préférence provenant de l'ancienne page n'est probablement pas implémentée avec un PreferenceController.

Ainsi, lorsque vous déplacez une préférence d'une ancienne page vers une nouvelle page, vous devez créer un PreferenceController et déplacer le code dans le contrôleur avant de l'instancier dans la nouvelle DashboardFragment. Les API requises par PreferenceController sont décrites dans leur nom et documentées dans Javadoc.

Nous vous recommandons vivement d'ajouter un test unitaire pour chaque PreferenceController. Si la modification est envoyée à AOSP, un test unitaire est requis. Pour en savoir plus sur l'écriture de tests basés sur Robolectric, consultez le fichier README packages/apps/Settings/tests/robotests/README.md.

Architecture de l'information de type plug-in

Chaque élément de paramètres est implémenté en tant que préférence. Une préférence peut facilement être déplacée d'une page à une autre.

Pour faciliter le déplacement de plusieurs paramètres, Android 8.0 a introduit un fragment d'hôte de type plug-in contenant des éléments de paramètres. Les éléments de paramètres sont modélisés comme des contrôleurs de type plug-in. Par conséquent, une page de paramètres est construite par un seul fragment hôte et plusieurs contrôleurs de paramètres.

Fragment de tableau de bord

DashboardFragment héberge les contrôleurs de préférences de style plug-in. Le fragment hérite de PreferenceFragment et comporte des hooks pour développer et mettre à jour les listes de préférences statiques et les listes de préférences dynamiques.

Préférences statiques

Une liste de préférences statiques est définie en XML à l'aide de la balise <Preference>. Une implémentation de DashboardFragment utilise la méthode getPreferenceScreenResId() pour définir le fichier XML contenant la liste statique de préférences à afficher.

Préférences dynamiques

Un élément dynamique représente une carte avec un intent, ce qui conduit à une activité externe ou interne. Généralement, l'intention mène à une page de paramètres différente. Par exemple, l'élément de paramètre "Google" sur la page d'accueil des paramètres est un élément dynamique. Les éléments dynamiques sont définis dans AndroidManifest (décrit ci-dessous) et chargés via un élément FeatureProvider (défini en tant que DashboardFeatureProvider).

Les paramètres dynamiques sont plus lourds que les paramètres configurés de manière statique. Par conséquent, les développeurs doivent normalement implémenter le paramètre en tant que paramètre statique. Toutefois, le paramètre dynamique peut être utile dans les cas suivants:

  • Le paramètre n'est pas directement implémenté dans l'application Paramètres (par exemple, l'injection d'un paramètre implémenté par les applications OEM/d'opérateur).
  • Le paramètre doit apparaître sur la page d'accueil des paramètres.
  • Vous disposez déjà d'une activité pour le paramètre et vous ne souhaitez pas implémenter la configuration statique supplémentaire.

Pour configurer une activité en tant que paramètre dynamique, procédez comme suit:

  • Pour marquer l'activité en tant que paramètre dynamique, ajoutez un filtre d'intent à l'activité.
  • Indiquez à l'application Paramètres à quelle catégorie elle appartient. La catégorie est une constante, définie dans CategoryKey.
  • Facultatif: Ajoutez un texte récapitulatif lorsque le paramètre est affiché.

Voici un exemple issu de l'application Paramètres pour DisplaySettings.

<activity android:name="Settings$DisplaySettingsActivity"
                   android:label="@string/display_settings"
                   android:icon="@drawable/ic_settings_display">
             <!-- Mark the activity as a dynamic setting -->
              <intent-filter>
                     <action android:name="com.android.settings.action.IA_SETTINGS" />
              </intent-filter>
             <!-- Tell Settings app which category it belongs to -->
              <meta-data android:name="com.android.settings.category"
                     android:value="com.android.settings.category.ia.homepage" />
             <!-- Add a summary text when the setting is displayed -->
              <meta-data android:name="com.android.settings.summary"
                     android:resource="@string/display_dashboard_summary"/>
             </activity>

Au moment de l'affichage, le fragment demandera une liste de préférences provenant à la fois des paramètres XML statiques et dynamiques définis dans AndroidManifest. Que les éléments PreferenceController soient définis en code Java ou en XML, DashboardFragment gère la logique de traitement de chaque paramètre via PreferenceController (décrit ci-dessous). Elles s'affichent ensuite dans l'interface utilisateur sous la forme d'une liste mixte.

PreferenceController

Il existe des différences entre l'implémentation de PreferenceController sous Android 9 et sous Android 8.x, comme décrit dans cette section.

PreferenceController dans la version d'Android 9

Un PreferenceController contient toutes les logiques permettant d'interagir avec la préférence, y compris l'affichage, la mise à jour, l'indexation pour la recherche, etc.

L'interface de PreferenceController est définie en tant que BasePreferenceController. Par exemple, reportez-vous au code dans packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java.

Il existe plusieurs sous-classes de BasePreferenceController, chacune mappée à un style d'interface utilisateur spécifique compatible avec l'application Paramètres par défaut. Par exemple, TogglePreferenceController dispose d'une API qui correspond directement à la manière dont l'utilisateur doit interagir avec une interface utilisateur de préférence basée sur un bouton d'activation.

BasePreferenceController dispose d'API telles que getAvailabilityStatus(), displayPreference(), handlePreferenceTreeClicked(),, etc. La documentation détaillée de chaque API se trouve dans la classe d'interface.

Une restriction appliquée à l'implémentation de BasePreferenceController (et de ses sous-classes telles que TogglePreferenceController) est que la signature du constructeur doit correspondre à l'un des éléments suivants:

  • public MyController(Context context, String key) {}
  • public MyController(Context context) {}

Lors de l'installation d'une préférence pour le fragment, le tableau de bord fournit une méthode permettant d'associer un PreferenceController avant l'heure d'affichage. Au moment de l'installation, le contrôleur est connecté au fragment afin que tous les événements pertinents ultérieurs lui soient envoyés.

DashboardFragment conserve une liste de PreferenceController à l'écran. Au niveau de l'élément onCreate() du fragment, tous les contrôleurs sont appelés pour la méthode getAvailabilityStatus(). Si la valeur est "true", displayPreference() est appelé pour traiter la logique d'affichage. getAvailabilityStatus() est également important pour indiquer au framework des paramètres les éléments disponibles lors de la recherche.

PreferenceController dans les versions Android 8.x

Un PreferenceController contient toutes les logiques permettant d'interagir avec la préférence, y compris l'affichage, la mise à jour, l'indexation pour la recherche, etc.

En fonction des interactions de préférences, l'interface de PreferenceController contient les API isAvailable(), displayPreference(), handlePreferenceTreeClicked(), etc. Vous trouverez une documentation détaillée sur chaque API dans la classe d'interface.

Lors de l'installation d'une préférence pour le fragment, le tableau de bord fournit une méthode permettant d'associer un PreferenceController avant l'heure d'affichage. Au moment de l'installation, le contrôleur est connecté au fragment afin que tous les événements pertinents ultérieurs lui soient envoyés.

DashboardFragment conserve une liste de PreferenceControllers à l'écran. Au niveau de l'élément onCreate() du fragment, tous les contrôleurs sont appelés pour la méthode isAvailable(). Si la valeur est "true", displayPreference() est appelé pour traiter la logique d'affichage.

Utiliser DashboardFragment

Déplacer une préférence de la page A vers la page B

Si la préférence est répertoriée de manière statique dans le fichier XML des préférences de la page d'origine, suivez la procédure de déplacement Static pour votre version d'Android ci-dessous. Sinon, suivez la procédure de déplacement dynamique pour votre version d'Android.

Déménagement statique sous Android 9

  1. Recherchez les fichiers XML de préférences pour la page d'origine et la page de destination. Vous pouvez trouver ces informations à partir de la méthode getPreferenceScreenResId() de la page.
  2. Supprimez la préférence du fichier XML de la page d'origine.
  3. Ajoutez la préférence au fichier XML de la page de destination.
  4. Supprimez le PreferenceController pour cette préférence de l'implémentation Java de la page d'origine. Elle se trouve généralement dans createPreferenceControllers(). Le contrôleur peut être déclaré directement en XML.

    Remarque: La préférence peut ne pas comporter de PreferenceController.

  5. Instanciez PreferenceController dans le createPreferenceControllers() de la page de destination. Si PreferenceController est défini en XML dans l'ancienne page, définissez-le également en XML pour la nouvelle page.

Déplacement dynamique sous Android 9

  1. Identifiez la catégorie hébergée par la page d'origine et la page de destination. Ces informations sont disponibles dans DashboardFragmentRegistry.
  2. Ouvrez le fichier AndroidManifest.xml contenant le paramètre que vous devez déplacer et recherchez l'entrée "Activity" (Activité) qui correspond à ce paramètre.
  3. Définissez la valeur des métadonnées de l'activité pour com.android.settings.category sur la clé de catégorie de la nouvelle page.

Déplacement statique dans les versions d'Android 8.x

  1. Recherchez les fichiers XML de préférences pour la page d'origine et la page de destination.
  2. Vous pouvez trouver ces informations à l'aide de la méthode getPreferenceScreenResId() de la page.
  3. Supprimez la préférence dans le fichier XML de la page d'origine.
  4. Ajoutez la préférence au fichier XML de la page de destination.
  5. Supprimez le PreferenceController pour cette préférence dans l'implémentation Java de la page d'origine. Elle se trouve généralement dans getPreferenceControllers().
  6. Remarque:Il est possible que la préférence ne comporte pas de PreferenceController.

  7. Instanciez PreferenceController dans le getPreferenceControllers() de la page de destination.

Déplacement dynamique dans les versions Android 8.x

  1. Identifiez la catégorie hébergée par la page d'origine et la page de destination. Vous trouverez ces informations dans DashboardFragmentRegistry.
  2. Ouvrez le fichier AndroidManifest.xml contenant le paramètre que vous devez déplacer et recherchez l'entrée "Activity" (Activité) qui correspond à ce paramètre.
  3. Modifiez la valeur de métadonnées de l'activité pour com.android.settings.category et définissez le point de valeur sur la clé de catégorie de la nouvelle page.

Créer une préférence sur une page

Si la préférence est répertoriée de manière statique dans le fichier XML des préférences de la page d'origine, suivez la procédure statique ci-dessous. Sinon, suivez la procédure dynamique.

Créer une préférence statique

  1. Recherchez les fichiers XML de préférences pour la page. Vous pouvez trouver ces informations à partir de la méthode getPreferenceScreenResId() de la page.
  2. Ajoutez un élément "Preference" (Préférence) dans le fichier XML. Assurez-vous qu'il possède un android:key unique.
  3. Définissez un PreferenceController pour cette préférence dans la méthode getPreferenceControllers() de la page.
    • Dans Android 8.x et éventuellement sous Android 9, instanciez un PreferenceController pour cette préférence dans la méthode createPreferenceControllers() de la page.

      Si cette préférence existait déjà à d'autres emplacements, il est possible qu'elle soit déjà associée à un élément PreferenceController. Vous pouvez réutiliser le PreferenceController sans en créer un autre.

    • À partir d'Android 9, vous pouvez choisir de déclarer PreferenceController en XML à côté de la préférence. Exemple :
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>
      

Créer une préférence dynamique

  1. Identifiez la catégorie hébergée par la page d'origine et la page de destination. Vous trouverez ces informations dans DashboardFragmentRegistry.
  2. Créer une activité dans AndroidManifest
  3. Ajoutez les métadonnées nécessaires à la nouvelle activité pour définir le paramètre. Définissez la valeur des métadonnées de com.android.settings.category sur la même valeur que celle définie à l'étape 1.

Créer une page

  1. Créez un fragment héritant de DashboardFragment.
  2. Définissez sa catégorie dans DashboardFragmentRegistry.

    Remarque:Cette étape est facultative. Si vous n'avez pas besoin de préférences dynamiques sur cette page, il n'est pas nécessaire de fournir une clé de catégorie.

  3. Suivez les étapes pour ajouter les paramètres requis pour cette page. Pour en savoir plus, consultez la section Implémentation.

Validation

  • Exécutez les tests robolectric dans "Paramètres". Tous les tests existants et nouveaux devraient réussir.
  • Paramètres de compilation et d'installation, puis ouvrez manuellement la page en cours de modification. La page devrait se mettre à jour immédiatement.