Informationsarchitektur

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. Android 9 bietet einige Verbesserungen, die die Einstellungen noch nutzerfreundlicher machen.

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

Die 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 der alten Seite (implementiert als SettingsPreferencePage) auf eine neue Seite (implementiert mit DashboardFragment) kann schwierig 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.

Wir empfehlen dringend, für jede PreferenceController einen Unittest hinzuzufügen. Wenn die Änderung an AOSP gesendet wird, ist ein Unit-Test 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 von Plug-in-Steuerelementen für Einstellungen. 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 der 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 statisch implementieren. Die dynamische Einstellung kann jedoch in folgenden Fällen nützlich sein:

  • Die Einstellung ist nicht direkt in den Einstellungen implementiert (z. B. Einschleusen 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 ihr 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 einen zusammenfassenden Text hinzu, der angezeigt wird, 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 PreferenceControllers 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

Die Implementierung von PreferenceController unter Android 9 und Android 8.x unterscheidet sich, wie in diesem Abschnitt beschrieben.

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. Beispiel: 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, 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 hat APIs wie getAvailabilityStatus(), displayPreference() und handlePreferenceTreeClicked(),. Eine detaillierte Dokumentation für jede API befindet sich in der Interface-Klasse.

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 PreferenceControllers auf dem Bildschirm. 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 enthält die Benutzeroberfläche von PreferenceController die APIs isAvailable(), displayPreference(), handlePreferenceTreeClicked() usw. Eine detaillierte Dokumentation zu jeder API finden Sie in der Benutzeroberflächenklasse.

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 hält eine Liste von PreferenceControllers auf dem Bildschirm. Bei onCreate() des Fragments werden alle Controller für die Methode isAvailable() aufgerufen. Wenn diese Methode „wahr“ zurückgibt, wird displayPreference() aufgerufen, um die Anzeigelogik zu verarbeiten.

DashboardFragment verwenden

Eine Einstellung von Seite A nach 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. Andernfalls folgen Sie der dynamischen Verschiebeprozedur für Ihre Android-Version.

Statische Routen in Android 9

  1. Suchen Sie die XML-Dateien mit den Einstellungen für die ursprüngliche Seite und die Zielseite. Diese Informationen finden Sie in der getPreferenceScreenResId()-Methode der Seite.
  2. Entfernen Sie die Einstellung aus der XML-Datei der ursprünglichen Seite.
  3. Fügen Sie die Einstellung der XML-Datei der Zielseite hinzu.
  4. Entfernen Sie das PreferenceController für diese Einstellung aus der Java-Implementierung der ursprünglichen Seite. Normalerweise ist das createPreferenceControllers(). Der Controller kann auch direkt in XML deklariert werden.

    Hinweis: Die Einstellung hat möglicherweise keine PreferenceController.

  5. Erstellen Sie eine Instanz von PreferenceController im createPreferenceControllers() der Zielseite. Wenn PreferenceController in der alten Seite in XML definiert ist, definieren Sie es auch in XML für die neue Seite.

Dynamisches Verschieben unter Android 9

  1. Finden Sie heraus, zu welcher Kategorie die ursprüngliche und die Zielseite gehören. Diese Informationen finden Sie in DashboardFragmentRegistry.
  2. Öffnen Sie die Datei AndroidManifest.xml mit der Einstellung, die Sie verschieben möchten, und suchen Sie den Aktivitätseintrag, der diese Einstellung darstellt.
  3. 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-Releases

  1. Suchen Sie die XML-Dateien mit den Einstellungen für die ursprüngliche Seite und die Zielseite.
  2. Diese Informationen finden Sie in der getPreferenceScreenResId() -Methode der Seite.
  3. Entfernen Sie die Einstellung in der XML-Datei der ursprünglichen Seite.
  4. Fügen Sie die Einstellung in die XML-Datei der Zielseite ein.
  5. Entfernen Sie das PreferenceController für diese Einstellung in der Java-Implementierung der ursprünglichen Seite. Normalerweise ist das getPreferenceControllers().
  6. Hinweis:Möglicherweise gibt es für die Einstellung keine PreferenceController.

  7. Erstellen Sie eine Instanz von PreferenceController im getPreferenceControllers() der Zielseite.

Dynamisches Verschieben in Android 8.x-Releases

  1. Finden Sie heraus, zu welcher Kategorie die ursprüngliche und die Zielseite gehören. Sie finden diese Informationen unter DashboardFragmentRegistry.
  2. Öffnen Sie die Datei AndroidManifest.xml mit der Einstellung, die Sie verschieben möchten, und suchen Sie den Aktivitätseintrag, der diese Einstellung darstellt.
  3. Ä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

  1. Suchen Sie die XML-Dateien mit den Einstellungen für die Seite. Sie finden diese Informationen in der Methode „getPreferenceScreenResId()“ der Seite.
  2. Fügen Sie der XML-Datei ein neues Element „Preference“ hinzu. Die Fahrtbeschreibung muss eine eindeutige android:key haben.
  3. Definieren Sie in der getPreferenceControllers()-Methode der Seite einen PreferenceController für diese Einstellung.
    • Unter Android 8.x und optional unter Android 9 muss in der createPreferenceControllers()-Methode der Seite eine PreferenceController für diese Einstellung erstellt werden.

      Wenn diese Einstellung bereits an anderer Stelle vorhanden war, gibt es möglicherweise bereits eine PreferenceController dafür. Sie können die PreferenceController wiederverwenden, ohne eine neue zu erstellen.

    • Ab Android 9 können Sie die 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"/>

Dynamische Einstellung erstellen

  1. Finden Sie heraus, zu welcher Kategorie die ursprüngliche und die Zielseite gehören. Sie finden diese Informationen unter DashboardFragmentRegistry.
  2. Neue Aktivität in AndroidManifest erstellen
  3. 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 den in Schritt 1 definierten Wert fest.

Neue Seite erstellen

  1. Erstellen Sie ein neues Fragment, das von DashboardFragment erbt.
  2. 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.

  3. Folgen Sie der Anleitung, um die für diese Seite erforderlichen Einstellungen hinzuzufügen. Weitere Informationen finden Sie im Abschnitt Implementierung.

Zertifizierungsstufe

  • Führen Sie die Robolectric-Tests in den Einstellungen aus. Alle vorhandenen und neuen Tests sollten funktionieren.
  • Erstelle und installiere die Einstellungen und öffne dann die zu ändernde Seite manuell. Die Seite sollte sofort aktualisiert werden.