Arquitectura de la información

Android 8.0 presentó una nueva arquitectura de la información para la app de Configuración para simplificar la forma en que se organiza la configuración y que a los usuarios les resulte más fácil encontrar con rapidez la configuración que necesitan para personalizar sus dispositivos Android. Android 9 introdujo algunas mejoras para proporcionar más funcionalidad de Configuración y una implementación más sencilla.

Ejemplos y fuente

Actualmente, la mayoría de las páginas de Configuración se implementan con el nuevo framework. Un buen ejemplo es DisplaySettings:packages/apps/Settings/src/com/android/settings/DisplaySettings.java

A continuación, se muestran las rutas de acceso de los archivos de los componentes importantes:

  • 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 (presentado en Android 9): packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

Implementación

Se recomienda a los fabricantes de dispositivos que adapten la arquitectura de información existente de la configuración y que inserten páginas de configuración adicionales según sea necesario para admitir funciones específicas de los socios. Mover las preferencias de una página heredada (implementadas como SettingsPreferencePage) a una nueva página (que se implementó mediante DashboardFragment) puede ser complicado. Es probable que la preferencia de la página heredada no se implemente con un PreferenceController.

Por lo tanto, cuando mueves una preferencia de una página heredada a una nueva, debes crear una PreferenceController y mueve el código al controlador antes y crear una instancia en el nuevo DashboardFragment. Las APIs que Los requisitos de PreferenceController se describen en su nombre y documentados en Javadoc.

Te recomendamos que agregues una prueba de unidades para cada PreferenceController. Si el cambio se envía a AOSP, se requiere una prueba de unidad. Para obtener más información sobre cómo escribir pruebas basadas en Robolectric, consulta el archivo packages/apps/Settings/tests/robotests/README.md de instrucciones.

Arquitectura de la información tipo complemento

Cada elemento de configuración se implementa como una Preference. Una Preferencia puede ser se muevan de una página a otra.

Para facilitar el traslado de varios parámetros de configuración, Android 8.0 introdujo un fragmento de host de estilo de complemento que contiene elementos de configuración. Los elementos de configuración modelados como controladores estilo complemento. Por lo tanto, una página de configuración se crea un solo fragmento de host y varios controladores de configuración.

Fragmento de panel

DashboardFragment es el host de los controladores de preferencias de estilo de complemento. El fragmento hereda de PreferenceFragment y tiene hooks para expandir y actualizar las listas de preferencias estáticas y dinámicas.

Preferencias estáticas

Se define una lista de preferencias estáticas en XML con la etiqueta <Preference>. R La implementación de DashboardFragment usa el Método getPreferenceScreenResId() para definir qué archivo en formato XML contiene la lista estática de preferencias para mostrar.

Preferencias dinámicas

Un elemento dinámico representa una tarjeta con un intent que conduce a una ubicación externa o interna. Actividad. Por lo general, el intent conduce a una página de configuración diferente. Por ejemplo: el "Google" en la página principal de Configuración es un elemento dinámico. Dinámico los elementos se definen en AndroidManifest (se analizan a continuación) y se cargan a través de un FeatureProvider (definido como DashboardFeatureProvider)

La configuración dinámica es más pesada que la configuración estática. de configuración, por lo que, por lo general, los desarrolladores deberían implementar este parámetro como estático. Sin embargo, la configuración dinámica puede ser útil cuando se cumple alguna de las siguientes condiciones:

  • La configuración no se implementa directamente en la app de Configuración (como insertar una configuración implementada por apps de OEM o operadores).
  • El parámetro de configuración debería aparecer en la página principal de Configuración.
  • Ya tienes una actividad para la configuración y no quieres implementar la configuración estática adicional.

Para configurar una actividad como un parámetro de configuración dinámico, haz lo siguiente:

  • Agrega un filtro de intents a la actividad para marcarla como configuración dinámica.
  • Indica a la app de Configuración a qué categoría pertenece. La categoría es una constante, definido en CategoryKey.
  • Opcional: Agrega texto de resumen cuando se muestre el parámetro de configuración.

