Mit Android 8.0 wurde eine neue Informationsarchitektur für die Einstellungen-App eingeführt, um die Organisation der Einstellungen zu vereinfachen und Nutzern die schnelle Suche nach Einstellungen zur Anpassung ihrer Android-Geräte zu erleichtern. Mit Android 9 wurden einige Verbesserungen eingeführt, um mehr Funktionen in den Einstellungen und eine einfachere Implementierung zu ermöglichen.
Beispiele und Quelle
Die meisten Seiten in den Einstellungen werden derzeit mit dem neuen Framework implementiert. Ein gutes Beispiel dafür ist DisplaySettings:
packages/apps/Settings/src/com/android/settings/DisplaySettings.java
Dateipfade für wichtige Komponenten sind unten aufgeführt:
- 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 (in Android 9 eingeführt):
packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java
Implementierung
Gerätehersteller werden aufgefordert, die vorhandene Architektur der Einstellungen anzupassen und nach Bedarf zusätzliche Seiten mit Einstellungen einzufügen, um partnerspezifische Funktionen zu berücksichtigen. Das Verschieben von Einstellungen von einer Legacy-Seite (implementiert als SettingsPreferencePage
) auf eine neue Seite (mit DashboardFragment
implementiert) kann kompliziert sein. Die Einstellung auf der alten Seite ist wahrscheinlich nicht mit einem PreferenceController
implementiert.
Wenn Sie also die Einstellungen von einer alten Seite auf eine neue Seite verschieben, müssen Sie einen PreferenceController
erstellen und den Code in den Controller verschieben, bevor Sie ihn in der neuen DashboardFragment
instanziieren. Die für PreferenceController
erforderlichen APIs sind in ihrem Namen beschrieben und im Javadoc dokumentiert.
Es wird dringend empfohlen, für jede PreferenceController
einen Einheitentest hinzuzufügen.
Wenn die Änderung bei AOSP eingereicht wird, ist ein Unittest erforderlich.
Weitere Informationen zum Schreiben von Robolectric-basierten Tests finden Sie in der packages/apps/Settings/tests/robotests/README.md
.
Informationsarchitektur im Plug-in-Stil
Jedes Element der Einstellungen wird als Einstellung implementiert. Eine Einstellung kann ganz einfach von einer Seite auf eine andere verschoben werden.
Damit sich mehrere Einstellungen leichter verschieben lassen, wurde in Android 8.0 ein Host-Fragment im Plug-in-Stil eingeführt, das Einstellungen enthält. Einstellungen werden als Plug-in-Controller modelliert. Daher besteht eine Seite mit Einstellungen aus einem einzelnen Hostfragment und mehreren Einstellungscontrollern.
DashboardFragment
DashboardFragment
ist der Host für Plug-in-basierte Einstellungscontroller.
Das Fragment wird von PreferenceFragment
übernommen und enthält Hooks, mit denen sowohl statische als auch dynamische Einstellungslisten erweitert und aktualisiert werden können.
Statische Einstellungen
Eine statische Präferenzliste wird in XML mit dem Tag <Preference>
definiert. Bei einer DashboardFragment
-Implementierung wird mit der Methode getPreferenceScreenResId()
definiert, welche XML-Datei die statische Liste der anzuzeigenden Einstellungen enthält.
Dynamische Einstellungen
Ein dynamisches Element stellt eine Kachel mit Intent dar, die zu einer externen oder internen Aktivität führt. Normalerweise führt der Intent zu einer anderen Einstellungsseite. Das Einstellungselement „Google“ auf der Startseite „Einstellungen“ ist beispielsweise ein dynamisches Element. Dynamische Elemente werden in AndroidManifest
(siehe unten) definiert und über ein FeatureProvider
(definiert als
DashboardFeatureProvider
) geladen.
Dynamische Einstellungen sind leistungsintensiver als statisch konfigurierte Einstellungen. Daher sollten Entwickler die Einstellung normalerweise als statische Einstellung implementieren. Die dynamische Einstellung kann jedoch in folgenden Fällen nützlich sein:
- Die Einstellung ist nicht direkt in der App „Einstellungen“ implementiert, z. B. durch das Einfügen einer Einstellung, die von OEM-/Mobilfunkanbieter-Apps implementiert wurde.
- Die Einstellung sollte auf der Startseite der Einstellungen angezeigt werden.
- Sie haben bereits eine Aktivität für die Einstellung und möchten die zusätzliche statische Konfiguration nicht implementieren.
So konfigurieren Sie eine Aktivität als dynamische Einstellung:
- Markieren Sie die Aktivität als dynamische Einstellung, indem Sie der Aktivität einen Intent-Filter hinzufügen.
- Teilen Sie der App „Einstellungen“ mit, zu welcher Kategorie sie gehört. Die Kategorie ist eine Konstante, die in
CategoryKey
definiert ist. - Optional: Fügen Sie eine Zusammenfassung hinzu, wenn die Einstellung angezeigt wird.
Hier ein Beispiel aus der Einstellungen App für 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>
Beim Rendern wird vom Fragment eine Liste der Einstellungen aus der statischen XML-Datei und den in AndroidManifest
definierten dynamischen Einstellungen angefordert. Unabhängig davon, ob die PreferenceController
s in Java-Code oder in XML definiert sind, verwaltet DashboardFragment
die Verarbeitungslogik jeder Einstellung über PreferenceController
(siehe unten). Sie werden dann in der Benutzeroberfläche als gemischte Liste angezeigt.
PreferenceController
Zwischen der Implementierung von PreferenceController
in Android 9 und Android 8.x gibt es Unterschiede, die in diesem Abschnitt beschrieben werden.
PreferenceController in der Android 9-Version
Ein PreferenceController
enthält die gesamte Logik für die Interaktion mit der Einstellung, einschließlich Anzeige, Aktualisierung, Suchindexierung usw.
Die Schnittstelle von PreferenceController
ist als BasePreferenceController
definiert. Sehen Sie sich zum Beispiel den Code in packages/apps/Settings/src/com/android/settings/core/
BasePreferenceController.java
an.
Es gibt mehrere Unterklassen von BasePreferenceController
, die jeweils einem bestimmten UI-Stil zugeordnet sind, der standardmäßig von der Einstellungen App unterstützt wird. TogglePreferenceController
hat beispielsweise eine API, die direkt darauf abbildet, wie der Nutzer mit einer UI für die Einstellungsschalter interagieren soll.
BasePreferenceController
enthält APIs wie getAvailabilityStatus()
, displayPreference()
, handlePreferenceTreeClicked(),
usw. Eine ausführliche Dokumentation für jede API finden Sie in der Schnittstellenklasse.
Bei der Implementierung von BasePreferenceController
(und deren Unterklassen wie TogglePreferenceController
) ist zu beachten, dass die Signatur des Konstruktors einer der folgenden Optionen entsprechen muss:
public MyController(Context context, String key) {}
public MyController(Context context) {}
Beim Installieren einer Einstellung für das Fragment bietet das Dashboard eine Methode, um vor der Auslieferung ein PreferenceController
anzuhängen. Bei der Installation wird der Controller mit dem Fragment verbunden, damit alle zukünftigen relevanten Ereignisse an den Controller gesendet werden.
DashboardFragment
behält eine Liste von PreferenceController
s auf dem Bildschirm bei. Bei onCreate()
des Fragments werden alle Controller für die Methode getAvailabilityStatus()
aufgerufen. Wenn diese Methode „wahr“ zurückgibt, wird displayPreference()
aufgerufen, um die Anzeigelogik zu verarbeiten.
getAvailabilityStatus()
ist auch wichtig, um dem Einstellungs-Framework mitzuteilen, welche Elemente bei der Suche verfügbar sind.
PreferenceController in Android 8.x-Releases
Ein PreferenceController
enthält die gesamte Logik für die Interaktion mit der Einstellung, einschließlich Anzeige, Aktualisierung, Suchindexierung usw.
Entsprechend den Interaktionen mit den Einstellungen hat die Benutzeroberfläche von
PreferenceController
die APIs isAvailable()
,
displayPreference()
, handlePreferenceTreeClicked()
usw. Eine detaillierte Dokumentation zu jeder API finden Sie in der Benutzeroberflächenklasse.
Während der Installation einer Einstellung für das Fragment bietet das Dashboard eine Methode zum Anhängen einer PreferenceController
vor der Anzeigezeit. Bei der Installation ist der Controller mit dem Fragment verbunden, sodass alle zukünftigen relevanten Ereignisse an den Controller gesendet werden.
DashboardFragment
behält eine Liste von PreferenceControllers
auf dem Bildschirm. Beim onCreate()
des Fragments werden alle Controller für die isAvailable()
-Methode aufgerufen. Wenn diese Methode „wahr“ zurückgibt, wird displayPreference()
aufgerufen, um die Anzeigelogik zu verarbeiten.
DashboardFragment verwenden
Eine Einstellung von Seite A auf Seite B verschieben
Wenn die Einstellung in der XML-Datei der ursprünglichen Seite statisch aufgeführt ist, folgen Sie unten der Anleitung für die statische Umstellung für Ihre Android-Version. Folgen Sie andernfalls dem dynamischen Verschiebungsvorgang für Ihren Android-Release.
Statische Bewegung in Android 9
- Suchen Sie die bevorzugten XML-Dateien für die Originalseite und die Zielseite. Diese Informationen finden Sie in der
getPreferenceScreenResId()
-Methode der Seite. - Entfernen Sie die Einstellung aus der XML-Datei der ursprünglichen Seite.
- Fügen Sie die Einstellung der XML-Datei der Zielseite hinzu.
- Entfernen Sie
PreferenceController
für diese Einstellung aus der Java-Implementierung der Originalseite. Normalerweise ist dascreatePreferenceControllers()
. Der Controller kann auch direkt in XML deklariert werden.Hinweis: Die Einstellung hat möglicherweise keine
PreferenceController
. - Instanziere die
PreferenceController
imcreatePreferenceControllers()
der Zielseite. WennPreferenceController
in der alten Seite in XML definiert ist, definieren Sie es auch in XML für die neue Seite.
Dynamisches Verschieben unter Android 9
- Finden Sie heraus, zu welcher Kategorie die Original- und Zielseite gehören. Diese Informationen finden Sie in
DashboardFragmentRegistry
. - Öffnen Sie die Datei
AndroidManifest.xml
mit der Einstellung, die Sie verschieben möchten, und suchen Sie den Aktivitätseintrag, der diese Einstellung darstellt. - Legen Sie den Metadatenwert der Aktivität für
com.android.settings.category
auf den Kategorieschlüssel der neuen Seite fest.
Statischer Umzug in Android 8.x-Releases
- Suchen Sie die XML-Dateien mit den Einstellungen für die ursprüngliche Seite und die Zielseite. Diese Informationen finden Sie in der
- Entfernen Sie die Einstellung in der XML-Datei der Originalseite.
- Fügen Sie die Einstellung in die XML-Datei der Zielseite ein.
- Entfernen Sie
PreferenceController
für diese Einstellung in der Java-Implementierung der Originalseite. Normalerweise ist dasgetPreferenceControllers()
. - Erstellen Sie eine Instanz von
PreferenceController
imgetPreferenceControllers()
der Zielseite.
getPreferenceScreenResId()
-Methode der Seite.
Hinweis:Möglicherweise hat die Einstellung keine PreferenceController
.
Dynamische Verschiebung in Android 8.x-Releases
- Finden Sie heraus, zu welcher Kategorie die ursprüngliche und die Zielseite gehören. Sie finden diese Informationen unter
DashboardFragmentRegistry
. - Öffnen Sie die Datei
AndroidManifest.xml
mit der Einstellung, die Sie verschieben möchten, und suchen Sie den Eintrag „Aktivität“ für diese Einstellung. - Ändern Sie den Metadatenwert der Aktivität für
com.android.settings.category
und legen Sie den Wertpunkt auf den Kategorieschlüssel der neuen Seite fest.
Neue Einstellung auf einer Seite erstellen
Wenn die Einstellung in der XML-Datei der ursprünglichen Seite statisch aufgeführt ist, folgen Sie der Anleitung unten unter statisch. Andernfalls folgen Sie dem dynamischen Verfahren.
Statische Einstellung erstellen
- Suchen Sie die XML-Dateien mit den Einstellungen für die Seite. Sie finden diese Informationen in der Methode „getPreferenceScreenResId()“ der Seite.
- Fügen Sie der XML-Datei ein neues Element „Preference“ hinzu. Die Fahrtbeschreibung muss eine eindeutige
android:key
haben. -
Definiere in der
getPreferenceControllers()
-Methode der Seite einePreferenceController
für diese Einstellung.- Unter Android 8.x und optional unter Android 9 müssen Sie in der
createPreferenceControllers()
-Methode der Seite einePreferenceController
für diese Einstellung instanziieren.Wenn diese Einstellung bereits an anderer Stelle vorhanden war, gibt es möglicherweise bereits eine
PreferenceController
dafür. Sie können diePreferenceController
wiederverwenden, ohne eine neue zu erstellen. -
Ab Android 9 können Sie
PreferenceController
neben der Einstellung in XML deklarieren. Beispiel:<Preference android:key="reset_dashboard" android:title="@string/reset_dashboard_title" settings:controller="com.android.settings.system.ResetPreferenceController"/>
- Unter Android 8.x und optional unter Android 9 müssen Sie in der
Dynamische Einstellungen erstellen
- Finden Sie heraus, zu welcher Kategorie die ursprüngliche und die Zielseite gehören. Sie finden diese Informationen unter
DashboardFragmentRegistry
. - Neue Aktivität in
AndroidManifest
erstellen - Fügen Sie der neuen Aktivität die erforderlichen Metadaten hinzu, um die Einstellung zu definieren. Legen Sie den Metadatenwert für
com.android.settings.category
auf denselben Wert fest, der in Schritt 1 definiert wurde.
Neue Seite erstellen
- Erstellen Sie ein neues Fragment, das von
DashboardFragment
erbt. - Definieren Sie die Kategorie in
DashboardFragmentRegistry
.Hinweis:Dieser Schritt ist optional. Wenn Sie auf dieser Seite keine dynamischen Einstellungen benötigen, müssen Sie keinen Kategorieschlüssel angeben.
- Folgen Sie der Anleitung, um die für diese Seite erforderlichen Einstellungen hinzuzufügen. Weitere Informationen finden Sie im Abschnitt Implementierung.
Zertifizierungsstufe
- Führe die robolectric-Tests in den Einstellungen aus. Alle vorhandenen und neuen Tests sollten funktionieren.
- Erstellen und installieren Sie die Einstellungen und öffnen Sie dann die zu ändernde Seite manuell. Die Seite sollte sofort aktualisiert werden.