Architektura informacji

W Androidzie 8.0 wprowadzono nową architekturę informacji w aplikacji Ustawienia, aby uprościć sposób ich organizacji i ułatwić użytkownikom szybkie znajdowanie ustawień do personalizacji urządzeń z Androidem. Android 9 wprowadził kilka ulepszeń, które zwiększają funkcjonalność ustawień i ułatwiają implementację.

Przykłady i źródło

Większość stron w sekcji Ustawienia jest obecnie implementowana za pomocą nowego frameworku. Dobrym przykładem jest DisplaySettings: packages/apps/Settings/src/com/android/settings/DisplaySettings.java

Ścieżki do plików ważnych komponentów:

  • kluczKategorii: 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 (wprowadzony w Androidzie 9):packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

Implementacja

Producentów urządzeń zachęcamy do dostosowania istniejącej architektury informacji w ustawieniach i do dodania dodatkowych stron ustawień w celu uwzględnienia funkcji partnerów. Przenoszenie ustawień ze starszej strony (implementowanej za pomocą funkcji SettingsPreferencePage) na nową stronę (implementowaną za pomocą funkcji DashboardFragment) może być skomplikowane. Ustawienie ze starszej strony prawdopodobnie nie jest zaimplementowane za pomocą funkcji PreferenceController.

Dlatego podczas przenoszenia ustawień ze starej strony na nową musisz utworzyć PreferenceController i przesunąć kod do kontrolera przed jego utworzeniem w nowym DashboardFragment. Interfejsy API wymagane przez usługę PreferenceController są opisane w jej nazwie i opisane w dokumentacji Javadoc.

Zdecydowanie zalecamy dodanie testu jednostkowego dla każdego PreferenceController. Jeśli zmiana zostanie przesłana do AOSP, wymagany jest test jednostkowy. Więcej informacji o pisaniu testów opartych na Robolectric znajdziesz w pliku readme packages/apps/Settings/tests/robotests/README.md.

Architektura informacji w stylu wtyczki

Każdy element ustawień jest implementowany jako ustawienie. Ustawienia można łatwo przenosić z jednej strony na inną.

Aby ułatwić przenoszenie wielu ustawień, w Androidzie 8.0 wprowadzono fragment hosta w stylu wtyczki, który zawiera elementy ustawień. Elementy ustawień są modelowane jako kontrolery w stylu wtyczki. Strona ustawień jest więc tworzona przez pojedynczy fragment hosta i wiele kontrolerów ustawień.

DashboardFragment

DashboardFragment jest hostem sterowników ustawień w stylu wtyczki. Fragment dziedziczy z PreferenceFragment i zawiera elementy wywołujące, które umożliwiają rozszerzanie i aktualizowanie zarówno statycznych, jak i dynamicznych list preferencji.

Ustawienia statyczne

Lista preferencji statycznych jest definiowana w pliku XML za pomocą tagu <Preference>. Wdrożenie DashboardFragment używa metody getPreferenceScreenResId(), aby określić, który plik XML zawiera stałą listę preferencji do wyświetlenia.

Dynamiczne ustawienia

Element dynamiczny reprezentuje kartę z intencją, która prowadzi do aktywności zewnętrznej lub wewnętrznej. Zwykle prowadzi ona do innej strony ustawień. Na przykład element „Google” na stronie głównej Ustawień jest elementem dynamicznym. Elementy dynamiczne są definiowane w pliku AndroidManifest (omówionym poniżej) i ładowane za pomocą pliku FeatureProvider (zdefiniowanego jako DashboardFeatureProvider).

Ustawienia dynamiczne są bardziej obciążające niż skonfigurowane statycznie, dlatego programiści powinni stosować je jako statyczne. Ustawienie dynamiczne może być jednak przydatne, gdy spełniony jest dowolny z tych warunków:

  • ustawienie nie jest implementowane bezpośrednio w aplikacji Ustawienia (np. poprzez wstrzyknięcie ustawienia zaimplementowanego przez aplikacje OEM lub operatora);
  • Ustawienie powinno pojawić się na stronie głównej Ustawienia.
  • Masz już aktywność dla tego ustawienia i nie chcesz stosować dodatkowej konfiguracji statycznej.

Aby skonfigurować aktywność jako ustawienie dynamiczne:

  • Oznacz działanie jako ustawienie dynamiczne, dodając do niego filtr intencji.
  • Powiedz aplikacji Ustawienia, do której kategorii należy. Kategoria jest stałą wartością zdefiniowaną w pliku CategoryKey.
  • Opcjonalnie: dodaj tekst podsumowania, który będzie wyświetlany po wybraniu ustawienia.

