Mit Android 8.0 wurde eine neue Informationsarchitektur für die Einstellungen eingeführt, um die Organisation der Einstellungen zu vereinfachen und Nutzern die Suche nach Einstellungen zum Anpassen ihrer Android-Geräte zu erleichtern. Mit Android 9 wurden einige Verbesserungen eingeführt, um mehr Einstellungsfunktionen 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 sind die 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 (eingeführt in Android 9):
packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java
Implementierung
Gerätehersteller werden aufgefordert, die vorhandene Architektur für Einstellungen anzupassen und bei Bedarf zusätzliche Einstellungsseiten einzufügen, um partnerspezifische Funktionen zu berücksichtigen. Die Übertragung von Einstellungen von einer alten Seite (implementiert als SettingsPreferencePage) auf eine neue Seite (implementiert mit DashboardFragment) kann kompliziert sein. Die Einstellung auf der alten Seite wurde wahrscheinlich nicht mit einem PreferenceController implementiert.
Wenn Sie also Einstellungen von einer alten Seite auf eine neue Seite verschieben, müssen Sie ein PreferenceController erstellen und den Code in den Controller verschieben, bevor Sie ihn im neuen DashboardFragment instanziieren. Die APIs, die für PreferenceController erforderlich sind, werden in ihrem Namen beschrieben und in Javadoc dokumentiert.
Es wird dringend empfohlen, für jede PreferenceController einen Unittest hinzuzufügen.
Wenn die Änderung an AOSP gesendet wird, ist ein Unittest erforderlich.
Weitere Informationen zum Schreiben von Robolectric-basierten Tests finden Sie in der README-Datei packages/apps/Settings/tests/robotests/README.md.
Informationsarchitektur im Stil von Plug-ins
Jedes Einstellungselement wird als Preference implementiert. Eine Einstellung kann ganz einfach von einer Seite auf eine andere verschoben werden.
Damit mehrere Einstellungen einfacher verschoben werden können, wurde in Android 8.0 ein Host-Fragment im Plug-in-Stil eingeführt, das Einstellungselemente enthält. Einstellungselemente werden als Controller im Plug-in-Stil modelliert. Eine Einstellungsseite besteht daher aus einem einzelnen Host-Fragment und mehreren Einstellungscontrollern.
DashboardFragment
DashboardFragment ist der Host von Preference-Controllern im Plug-in-Stil.
Das Fragment erbt von PreferenceFragment und enthält Hooks zum Erweitern und Aktualisieren von statischen und dynamischen Einstellungslisten.
Statische Einstellungen
Eine statische Liste mit Einstellungen 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 einem Intent dar, die zu einer externen oder internen Aktivität führt. Normalerweise führt der Intent zu einer anderen Einstellungsseite. Beispiel: Das Element „Google“ auf der Startseite der Einstellungen ist ein dynamisches Element. Dynamische Elemente werden in AndroidManifest (siehe unten) definiert und über einen FeatureProvider (definiert als 
DashboardFeatureProvider) geladen.
Dynamische Einstellungen sind aufwendiger als statisch konfigurierte Einstellungen. Entwickler sollten die Einstellung daher normalerweise statisch implementieren. Die dynamische Einstellung kann jedoch in folgenden Fällen nützlich sein:
- Die Einstellung wird nicht direkt in der Einstellungen App implementiert, z. B. durch Einfügen einer Einstellung, die von OEM-/Mobilfunkanbieter-Apps implementiert wird.
- 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 Einstellungen-App mit, zu welcher Kategorie sie gehört. Die Kategorie ist eine Konstante, die in CategoryKeydefiniert ist.
- Optional: Fügen Sie einen Zusammenfassungstext hinzu, der angezeigt wird, wenn die Einstellung aufgerufen wird.
Hier ist ein Beispiel aus den Einstellungen 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>
Zur Renderzeit fordert das Fragment eine Liste von Einstellungen sowohl aus statischem XML als auch aus dynamischen Einstellungen an, die in AndroidManifest definiert sind. Unabhängig davon, ob die PreferenceController im Java-Code oder in XML definiert sind, verwaltet DashboardFragment die Logik für die Verarbeitung jeder Einstellung über PreferenceController (siehe unten). Sie werden dann in der Benutzeroberfläche als gemischte Liste angezeigt.
PreferenceController
Die Implementierung von PreferenceController in Android 9 und Android 8.x unterscheidet sich, wie in diesem Abschnitt beschrieben.
PreferenceController in Android 9-Release
Ein PreferenceController enthält die gesamte Logik für die Interaktion mit der Einstellung, einschließlich der Anzeige, Aktualisierung und Suchindexierung.
Die Schnittstelle von PreferenceController ist als BasePreferenceController definiert. Sehen Sie sich beispielsweise 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 entsprechen, der von der Einstellungs-App standardmäßig unterstützt wird. TogglePreferenceController hat beispielsweise eine API, die direkt der Interaktion des Nutzers mit einer auf Ein/Aus-Schaltern basierenden Benutzeroberfläche für Einstellungen entspricht.
BasePreferenceController hat APIs wie getAvailabilityStatus(), displayPreference(), handlePreferenceTreeClicked(), usw. Eine detaillierte Dokumentation für jede API finden Sie in der Schnittstellenklasse.
Eine Einschränkung bei der Implementierung von BasePreferenceController (und seinen Unterklassen wie TogglePreferenceController) besteht darin, dass die Konstruktorsignatur mit einer der folgenden übereinstimmen muss:
- public MyController(Context context, String key) {}
- public MyController(Context context) {}
Beim Installieren einer Einstellung für das Fragment bietet das Dashboard eine Methode zum Anhängen eines PreferenceController vor der Anzeigezeit. Bei der Installation wird der Controller mit dem Fragment verbunden, sodass alle zukünftigen relevanten Ereignisse an den Controller gesendet werden.
DashboardFragment enthält eine Liste von PreferenceControllers auf dem Bildschirm. Am onCreate() des Fragments werden alle Controller für die getAvailabilityStatus()-Methode aufgerufen. Wenn sie „true“ 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-Versionen
Ein PreferenceController enthält die gesamte Logik für die Interaktion mit der Einstellung, einschließlich der Anzeige, Aktualisierung, Suchindexierung usw.
Entsprechend den Interaktionen mit den Einstellungen hat die Schnittstelle von 
PreferenceController APIs isAvailable(), 
displayPreference(), handlePreferenceTreeClicked() usw. Eine detaillierte Dokumentation zu jeder API finden Sie in der Schnittstellenklasse.
Beim Installieren einer Einstellung für das Fragment bietet das Dashboard eine Methode zum Anhängen eines PreferenceController vor der Anzeigezeit. Bei der Installation wird der Controller mit dem Fragment verbunden, sodass alle zukünftigen relevanten Ereignisse an den Controller gesendet werden.
DashboardFragment zeigt eine Liste von PreferenceControllers
 auf dem Bildschirm an. Im onCreate() des Fragments werden alle Controller für die Methode isAvailable() aufgerufen. Wenn sie „true“ zurückgibt, wird displayPreference() aufgerufen, um die Anzeigelogik zu verarbeiten.
