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
CategoryKey
definiert 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 PreferenceController
s 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
PreferenceController
fü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
PreferenceController
imcreatePreferenceControllers()
der Zielseite. WennPreferenceController
in 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.category
auf 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
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: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.category
und 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:key
hat. -
Definieren Sie eine
PreferenceController
für diese Einstellung in dergetPreferenceControllers()
-Methode der Seite.- In Android 8.x und optional in Android 9 instanziieren Sie ein
PreferenceController
für diese Einstellung in dercreatePreferenceControllers()
-Methode der Seite.Wenn diese Einstellung bereits an anderen Stellen vorhanden war, gibt es möglicherweise schon eine
PreferenceController
dafür. Sie können diePreferenceController
wiederverwenden, ohne eine neue erstellen zu müssen. -
Ab Android 9 können Sie die
PreferenceController
in 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
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
abgeleitet 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.