Este es un ejemplo tomado de la app de Configuración para 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>

En el momento de la renderización, el fragmento solicitará una lista de preferencias del XML estático y de la configuración dinámica definida en AndroidManifest. Ya sea que los PreferenceController se definan en código Java o en XML, DashboardFragment administra la lógica de control de cada parámetro de configuración a través de PreferenceController (que se analiza a continuación). Luego, se hace se muestra en la IU como una lista mixta.

Controlador de preferencias

Existen diferencias entre la implementación de PreferenceController en Android 9 y Android 8.x, como se describe en esta sección.

PreferenceController en la versión de Android 9

Un PreferenceController contiene toda la lógica para interactuar con la preferencia, incluida la visualización, la actualización, la indexación de búsqueda, etcétera.

La interfaz de PreferenceController se define de la siguiente manera: BasePreferenceController Por ejemplo, consulta el código en packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

Hay varias subclases de BasePreferenceController, cada una de las cuales se asigna a un estilo de IU específico que la app de Configuración admite de forma predeterminada. Por ejemplo, TogglePreferenceController tiene una API que se asigna directamente a cómo el usuario debe interactuar con una IU de preferencias basada en botones de activación.

BasePreferenceController tiene APIs como getAvailabilityStatus(), displayPreference(), handlePreferenceTreeClicked(),, etc. La documentación detallada de cada API se encuentra en la clase de interfaz.

Una restricción sobre la implementación de BasePreferenceController (y sus subclases, como TogglePreferenceController) es que el la firma del constructor debe coincidir con alguna de las siguientes opciones:

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

Mientras se instala una preferencia en el fragmento, el panel proporciona un método para vincular un PreferenceController antes del tiempo de visualización. En el momento de la instalación, el controlador está conectado al fragmento para que todos los eventos relevantes futuros enviados al controlador.

DashboardFragment mantiene una lista de PreferenceController en la pantalla. En el onCreate() del fragmento, se invocan todos los controladores para el método getAvailabilityStatus() y, si muestra un valor verdadero, se invoca displayPreference() para procesar la lógica de visualización. getAvailabilityStatus() también es importante para indicarle al framework de configuración qué elementos están disponibles durante la búsqueda.

PreferenceController en versiones de Android 8.x

Un PreferenceController contiene toda la lógica para interactuar con el preferencia, incluida la visualización, la actualización y la indexación de búsqueda. etcétera

En función de las interacciones de preferencia, la interfaz de PreferenceController tiene las APIs isAvailable(), displayPreference(), handlePreferenceTreeClicked(), etcétera. Puedes encontrar documentación detallada sobre cada API en la clase de interfaz.

Mientras instalas una preferencia para el fragmento, el panel proporciona un método para adjunta un PreferenceController antes de la hora de visualización. En el momento de la instalación, el controlador se conecta al fragmento para que todos los eventos relevantes futuros se envíen al controlador.

DashboardFragment mantiene una lista de PreferenceControllers en la pantalla. En el onCreate() del fragmento, se invocan todos los controladores para el método isAvailable() y, si muestra un valor verdadero, se invoca displayPreference() para procesar la lógica de visualización.

Usa DashboardFragment

Cómo mover una preferencia de la página A a la B

Si la preferencia se indica estáticamente en el archivo XML de preferencias de la página original sigue el procedimiento de traslado estático para tu dispositivo Android a continuación. De lo contrario, sigue el procedimiento de traslado dinámico para tu versión de Android.

Movimiento estático en Android 9

  1. Busca los archivos XML de preferencia para la página y el destino originales. . Puedes encontrar esta información en el método getPreferenceScreenResId() de la página.
  2. Quita la preferencia del XML de la página original.
  3. Agrega la preferencia al archivo en formato XML de la página de destino.
  4. Quita el PreferenceController de esta preferencia de la implementación de Java de la página original. Suele estar en createPreferenceControllers() El controlador se puede declarar directamente en XML.

    Nota: Es posible que la preferencia no tenga un PreferenceController.

  5. Crea una instancia de PreferenceController en el createPreferenceControllers() de la página de destino. Si el botón PreferenceController está definido en XML en la página anterior y defínelo. en XML para la nueva página también.

