Informationsarchitektur

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

  1. Suchen Sie die bevorzugten XML-Dateien für die Originalseite und die Zielseite. Sie finden diese Informationen in der getPreferenceScreenResId() -Methode der Seite.
  2. Entfernen Sie die Einstellung aus dem XML der Originalseite.
  3. Fügen Sie die Einstellung zum XML der Zielseite hinzu.
  4. Entfernen Sie den PreferenceController für diese Einstellung aus der Java-Implementierung der Originalseite. Normalerweise ist es in createPreferenceControllers() . Der Controller kann direkt in XML deklariert werden.

    Hinweis : Die Einstellung verfügt möglicherweise nicht über einen PreferenceController .

  5. Instanziieren Sie den PreferenceController im createPreferenceControllers() der Zielseite. Wenn der PreferenceController auf der alten Seite in XML definiert ist, definieren Sie ihn auch für die neue Seite in XML.

Dynamischer Umzug in Android 9

  1. Finden Sie heraus, welche Kategorie die Original- und Zielseite hostet. Sie finden diese Informationen in DashboardFragmentRegistry .
  2. Ö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.
  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-Versionen

  1. Suchen Sie die bevorzugten XML-Dateien für die Originalseite und die Zielseite.
  2. Sie finden diese Informationen in der getPreferenceScreenResId() -Methode der Seite.
  3. Entfernen Sie die Einstellung im XML der Originalseite.
  4. Fügen Sie die Einstellung zum XML der Zielseite hinzu.
  5. Entfernen Sie den PreferenceController für diese Einstellung in der Java-Implementierung der Originalseite. Normalerweise ist es in getPreferenceControllers() .
  6. Hinweis : Es ist möglich, dass die Einstellung keinen PreferenceController hat.

  7. Instanziieren Sie den PreferenceController im getPreferenceControllers() der Zielseite.

Dynamischer Umzug in Android 8.x-Versionen

  1. Finden Sie heraus, welche Kategorie die Original- und Zielseite hostet. Sie finden diese Informationen in DashboardFragmentRegistry .
  2. Ö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.
  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.

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

  1. Suchen Sie die XML-Voreinstellungsdateien für die Seite. Sie finden diese Informationen in der getPreferenceScreenResId()-Methode der Seite.
  2. Fügen Sie im XML ein neues Einstellungselement hinzu. Stellen Sie sicher, dass es einen eindeutigen android:key hat.
  3. Definieren Sie einen PreferenceController für diese Einstellung in der getPreferenceControllers() -Methode der Seite.
    • Instanziieren Sie in Android 8.x und optional in Android 9 einen PreferenceController für diese Einstellung in der Methode createPreferenceControllers() der Seite.

      Wenn diese Präferenz bereits an anderen Stellen vorhanden war, gibt es möglicherweise bereits einen PreferenceController dafür. Sie können den PreferenceController 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"/>
      

Erstellen einer dynamischen Präferenz

  1. Finden Sie heraus, welche Kategorie die Original- und Zielseite hostet. Sie finden diese Informationen in DashboardFragmentRegistry .
  2. Erstellen Sie eine neue Aktivität in AndroidManifest
  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 denselben Wert fest, der in Schritt 1 definiert wurde.

Erstellen Sie eine neue Seite

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

  3. 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.