Oto przykład z aplikacji Ustawienia dla 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>

W momencie renderowania fragment poprosi o listę preferencji z zarówno statycznych elementów XML, jak i ustawień dynamicznych zdefiniowanych w pliku AndroidManifest. Niezależnie od tego, czy PreferenceController są zdefiniowane w kodzie Java czy w pliku XML, DashboardFragment zarządza logiką obsługi każdego ustawienia za pomocą PreferenceController (omówionego poniżej). Następnie są wyświetlane w interfejsie jako lista mieszana.

PreferenceController

W tym rozdziale opisujemy różnice między implementacją PreferenceController w Androidzie 9 a Androidem 8.x.

PreferenceController w wersji Androida 9

Obiekt PreferenceController zawiera całą logikę dotyczącą interakcji z preferencją, w tym wyświetlanie, aktualizowanie, indeksowanie w wyszukiwarce itp.

Interfejs PreferenceController jest zdefiniowany jako BasePreferenceController. Przykładowy kod znajdziesz na stronie:packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

Istnieje kilka podklas BasePreferenceController, z których każda odpowiada określonemu stylowi interfejsu obsługiwanemu domyślnie przez aplikację Ustawienia. Na przykład TogglePreferenceController ma interfejs API, który bezpośrednio odzwierciedla sposób interakcji użytkownika z interfejsem ustawień opartym na przełącznikach.

BasePreferenceController ma interfejsy API takie jak getAvailabilityStatus(), displayPreference(), handlePreferenceTreeClicked(), itp. Szczegółowe informacje o każdym interfejsie API znajdują się w klasie interfejsu.

Ograniczenie implementacji klasy BasePreferenceController (i jej podklas, np. TogglePreferenceController) polega na tym, że sygnatura konstruktora musi być zgodna z jednym z tych elementów:

  • public MyController(Context context, String key) {}
  • public MyController(Context context) {}

Podczas instalowania preferencji do fragmentu panel oferuje metodę dołączania PreferenceController przed czasem wyświetlania. Podczas instalacji kontroler jest podłączony do fragmentu, dzięki czemu wszystkie przyszłe zdarzenia są wysyłane do kontrolera.

DashboardFragment przechowuje na ekranie listę PreferenceController. W miejscu fragmentu onCreate() wywoływane są wszystkie kontrolery dla metody getAvailabilityStatus(), a jeśli zwróci ona wartość true, wywoływana jest metoda displayPreference(), która przetwarza logikę wyświetlania. getAvailabilityStatus() jest też ważne, aby poinformować framework ustawień, które elementy są dostępne podczas wyszukiwania.

PreferenceController w wersjach Androida 8.x

Obiekt PreferenceController zawiera całą logikę interakcji z preferencją, w tym wyświetlanie, aktualizowanie, indeksowanie w wyszukiwarce itp.

W zależności od interakcji z preferencjami interfejs PreferenceController ma interfejsy API isAvailable(), displayPreference(), handlePreferenceTreeClicked() itp. Szczegółową dokumentację każdego interfejsu API znajdziesz w klasie interfejsu.

Podczas instalowania preferencji do fragmentu panel oferuje metodę dołączania PreferenceController przed czasem wyświetlania. Podczas instalacji kontroler jest podłączony do fragmentu, dzięki czemu wszystkie przyszłe zdarzenia są wysyłane do kontrolera.

DashboardFragment wyświetla na ekranie listę PreferenceControllers . W miejscu onCreate() fragmentu wywoływane są wszystkie kontrolery dla metody isAvailable(), a jeśli zwróci ona wartość true, wywoływana jest metoda displayPreference(), aby przetworzyć logikę wyświetlania.

Używanie DashboardFragment

Przenoszenie ustawienia z strony A na stronę B

Jeśli ustawienie jest wymienione statycznie w pliku XML preferencji oryginalnej strony, wykonaj poniżej procedurę przenoszenia statycznego dla wersji Androida. W przeciwnym razie postępuj zgodnie z procedurą przenoszenia Dynamic w przypadku wersji na Androida.

Przenoszenie statyczne w Androidzie 9

  1. Znajdź pliki XML ustawień oryginalnej strony i strony docelowej. Te informacje znajdziesz w metodie getPreferenceScreenResId() strony.
  2. Usuń ustawienie z pliku XML oryginalnej strony.
  3. Dodaj ustawienie do pliku XML strony docelowej.
  4. Usuń z implementacji Javy oryginalnej strony element PreferenceController odpowiadający tej opcji. Zazwyczaj jest to createPreferenceControllers(). Kontroler może być zadeklarowany bezpośrednio w pliku XML.

    Uwaga: ustawienie może nie mieć wartości PreferenceController.

  5. Utwórz instancję klasy PreferenceController w bloku createPreferenceControllers() na stronie docelowej. Jeśli element PreferenceController jest zdefiniowany w pliku XML starej strony, zdefiniuj go też w pliku XML nowej strony.