Movimiento dinámico en Android 9

  1. Descubre qué categoría aloja la página original y la de destino. Puedes encontrar esta información en DashboardFragmentRegistry.
  2. Abre el archivo AndroidManifest.xml que contiene el parámetro de configuración que debes mover y busca la entrada de actividad que lo representa.
  3. Establece el valor de metadatos de la actividad para com.android.settings.category a la clave de categoría de la página nueva

Movimiento estático en versiones de Android 8.x

  1. Busca los archivos en formato XML de preferencias de la página original y de la página de destino.
  2. Puedes encontrar esta información en el método getPreferenceScreenResId() de la página.
  3. Quita la preferencia en el archivo XML de la página original.
  4. Agrega la preferencia al XML de la página de destino.
  5. Quita el atributo PreferenceController de esta preferencia en la implementación de Java de la página original. Por lo general, se encuentra en getPreferenceControllers()
  6. Nota: Es posible que la preferencia no tenga un PreferenceController.

  7. Crea una instancia de PreferenceController en el getPreferenceControllers() de la página de destino.

Movimiento dinámico en versiones de Android 8.x

  1. Buscar la categoría que alojan la página original y la de destino Puedes encontrar esta información en DashboardFragmentRegistry.
  2. Abre el archivo AndroidManifest.xml que contiene la configuración que tendrás que moverte y buscar la entrada de la actividad que representa este parámetro de configuración.
  3. Cambia el valor de metadatos de la actividad para com.android.settings.category y configura el valor para que apunte a la clave de categoría de la página nueva.

Cómo crear una nueva preferencia en una página

Si la preferencia se indica estáticamente en el archivo XML de preferencias de la página original sigue el procedimiento estático que se indica a continuación. De lo contrario, sigue las dinámico.

Cómo crear una preferencia estática

  1. Busca los archivos en formato XML de preferencia para la página. Puedes encontrar esta información en el método getPreferenceScreenResId() de la página.
  2. Agrega un nuevo elemento Preference en el archivo XML. Asegúrate de que tenga un android:key único.
  3. Define un PreferenceController para esta preferencia en el método getPreferenceControllers() de la página.
    • En Android 8.x y, opcionalmente, en Android 9 crea una instancia de PreferenceController para esta preferencia en método createPreferenceControllers() de la página.

      Si esta preferencia ya existía en otros lugares, es posible que ya haya un PreferenceController para ella. Puedes reutilizar el PreferenceController sin crear uno nuevo.

    • A partir de Android 9, puedes optar por declarar el PreferenceController en XML junto a la preferencia. Por ejemplo:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>

Crea una preferencia dinámica

  1. Descubre qué categoría aloja la página original y la de destino. Puedes encontrar esta información en DashboardFragmentRegistry.
  2. Crea una actividad nueva en AndroidManifest
  3. Agrega los metadatos necesarios a la actividad nueva para definir la configuración. Establece el valor de metadatos de com.android.settings.category en el mismo valor que se definió en el paso 1.

Crear página nueva

  1. Crea un nuevo fragmento y lo hereda de DashboardFragment.
  2. Define su categoría en DashboardFragmentRegistry.

    Nota: Este paso es opcional. Si no necesitas ninguna preferencia dinámica en esta página, no es necesario que proporciones una clave de categoría.

  3. Sigue los pasos para agregar la configuración necesaria para esta página. Para obtener más información, consulta la sección Implementación.

Validación

  • Ejecuta las pruebas de Robolectric en Configuración. Todas las pruebas existentes y nuevas que el pase.
  • Compila e instala la configuración y, luego, abre manualmente la página que deseas modificar. La página debería actualizarse de inmediato.