Architecture de l’information

Android 8.0 a introduit une nouvelle architecture d'informations pour l'application Paramètres afin de simplifier la façon dont les paramètres sont organisés et permettre aux utilisateurs de trouver plus facilement les paramètres permettant de personnaliser leurs appareils Android. Android 9 a introduit quelques améliorations pour offrir davantage de fonctionnalités de paramètres et une mise en œuvre plus facile.

Exemples et source

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

Les chemins d’accès aux fichiers pour les composants importants sont répertorié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

Mise en œuvre

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

Ainsi, lorsque vous déplacez des préférences 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 le nouveau DashboardFragment . Les API requises par PreferenceController sont décrites dans leur nom et documentées dans Javadoc.

Il est fortement recommandé d'ajouter un test unitaire pour chaque PreferenceController . Si la modification est soumise à AOSP, un test unitaire est requis. Pour obtenir plus d'informations sur la façon d'écrire des tests basés sur Robolectric, consultez le fichier Lisezmoi packages/apps/Settings/tests/robotests/README.md .

Architecture d'informations de type plugin

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 hôte de type plugin qui contient des éléments de paramètres. Les éléments de paramètres sont modélisés sous forme de contrôleurs de type plugin. Par conséquent, une page de paramètres est construite par un seul fragment d’hôte et plusieurs contrôleurs de paramètres.

Tableau de bordFragment

DashboardFragment est l'hôte de contrôleurs de préférences de type plugin. Le fragment hérite de PreferenceFragment et possède 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 DashboardFragment utilise la méthode getPreferenceScreenResId() pour définir quel fichier XML contient la liste statique des préférences à afficher.

Préférences dynamiques

Un élément dynamique représente une vignette avec une intention, menant à une activité externe ou interne. Habituellement, l’intention mène à une page de paramètres différente. Par exemple, l'élément de paramètre « Google » dans la page d'accueil Paramètres est un élément dynamique. Les éléments dynamiques sont définis dans AndroidManifest (discuté ci-dessous) et chargés via un FeatureProvider (défini comme DashboardFeatureProvider ).

Les paramètres dynamiques sont plus lourds que les paramètres configurés statiquement, donc normalement les développeurs doivent implémenter le paramètre comme un paramètre statique. Cependant, le paramètre dynamique peut être utile lorsque l'une des conditions suivantes est vraie :

  • Le paramètre n'est pas directement implémenté dans l'application Paramètres (comme l'injection d'un paramètre implémenté par les applications OEM/Carrier).
  • Le paramètre devrait 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 :

  • Marquez l'activité comme paramètre dynamique en ajoutant un filtre d'intention à 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 tiré 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 du rendu, le fragment demandera une liste de préférences à partir des paramètres XML statiques et dynamiques définis dans AndroidManifest . Que les PreferenceController soient définis en code Java ou en XML, DashboardFragment gère la logique de gestion de chaque paramètre via PreferenceController (discuté ci-dessous). Ensuite, ils sont affichés dans l’interface utilisateur sous forme de liste mixte.

PréférenceContrôleur

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

PreferenceController dans la version Android 9

Un PreferenceController contient toute la logique pour interagir avec la préférence, y compris l'affichage, la mise à jour, l'indexation de la recherche, etc.

L'interface de PreferenceController est définie comme BasePreferenceController . Par exemple, consultez le code dans packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

Il existe plusieurs sous-classes de BasePreferenceController , chacune correspondant à un style d'interface utilisateur spécifique pris en charge par défaut par l'application Paramètres. 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érences basée sur les bascules.

BasePreferenceController possède des API telles que getAvailabilityStatus() , displayPreference() , handlePreferenceTreeClicked(), etc. Une documentation détaillée pour chaque API se trouve dans la classe d'interface.

Une restriction sur l'implémentation 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 sur le fragment, le tableau de bord fournit une méthode pour attacher un PreferenceController avant l'heure d'affichage. Au moment de l'installation, le contrôleur est connecté au fragment afin que tous les futurs événements pertinents soient envoyés au contrôleur.