Dynamiczne przenoszenie w Androidzie 9

  1. Sprawdź, do której kategorii należy strona docelowa i oryginalna. Te informacje znajdziesz na stronie DashboardFragmentRegistry.
  2. Otwórz plik AndroidManifest.xml, który zawiera ustawienie, które chcesz przenieść, i znajdź wpis Aktywność reprezentujący to ustawienie.
  3. Ustaw wartość metadanych aktywności com.android.settings.category na klucz kategorii nowej strony.

Statyczne przenoszenie w wersjach Androida 8.x

  1. Znajdź pliki XML ustawień oryginalnej strony i strony docelowej.
  2. Te informacje znajdziesz w metodzie getPreferenceScreenResId() strony.
  3. Usuń ustawienie z pliku XML oryginalnej strony.
  4. Dodaj ustawienie do pliku XML strony docelowej.
  5. Usuń element PreferenceController dla tej opcji w implementacji w języku Java na oryginalnej stronie. Zwykle jest to getPreferenceControllers().
  6. Uwaga: może się zdarzyć, że ustawienie nie ma wartości PreferenceController.

  7. Utwórz instancję klasy PreferenceController w bloku getPreferenceControllers() na stronie docelowej.

Dynamiczny ruch w wersjach Androida 8.x

  1. Sprawdź, do której kategorii należy strona docelowa i oryginalna. Te informacje znajdziesz na stronie DashboardFragmentRegistry.
  2. Otwórz plik AndroidManifest.xml, który zawiera ustawienie, które chcesz przenieść, i znajdź wpis Aktywność reprezentujący to ustawienie.
  3. Zmień wartość metadanych aktywności w przypadku com.android.settings.category, ustaw punkt wartości na klucz kategorii nowej strony.

Tworzenie nowych ustawień na stronie

Jeśli ustawienie jest wymienione statycznie w pliku XML z ustawieniami oryginalnej strony, wykonaj podaną niżej procedurę statyczną. W przeciwnym razie postępuj zgodnie z procedurą dynamiczną.

Tworzenie preferencji statycznej

  1. Znajdź pliki XML ustawień strony. Te informacje można znaleźć w metodzie getPreferenceScreenResId() strony.
  2. Dodaj nowy element preferencji w pliku XML. Upewnij się, że ma unikalny android:key.
  3. W metodzie getPreferenceControllers() strony zdefiniuj parametr PreferenceController dla tej preferencji.
    • W Androidzie 8.x i opcjonalnie 9 utwórz instancję klasy PreferenceController dla tej preferencji w metodzie createPreferenceControllers() strony.

      Jeśli te ustawienia były już używane w innych miejscach, być może istnieje już dla nich PreferenceController. Możesz ponownie użyć PreferenceController bez tworzenia nowego.

    • Od Androida 9 możesz zadeklarować element PreferenceController w pliku XML obok preferencji. Przykład:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>

Tworzenie preferencji dynamicznych

  1. Sprawdź, do której kategorii należy strona docelowa i oryginalna. Te informacje znajdziesz na stronie DashboardFragmentRegistry.
  2. Utwórz nową aktywność w AndroidManifest
  3. Dodaj do nowej aktywności niezbędne metadane, aby zdefiniować ustawienie. Ustaw wartość metadanych com.android.settings.category na tę samą wartość, która została zdefiniowana w kroku 1.

Utwórz nową stronę

  1. Utwórz nowy fragment, dziedziczący z poziomu DashboardFragment.
  2. Określ kategorię w parametrye DashboardFragmentRegistry.

    Uwaga: ten krok jest opcjonalny. Jeśli nie potrzebujesz żadnych ustawień dynamicznych na tej stronie, nie musisz podawać klucza kategorii.

  3. Wykonaj czynności opisane w sekcji dotyczącej dodawania ustawień potrzebnych na tej stronie. Więcej informacji znajdziesz w sekcji Implementacja.

Weryfikacja

  • Uruchom testy robolectric w Ustawieniach. Wszystkie istniejące i nowe testy powinny przejść.
  • Utwórz i zainstaluj Ustawienia, a potem ręcznie otwórz stronę, którą chcesz zmodyfikować. Strona powinna zostać zaktualizowana natychmiast.