Mit Android 8.0 wurde eine neue Informationsarchitektur für die Einstellungen-App eingeführt, um die Organisation der Einstellungen zu vereinfachen und es Benutzern zu erleichtern, schnell Einstellungen zum Anpassen ihrer Android-Geräte zu finden. Mit Android 9 wurden einige Verbesserungen eingeführt, um mehr Einstellungsfunktionen und eine einfachere Implementierung bereitzustellen.
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
- 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 bestehende Informationsarchitektur für Einstellungen anzupassen und bei Bedarf zusätzliche Einstellungsseiten einzufügen, um partnerspezifische Funktionen zu berücksichtigen. Das Verschieben von Einstellungen von einer alten Seite (implementiert als SettingsPreferencePage
) auf eine neue Seite (implementiert mit DashboardFragment
) kann kompliziert sein. Die Präferenz von der Legacy-Seite wird wahrscheinlich nicht mit einem PreferenceController
implementiert.
Wenn Sie also 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 im neuen DashboardFragment
instanziieren. Die PreferenceController
benötigten APIs sind in ihrem Namen beschrieben und in Javadoc dokumentiert.
Es wird dringend empfohlen, für jeden PreferenceController
einen Komponententest hinzuzufügen. Wenn die Änderung an AOSP übermittelt wird, ist ein Komponententest erforderlich. Weitere Informationen zum Schreiben von Robolectric-basierten Tests finden Sie in der Readme-Datei packages/apps/Settings/tests/robotests/README.md
.
Informationsarchitektur im Plugin-Stil
Jedes Einstellungselement wird als Präferenz implementiert. Eine Präferenz kann leicht von einer Seite auf eine andere verschoben werden.
Um das Verschieben mehrerer Einstellungen zu erleichtern, hat Android 8.0 ein Hostfragment im Plugin-Stil eingeführt, das Einstellungselemente enthält. Einstellungselemente werden als Controller im Plugin-Stil modelliert. Daher besteht eine Einstellungsseite aus einem einzelnen Hostfragment und mehreren Einstellungscontrollern.
DashboardFragment
DashboardFragment
ist der Host von Präferenz-Controllern im Plugin-Stil. Das Fragment erbt von PreferenceFragment
und verfügt über Hooks zum Erweitern und Aktualisieren sowohl statischer als auch dynamischer Präferenzlisten.
Statische Präferenzen
Eine statische Präferenzliste wird in XML mithilfe des <Preference>
-Tags definiert. Eine DashboardFragment
Implementierung verwendet die Methode getPreferenceScreenResId()
, um zu definieren, welche XML-Datei die statische Liste der anzuzeigenden Einstellungen enthält.
Dynamische Einstellungen
Ein dynamisches Element stellt eine Kachel mit Absicht dar, die zu einer externen oder internen Aktivität führt. Normalerweise führt die Absicht zu einer anderen Einstellungsseite. Beispielsweise ist das Einstellungselement „Google“ auf der Startseite „Einstellungen“ ein dynamisches Element. Dynamische Elemente werden in AndroidManifest
definiert (siehe unten) und über einen FeatureProvider
(definiert als DashboardFeatureProvider
) geladen.
Dynamische Einstellungen sind wichtiger als statisch konfigurierte Einstellungen, daher sollten Entwickler die Einstellung normalerweise als statische Einstellung implementieren. Die dynamische Einstellung kann jedoch nützlich sein, wenn eine der folgenden Bedingungen zutrifft:
- Die Einstellung wird nicht direkt in der Einstellungen-App implementiert (z. B. das Einfügen einer von OEM-/Carrier-Apps implementierten Einstellung).
- 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.
Gehen Sie wie folgt vor, um eine Aktivität als dynamische Einstellung zu konfigurieren:
- Markieren Sie die Aktivität als dynamische Einstellung, indem Sie der Aktivität einen Absichtsfilter hinzufügen.
- Teilen Sie der App „Einstellungen“ mit, zu welcher Kategorie sie gehört. Die Kategorie ist eine Konstante, definiert in
CategoryKey
. - Optional: Fügen Sie einen zusammenfassenden Text hinzu, wenn die Einstellung angezeigt wird.
Hier ist ein Beispiel aus der Settings-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 fragt das Fragment nach einer Liste von Einstellungen sowohl aus statischem XML als auch aus dynamischen Einstellungen, die in AndroidManifest
definiert sind. Unabhängig davon, ob die PreferenceController
in Java-Code oder in XML definiert sind, verwaltet DashboardFragment
die Verarbeitungslogik jeder Einstellung über PreferenceController
(siehe unten). Anschließend werden sie in der Benutzeroberfläche als gemischte Liste angezeigt.
PreferenceController
Es gibt Unterschiede zwischen der Implementierung PreferenceController
in Android 9 und Android 8.x, wie in diesem Abschnitt beschrieben.
PreferenceController in der Android 9-Version
Ein PreferenceController
enthält die gesamte Logik zur Interaktion mit der Präferenz, einschließlich Anzeige, Aktualisierung, Suchindizierung usw.
Die Schnittstelle von PreferenceController
ist als BasePreferenceController
definiert. Siehe beispielsweise Code in packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java
Es gibt mehrere Unterklassen von BasePreferenceController
, die jeweils einem bestimmten UI-Stil zugeordnet sind, den die Einstellungen-App standardmäßig unterstützt. TogglePreferenceController
verfügt beispielsweise über eine API, die direkt zuordnet, wie der Benutzer mit einer umschaltbaren Einstellungs-Benutzeroberfläche interagieren soll.
BasePreferenceController
verfügt über APIs wie getAvailabilityStatus()
, displayPreference()
, handlePreferenceTreeClicked(),
usw. Eine detaillierte Dokumentation für jede API befindet sich in der Schnittstellenklasse.
Eine Einschränkung bei der Implementierung BasePreferenceController
(und seinen Unterklassen wie TogglePreferenceController
) besteht darin, dass die Konstruktorsignatur mit einer der folgenden Angaben übereinstimmen muss:
-
public MyController(Context context, String key) {}
-
public MyController(Context context) {}
Beim Installieren einer Präferenz 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
führt eine Liste von PreferenceController
s auf dem Bildschirm. Beim onCreate()
des Fragments werden alle Controller für die getAvailabilityStatus()
Methode aufgerufen, und wenn sie „true“ zurückgibt, wird displayPreference()
aufgerufen, um die Anzeigelogik zu verarbeiten. getAvailabilityStatus()
ist auch wichtig, um dem Einstellungsframework mitzuteilen, welche Elemente während der Suche verfügbar sind. PreferenceController in Android 8.x-Versionen
Ein PreferenceController
enthält die gesamte Logik zur Interaktion mit der Präferenz, einschließlich Anzeige, Aktualisierung und Suchindizierung. usw.
Entsprechend den Präferenzinteraktionen verfügt die Schnittstelle von PreferenceController
über die APIs isAvailable()
, displayPreference()
, handlePreferenceTreeClicked()
usw. Eine detaillierte Dokumentation zu jeder API finden Sie in der Schnittstellenklasse.
Beim Installieren einer Präferenz 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
führt eine Liste der PreferenceControllers
auf dem Bildschirm. Beim onCreate()
des Fragments werden alle Controller für die Methode isAvailable()
aufgerufen, und wenn sie „true“ zurückgibt, wird displayPreference()
aufgerufen, um die Anzeigelogik zu verarbeiten.
Verwenden von DashboardFragment
Verschieben einer Präferenz von Seite A nach B
Wenn die Einstellung statisch in der Einstellungs-XML-Datei der Originalseite aufgeführt ist, befolgen Sie das unten stehende Verfahren zum statischen Verschieben für Ihre Android-Version. Befolgen Sie andernfalls das Verfahren zum dynamischen Verschieben für Ihre Android-Version.
Statischer Umzug in Android 9
- Suchen Sie die bevorzugten XML-Dateien für die Originalseite und die Zielseite. Sie finden diese Informationen in der
getPreferenceScreenResId()
-Methode der Seite. - Entfernen Sie die Einstellung aus dem XML der Originalseite.
- Fügen Sie die Einstellung zum XML der Zielseite hinzu.
- Entfernen Sie den
PreferenceController
für diese Einstellung aus der Java-Implementierung der Originalseite. Normalerweise ist es increatePreferenceControllers()
. Der Controller kann direkt in XML deklariert werden.Hinweis : Die Einstellung verfügt möglicherweise nicht über einen
PreferenceController
. - Instanziieren Sie den
PreferenceController
imcreatePreferenceControllers()
der Zielseite. Wenn derPreferenceController
auf der alten Seite in XML definiert ist, definieren Sie ihn auch für die neue Seite in XML.
Dynamischer Umzug in Android 9
- Finden Sie heraus, welche Kategorie die Original- und Zielseite hostet. Sie finden diese Informationen in
DashboardFragmentRegistry
. - Öffnen Sie die Datei
AndroidManifest.xml
, die die Einstellung enthält, die Sie verschieben müssen, 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.
Statische Verschiebung in Android 8.x-Versionen
- Suchen Sie die bevorzugten XML-Dateien für die Originalseite und die Zielseite. Sie finden diese Informationen in der
- Entfernen Sie die Einstellung im XML der Originalseite.
- Fügen Sie die Einstellung zum XML der Zielseite hinzu.
- Entfernen Sie den
PreferenceController
für diese Einstellung in der Java-Implementierung der Originalseite. Normalerweise ist es ingetPreferenceControllers()
. - Instanziieren Sie den
PreferenceController
imgetPreferenceControllers()
der Zielseite.
getPreferenceScreenResId()
-Methode der Seite. Hinweis : Es ist möglich, dass die Einstellung keinen PreferenceController
hat.
Dynamischer Umzug in Android 8.x-Versionen
- Finden Sie heraus, welche Kategorie die Original- und Zielseite hostet. Sie finden diese Informationen in
DashboardFragmentRegistry
. - Öffnen Sie die Datei
AndroidManifest.xml
, die die Einstellung enthält, die Sie verschieben müssen, und suchen Sie den Aktivitätseintrag, der diese Einstellung darstellt. - Ä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.
Erstellen einer neuen Einstellung auf einer Seite
Wenn die Voreinstellung statisch in der Voreinstellungs-XML-Datei der Originalseite aufgeführt ist, befolgen Sie das unten stehende statische Verfahren. Andernfalls folgen Sie dem dynamischen Verfahren.
Erstellen einer statischen Präferenz
- Suchen Sie die XML-Voreinstellungsdateien für die Seite. Sie finden diese Informationen in der getPreferenceScreenResId()-Methode der Seite.
- Fügen Sie im XML ein neues Einstellungselement hinzu. Stellen Sie sicher, dass es einen eindeutigen
android:key
hat. - Definieren Sie einen
PreferenceController
für diese Einstellung in dergetPreferenceControllers()
-Methode der Seite.- Instanziieren Sie in Android 8.x und optional in Android 9 einen
PreferenceController
für diese Einstellung in der MethodecreatePreferenceControllers()
der Seite.Wenn diese Präferenz bereits an anderen Stellen vorhanden war, gibt es möglicherweise bereits einen
PreferenceController
dafür. Sie können denPreferenceController
wiederverwenden, ohne einen neuen zu erstellen. - Ab Android 9 können Sie den
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"/>
- Instanziieren Sie in Android 8.x und optional in Android 9 einen
Erstellen einer dynamischen Präferenz
- Finden Sie heraus, welche Kategorie die Original- und Zielseite hostet. Sie finden diese Informationen in
DashboardFragmentRegistry
. - Erstellen Sie eine neue Aktivität in
AndroidManifest
- 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.
Erstellen Sie eine neue Seite
- Erstellen Sie ein neues Fragment, das von
DashboardFragment
erbt. - Definieren Sie seine 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.
- Befolgen Sie die Schritte zum Hinzufügen der für diese Seite erforderlichen Einstellungen. Weitere Informationen finden Sie im Abschnitt „Implementierung“ .
Validierung
- Führen Sie die roboelektrischen Tests in den Einstellungen aus. Alle bestehenden und neuen Tests sollten bestanden werden.
- Erstellen und installieren Sie Einstellungen und öffnen Sie dann manuell die Seite, die geändert werden soll. Die Seite sollte sofort aktualisiert werden.