DashboardFragment conserve une liste de PreferenceController à l'écran. Au niveau de onCreate() du fragment, tous les contrôleurs sont invoqués pour la méthode getAvailabilityStatus() , et si elle renvoie true, displayPreference() est invoquée pour traiter la logique d'affichage. getAvailabilityStatus() est également important pour indiquer au cadre de paramètres quels éléments sont disponibles lors de la recherche.

PreferenceController dans les versions Android 8.x

Un PreferenceController contient toute la logique pour interagir avec la préférence, y compris l'affichage, la mise à jour et l'indexation de la recherche. etc.

Correspondant aux interactions de préférence, l'interface de PreferenceController possède les API isAvailable() , displayPreference() , handlePreferenceTreeClicked() etc. Une documentation détaillée sur chaque API peut être trouvée dans la classe d'interface.

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

DashboardFragment conserve une liste de PreferenceControllers à l'écran. Au niveau onCreate() du fragment, tous les contrôleurs sont invoqués pour la méthode isAvailable() , et si elle renvoie true, displayPreference() est invoquée pour traiter la logique d'affichage.

Utilisation de 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 de préférences de la page d'origine, suivez la procédure de déplacement statique pour votre version Android ci-dessous. Sinon, suivez la procédure de déplacement dynamique pour votre version Android.

Déplacement statique dans 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 XML de la page d'origine.
  3. Ajoutez la préférence au 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. Habituellement, c'est dans createPreferenceControllers() . Le contrôleur peut être déclaré directement en XML.

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

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

Déplacement dynamique dans Android 9

  1. Recherchez la catégorie hébergée par la page d'origine et la page de destination. Vous pouvez trouver ces informations dans DashboardFragmentRegistry .
  2. Ouvrez le fichier AndroidManifest.xml qui contient le paramètre que vous devez déplacer et recherchez l'entrée d'activité représentant 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 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 à partir de la méthode getPreferenceScreenResId() de la page.
  3. Supprimez la préférence dans le XML de la page d'origine.
  4. Ajoutez la préférence au 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. Habituellement, c'est dans getPreferenceControllers() .
  6. Remarque : Il est possible que la préférence n'ait pas de PreferenceController .

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

Déplacement dynamique dans les versions Android 8.x

  1. Recherchez la catégorie hébergée par la page d'origine et la page de destination. Vous pouvez trouver ces informations dans DashboardFragmentRegistry .
  2. Ouvrez le fichier AndroidManifest.xml qui contient le paramètre que vous devez déplacer et recherchez l'entrée d'activité représentant ce paramètre.
  3. Modifiez la valeur des métadonnées de l'activité pour com.android.settings.category , définissez le point de valeur sur la clé de catégorie de la nouvelle page.

Créer une nouvelle préférence dans une page

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

Création d'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 nouvel élément de préférence dans le XML. Assurez-vous qu’il dispose d’un android:key unique.
  3. Définissez un PreferenceController pour cette préférence dans la méthode getPreferenceControllers() de la page.
    • Sous 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à ailleurs, il est possible qu'il existe déjà un PreferenceController pour elle. Vous pouvez réutiliser le PreferenceController sans en créer un nouveau.

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

Création d'une préférence dynamique

  1. Recherchez la catégorie hébergée par la page d'origine et la page de destination. Vous pouvez trouver ces informations dans DashboardFragmentRegistry .
  2. Créer une nouvelle 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 pour com.android.settings.category sur la même valeur définie à l'étape 1.

Créer une nouvelle page

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

    Remarque : Cette étape est facultative. Si vous n'avez besoin d'aucune préférence dynamique dans cette page, vous n'avez pas besoin de fournir de clé de catégorie.

  3. Suivez les étapes pour ajouter les paramètres nécessaires à cette page. Pour plus d’informations, consultez la section Implémentation .

Validation

  • Exécutez les tests robotiques dans Paramètres. Tous les tests existants et nouveaux doivent réussir.
  • Créez et installez les paramètres, puis ouvrez manuellement la page en cours de modification. La page devrait être mise à jour immédiatement.