Android 8.0 a introduit une nouvelle architecture d'informations pour l'application Paramètres afin de simplifier l'organisation des paramètres et de permettre aux utilisateurs de trouver plus facilement les paramètres permettant de personnaliser leurs appareils Android. Android 9 a introduit certaines améliorations pour offrir plus de fonctionnalités de paramètres et une implémentation plus simple.
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 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 de paramètres existante et à insérer des pages de paramètres supplémentaires si nécessaire pour prendre en charge les fonctionnalités propres aux partenaires. Le transfert 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
) peut s'avérer complexe. La préférence de l'ancienne page n'est probablement pas implémentée avec un PreferenceController
.
Par conséquent, 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.
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 de documentation 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 "Preference". 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 en tant que contrôleurs de type plug-in. Par conséquent, une page de paramètres se compose d'un seul fragment hôte et de plusieurs contrôleurs de paramètres.
DashboardFragment
DashboardFragment
est l'hôte des contrôleurs de préférences de type plug-in.
Le fragment hérite de PreferenceFragment
et dispose de crochets pour développer et mettre à jour à la fois 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 statique est définie au format XML à l'aide de la balise <Preference>
. Une implémentation DashboardFragment
utilise la méthode getPreferenceScreenResId()
pour définir le fichier XML contenant la liste statique des préférences à afficher.
Préférences dynamiques
Un élément dynamique représente une carte avec un intent, qui mène à une activité externe ou interne. En règle générale, l'intent mène à une autre page de paramètres. Par exemple, l'élément de paramètre "Google" de 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 FeatureProvider
(défini comme
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 implémenté directement dans l'application Paramètres (par exemple, en injectant un paramètre implémenté par les applications OEM/opérateur).
- 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'intent à l'activité.
- Indiquez à l'application Paramètres à quelle catégorie il appartient. La catégorie est une constante, définie dans
CategoryKey
. - Facultatif: ajoutez un texte récapitulatif lorsque le paramètre s'affiche.
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 demande une liste de préférences à partir des fichiers XML statiques et des paramètres 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
(voir ci-dessous). Ils sont ensuite affichés dans l'UI sous la forme d'une liste mixte.
PreferenceController
Il existe des différences entre l'implémentation de PreferenceController
dans Android 9 et Android 8.x, comme décrit dans cette section.
PreferenceController dans la version d'Android 9
Un PreferenceController
contient toute la logique permettant d'interagir avec la préférence, y compris l'affichage, la mise à jour, l'indexation de 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 correspondant à un style d'UI spécifique compatible avec l'application Paramètres par défaut. Par exemple, TogglePreferenceController
dispose d'une API qui correspond directement à la façon dont l'utilisateur doit interagir avec une UI de préférences basée sur des boutons d'activation/de désactivation.
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 concernant l'implémentation de BasePreferenceController
(et de ses sous-classes telles que TogglePreferenceController
) est que la signature du constructeur doit correspondre à l'une des options suivantes:
public MyController(Context context, String key) {}
public MyController(Context context) {}
Lors de l'installation d'une préférence dans 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 câblé au fragment afin que tous les événements pertinents futurs soient envoyés au contrôleur.
DashboardFragment
conserve une liste de PreferenceController
sur l'écran. Dans la onCreate()
du fragment, tous les contrôleurs sont appelés pour la méthode getAvailabilityStatus()
. Si elle renvoie la valeur "true", displayPreference()
est appelé pour traiter la logique d'affichage.
getAvailabilityStatus()
est également important pour indiquer au framework de paramètres les éléments disponibles lors de la recherche.
PreferenceController dans les versions d'Android 8.x
Un PreferenceController
contient toute la logique permettant d'interagir avec la préférence, y compris l'affichage, la mise à jour, l'indexation de recherche, etc.
Conformément aux interactions de préférences, l'interface de
PreferenceController
comporte 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 dans 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 câblé au fragment afin que tous les événements pertinents futurs soient envoyés au contrôleur.
DashboardFragment
conserve une liste de PreferenceControllers
à l'écran. Dans le onCreate()
du fragment, tous les contrôleurs sont appelés pour la méthode isAvailable()
. Si elle renvoie la valeur "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 Android.
Déplacement statique sous Android 9
- Recherchez les fichiers XML de préférences pour la page d'origine et la page de destination. Vous trouverez ces informations dans la méthode
getPreferenceScreenResId()
de la page. - Supprimez la préférence du fichier XML de la page d'origine.
- Ajoutez la préférence au fichier XML de la page de destination.
- Supprimez
PreferenceController
pour cette préférence de l'implémentation Java de la page d'origine. Il se trouve généralement danscreatePreferenceControllers()
. Le contrôleur peut être déclaré directement en XML.Remarque: Il est possible que la préférence ne comporte pas de
PreferenceController
. - Instanciez
PreferenceController
dans lecreatePreferenceControllers()
de la page de destination. SiPreferenceController
est défini en XML sur l'ancienne page, définissez-le également en XML pour la nouvelle page.
Déplacement dynamique sous Android 9
- Identifiez la catégorie hébergée par la page d'origine et la page de destination. Vous trouverez ces informations dans
DashboardFragmentRegistry
. - Ouvrez le fichier
AndroidManifest.xml
contenant le paramètre que vous devez déplacer, puis recherchez l'entrée Activity représentant ce paramètre. - 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
- Recherchez les fichiers XML de préférences pour la page d'origine et la page de destination. Vous pouvez trouver ces informations à l'aide de la méthode
- Supprimez la préférence dans le fichier XML de la page d'origine.
- Ajoutez la préférence au fichier XML de la page de destination.
- Supprimez
PreferenceController
pour cette préférence dans l'implémentation Java de la page d'origine. Il se trouve généralement dansgetPreferenceControllers()
. - Instanciez
PreferenceController
dans legetPreferenceControllers()
de la page de destination.
getPreferenceScreenResId()
de la page.
Remarque:Il est possible que la préférence ne comporte pas de PreferenceController
.
Déplacement dynamique dans les versions Android 8.x
- Identifiez la catégorie hébergée par la page d'origine et la page de destination. Vous trouverez ces informations dans
DashboardFragmentRegistry
. - Ouvrez le fichier
AndroidManifest.xml
contenant le paramètre que vous devez déplacer, puis recherchez l'entrée "Activity" (Activité) qui le représente. - Modifiez la valeur des métadonnées de l'activité pour
com.android.settings.category
, puis définissez le point de valeur sur la clé de catégorie de la nouvelle page.
Créer une préférence dans une page
Si la préférence est listé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éer une préférence statique
- Recherchez les fichiers XML de préférences de la page. Vous trouverez ces informations dans la méthode getPreferenceScreenResId() de la page.
- Ajoutez un élément de préférence dans le fichier XML. Assurez-vous qu'il dispose d'un
android:key
unique. -
Définissez un
PreferenceController
pour cette préférence dans la méthodegetPreferenceControllers()
de la page.- Sous Android 8.x et éventuellement sous Android 9, instanciez un
PreferenceController
pour cette préférence dans la méthodecreatePreferenceControllers()
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 lePreferenceController
sans en créer un nouveau. -
À 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"/>
- Sous Android 8.x et éventuellement sous Android 9, instanciez un
Créer une préférence dynamique
- Identifiez la catégorie hébergée par la page d'origine et la page de destination. Vous trouverez ces informations dans
DashboardFragmentRegistry
. - Créer une activité dans
AndroidManifest
- 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 page
- Créez un fragment héritant de
DashboardFragment
. - 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, vous n'avez pas besoin de fournir de clé de catégorie.
- Suivez la procédure pour ajouter les paramètres nécessaires à 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 doivent réussir.
- Créez et installez les paramètres, puis ouvrez manuellement la page en cours de modification. La page devrait se mettre à jour immédiatement.