Mit Android 8.0 wurde eine neue Informationsarchitektur für die App „Einstellungen“ eingeführt, die die Organisation von Einstellungen vereinfacht und es Nutzern erleichtert, Einstellungen zum Anpassen ihrer Android-Geräte schnell zu finden. Mit Android 9 wurden einige Verbesserungen eingeführt, um mehr Einstellungen und eine einfachere Implementierung zu bieten.
Beispiele und Quelle
Die meisten Seiten in den Einstellungen werden derzeit mit dem neuen Framework implementiert. Ein gutes Beispiel 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
- Abstrakte Präferenzen-Controller:
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äteherstellern wird empfohlen, die vorhandene Architektur mit Einstellungsinformationen anzupassen und bei Bedarf zusätzliche Einstellungsseiten einzufügen, um partnerspezifische Funktionen zu berücksichtigen. Das Verschieben von Einstellungen von einer Legacy-Seite (implementiert als SettingsPreferencePage
) auf eine neue Seite, die mit DashboardFragment
implementiert wurde, kann kompliziert sein. Die Einstellung von der Legacy-Seite wurde wahrscheinlich nicht mit einer PreferenceController
implementiert.
Wenn Sie also Einstellungen von einer Legacy-Seite auf eine neue Seite verschieben, müssen Sie eine PreferenceController
erstellen und den Code in den Controller verschieben, bevor Sie ihn auf der neuen DashboardFragment
instanziieren. Die von PreferenceController
erforderlichen APIs sind in ihrem Namen beschrieben und in Javadoc dokumentiert.
Es wird dringend empfohlen, für jede PreferenceController
einen Unittest 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 Readme-Datei packages/apps/Settings/tests/robotests/README.md
.
Informationsarchitektur im Plug-in-Stil
Jedes Einstellungselement wird als Einstellung implementiert. Präferenzen lassen sich ganz einfach von einer Seite auf eine andere verschieben.
Um das Verschieben mehrerer Einstellungen zu erleichtern, wurde mit Android 8.0 ein Hostfragment im Plug-in-Stil eingeführt, das Einstellungselemente enthält. Einstellungselemente werden als Controller im Plug-in-Stil modelliert. Daher besteht eine Einstellungsseite aus einem einzelnen Hostfragment und mehreren Einstellungs-Controllern.
Dashboard-Fragment
DashboardFragment
ist der Host von bevorzugten Controllern im Plug-in-Stil.
Das Fragment übernimmt die Einstellungen von PreferenceFragment
und verfügt über Hooks zum Erweitern und Aktualisieren von statischen und dynamischen Einstellungslisten.
Statische Einstellungen
Eine statische Einstellungsliste 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
definiert (wie unten erläutert) und über ein FeatureProvider
(definiert als
DashboardFeatureProvider
) geladen.
Dynamische Einstellungen sind komplexer als statisch konfigurierte Einstellungen. Daher sollten Entwickler die Einstellung in der Regel als statische Einstellungen implementieren. Die dynamische Einstellung kann jedoch nützlich sein, wenn eine der folgenden Bedingungen zutrifft:
- Die Einstellung ist nicht direkt in der App „Einstellungen“ implementiert. Beispielsweise wird eine von OEM-/Mobilfunkanbieter-Apps implementierte Einstellung eingefügt.
- 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 und wird in
CategoryKey
definiert. - Optional: Fügen Sie eine Zusammenfassung hinzu, wenn die Einstellung angezeigt 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>
Beim Rendern fordert das Fragment eine Liste von Einstellungen sowohl aus dem statischen XML als auch den dynamischen Einstellungen an, die in AndroidManifest
definiert sind. 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). Dann werden sie in der UI als gemischte Liste angezeigt.
Präferenz-Controller
Zwischen der Implementierung von PreferenceController
in Android 9 und Android 8.x gibt es Unterschiede, die in diesem Abschnitt beschrieben werden.
PreferenceController in 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 abgeleitete Klassen von BasePreferenceController
, die jeweils einem bestimmten UI-Stil zugeordnet sind, der von der App „Einstellungen“ standardmäßig unterstützt wird. TogglePreferenceController
hat beispielsweise eine API, die direkt der Interaktion des Nutzers mit einer Ein/Aus-Schaltfläche für Einstellungen zugeordnet ist.
BasePreferenceController
enthält APIs wie getAvailabilityStatus()
, displayPreference()
oder handlePreferenceTreeClicked(),
. Eine ausführliche Dokumentation für jede API finden Sie in der Schnittstellenklasse.
Eine Einschränkung für die Implementierung von BasePreferenceController
(und dessen abgeleiteten Klassen wie TogglePreferenceController
) besteht darin, dass die Konstruktorsignatur einer der folgenden Optionen entsprechen muss:
public MyController(Context context, String key) {}
public MyController(Context context) {}
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 PreferenceController
s auf dem Bildschirm bei. Im onCreate()
des Fragments werden alle Controller für die Methode getAvailabilityStatus()
aufgerufen. Wenn sie "true" zurückgibt, wird displayPreference()
zur Verarbeitung der Anzeigelogik aufgerufen.
getAvailabilityStatus()
ist auch wichtig, um dem Einstellungen-Framework mitzuteilen, welche Elemente während 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 Präferenzinteraktionen verfügt die Schnittstelle von
PreferenceController
über die APIs isAvailable()
,
displayPreference()
, handlePreferenceTreeClicked()
usw. Eine detaillierte Dokumentation zu den einzelnen APIs finden Sie in der Schnittstellenklasse.
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 Methode isAvailable()
aufgerufen. Wenn sie "true" zurückgibt, wird displayPreference()
zur Verarbeitung der Anzeigelogik aufgerufen.
DashboardFragment verwenden
Eine Einstellung von Seite A nach B verschieben
Wenn die Einstellung statisch in der bevorzugten XML-Datei der Originalseite aufgeführt ist, folgen Sie der statischen Verschiebung für Ihren Android-Release unten. Folgen Sie andernfalls dem dynamischen Verschiebungsvorgang für Ihren Android-Release.
Statischer Umzug in Android 9
- Suchen Sie die bevorzugten XML-Dateien für die Originalseite und die Zielseite. Sie finden diese Informationen in der Methode
getPreferenceScreenResId()
der Seite. - Entfernen Sie die Einstellung aus der XML-Datei der Originalseite.
- Fügen Sie die Einstellung in der XML-Datei der Zielseite hinzu.
- Entfernen Sie
PreferenceController
für diese Einstellung aus der Java-Implementierung der Originalseite. Normalerweise befindet sie sich increatePreferenceControllers()
. Der Controller kann direkt in XML deklariert werden.Hinweis: Die Einstellung hat möglicherweise keinen
PreferenceController
-Wert. - Instanziieren Sie
PreferenceController
imcreatePreferenceControllers()
der Zielseite. WennPreferenceController
auf der alten Seite in XML definiert ist, definiere es auch für die neue Seite in XML.
Dynamische Veränderungen in Android 9
- Ermitteln Sie, welche Kategorie die Originalseite und die Zielseite hosten. 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. - 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 bevorzugten XML-Dateien für die Originalseite und die Zielseite. Sie finden diese Informationen in der
- Entfernen Sie die Einstellung in der XML-Datei der Originalseite.
- Fügen Sie die Einstellung der XML-Datei der Zielseite hinzu.
- Entfernen Sie
PreferenceController
für diese Einstellung in der Java-Implementierung der Originalseite. Normalerweise befindet sie sich ingetPreferenceControllers()
. - Instanziieren Sie
PreferenceController
imgetPreferenceControllers()
der Zielseite.
getPreferenceScreenResId()
-Methode der Seite.
Hinweis:Möglicherweise hat die Einstellung keine PreferenceController
.
Dynamische Verschiebung in Android 8.x-Releases
- Ermitteln Sie, welche Kategorie die Originalseite und die Zielseite hosten. Die entsprechenden Informationen finden Sie 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 statisch in der bevorzugten XML-Datei der Originalseite aufgeführt ist, folge der statischen Vorgehensweise unten. Folgen Sie andernfalls dem dynamischen Verfahren.
Statische Einstellung erstellen
- Suche nach den bevorzugten XML-Dateien für die Seite. Sie finden diese Informationen in der Methode getPreferenceScreenResId() der Seite.
- Fügen Sie ein neues Einstellungselement in der XML-Datei hinzu. Er muss eine eindeutige
android:key
haben. -
Definiere in der
getPreferenceControllers()
-Methode der Seite einePreferenceController
für diese Einstellung.- In Android 8.x und optional in Android 9 muss ein
PreferenceController
für diese Einstellung in dercreatePreferenceControllers()
-Methode der Seite instanziiert werden.Wenn diese Einstellung bereits an anderen Stellen existiert, ist möglicherweise bereits ein
PreferenceController
dafür vorhanden. Sie können diePreferenceController
wiederverwenden, ohne ein neues erstellen zu müssen. -
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"/>
- In Android 8.x und optional in Android 9 muss ein
Dynamische Einstellungen erstellen
- Ermitteln Sie, welche Kategorie die Originalseite und die Zielseite hosten. Die entsprechenden Informationen finden Sie unter
DashboardFragmentRegistry
. - Neue Aktivität in
AndroidManifest
erstellen - Füge der neuen Activity-Klasse 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
- Erstellt ein neues Fragment, das die Übernahme von
DashboardFragment
übernimmt. - Definieren Sie die Kategorie in
DashboardFragmentRegistry
.Hinweis:Dieser Schritt ist optional. Wenn Sie keine dynamischen Einstellungen auf dieser Seite benötigen, müssen Sie keinen Kategorieschlüssel angeben.
- Führen Sie die Schritte zum Hinzufügen der Einstellungen aus, die für diese Seite erforderlich sind. Weitere Informationen finden Sie im Abschnitt Implementierung.
Zertifizierungsstufe
- Führe 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.