DashboardFragment verwenden
Eine Einstellung von Seite A auf Seite B verschieben
Wenn die Einstellung statisch in der XML-Datei der ursprünglichen Seite aufgeführt ist, folgen Sie der unten beschriebenen statischen Vorgehensweise für Ihre Android-Version. Andernfalls folgen Sie der dynamischen Vorgehensweise für die Verschiebung für Ihre Android-Version.
Statische Bewegung in Android 9
- Suchen Sie die XML-Dateien für die Einstellungen der ursprünglichen Seite und der Zielseite. Diese Informationen finden Sie in der getPreferenceScreenResId()-Methode der Seite.
- Entfernen Sie die Einstellung aus dem XML-Code der ursprünglichen Seite.
- Fügen Sie die Einstellung in die XML-Datei der Zielseite ein.
- Entfernen Sie die PreferenceControllerfür diese Einstellung aus der Java-Implementierung der Originalseite. Normalerweise ist sie increatePreferenceControllers(). Der Controller wird möglicherweise direkt in XML deklariert.Hinweis: Die Einstellung hat möglicherweise keine PreferenceController.
- Instanziieren Sie PreferenceControllerimcreatePreferenceControllers()der Zielseite. WennPreferenceControllerin der XML-Datei der alten Seite definiert ist, müssen Sie es auch in der XML-Datei der neuen Seite definieren.
Dynamisches Verschieben in Android 9
- Ermitteln Sie, in welcher Kategorie sich die ursprüngliche und die Zielseite befinden. Diese Informationen finden Sie unter DashboardFragmentRegistry.
- Öffnen Sie die Datei AndroidManifest.xml, die die Einstellung enthält, die Sie verschieben möchten, und suchen Sie den Aktivitätseintrag, der diese Einstellung repräsentiert.
- Legen Sie den Metadatenwert der Aktivität für com.android.settings.categoryauf den Kategorienschlüssel der neuen Seite fest.
Statische Bewegung in Android 8.x-Versionen
- Suchen Sie die XML-Dateien für die Einstellungen der ursprünglichen Seite und der Zielseite. Diese Informationen finden Sie in der
- Entfernen Sie die Einstellung aus dem XML-Code der Originalseite.
- Fügen Sie die Einstellung in die XML-Datei der Zielseite ein.
- Entfernen Sie das PreferenceControllerfür diese Einstellung in der Java-Implementierung der Originalseite. Normalerweise befindet sie sich ingetPreferenceControllers().
- Instanziieren Sie PreferenceControllerimgetPreferenceControllers()der Zielseite.
getPreferenceScreenResId()
-Methode der Seite.
Hinweis:Es ist möglich, dass die Einstellung keine PreferenceController hat.
Dynamisches Verschieben in Android 8.x-Versionen
- Ermitteln Sie, in welcher Kategorie sich die ursprüngliche und die Zielseite befinden. Diese Informationen finden Sie unter DashboardFragmentRegistry.
- Öffnen Sie die Datei AndroidManifest.xml, die die Einstellung enthält, die Sie verschieben möchten, und suchen Sie den Aktivitätseintrag, der diese Einstellung repräsentiert.
- Ändern Sie den Metadatenwert der Aktivität für com.android.settings.categoryund legen Sie den Wertpunkt auf den Kategorienschlüssel der neuen Seite fest.
Neue Einstellung auf einer Seite erstellen
Wenn die Einstellung statisch in der XML-Datei der ursprünglichen Seite aufgeführt ist, folgen Sie der statischen Vorgehensweise unten. Andernfalls folgen Sie der dynamischen Anleitung.
Statische Einstellung erstellen
- Suchen Sie die XML-Dateien für die Einstellungen der Seite. Sie finden diese Informationen in der Methode getPreferenceScreenResId() der Seite.
- Fügen Sie in der XML-Datei ein neues Preference-Element hinzu. Achten Sie darauf, dass sie eine eindeutige android:keyhat.
- 
Definieren Sie eine PreferenceControllerfür diese Einstellung in dergetPreferenceControllers()-Methode der Seite.- In Android 8.x und optional in Android 9 instanziieren Sie ein PreferenceControllerfür diese Einstellung in dercreatePreferenceControllers()-Methode der Seite.Wenn diese Einstellung bereits an anderen Stellen vorhanden war, gibt es möglicherweise schon eine PreferenceControllerdafür. Sie können diePreferenceControllerwiederverwenden, ohne eine neue erstellen zu müssen.
- 
Ab Android 9 können Sie die PreferenceControllerin XML neben der Einstellung deklarieren. Beispiel:<Preference android:key="reset_dashboard" android:title="@string/reset_dashboard_title" settings:controller="com.android.settings.system.ResetPreferenceController"/> 
 
- In Android 8.x und optional in Android 9 instanziieren Sie ein 
Dynamische Einstellung erstellen
- Ermitteln Sie, in welcher Kategorie sich die ursprüngliche und die Zielseite befinden. Diese Informationen finden Sie unter DashboardFragmentRegistry.
- Neue Aktivität in AndroidManifesterstellen
- 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.categoryauf denselben Wert fest, der in Schritt 1 definiert wurde.
Neue Seite erstellen
- Erstellen Sie ein neues Fragment, das von DashboardFragmentabgeleitet wird.
- 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 zum Hinzufügen der für diese Seite erforderlichen Einstellungen. Weitere Informationen finden Sie im Abschnitt Implementierung.
Zertifizierungsstufe
- Führen Sie die Robolectric-Tests in den Einstellungen aus. Alle vorhandenen und neuen Tests sollten bestanden werden.
- Erstellen und installieren Sie die Einstellungen und öffnen Sie dann die Seite, die geändert wird, manuell. Die Seite sollte sofort aktualisiert werden.
