Cómo agregar la configuración del vehículo

La mayoría de las páginas de la configuración del vehículo se implementan como una serie de fragmentos que extienden SettingsFragment, cada uno de los cuales tiene su propia actividad definida en CarSettingActivities. Estas actividades estáticas se extienden desde BaseCarSettingsActivity. Además de estos parámetros de configuración, puedes insertar preferencias de otras apps del sistema para que aparezcan en CarSettings.

Agrega una nueva preferencia en la configuración del vehículo

Para agregar un parámetro de configuración nuevo, haz lo siguiente:

  1. Define un archivo en formato XML:
    1. Asegúrate de que todas las preferencias tengan definido android:key. La lista de claves se mantiene en preference_keys.xml. Las claves de preferencias deben ser únicas.
    2. Para la indexación de búsqueda, las pantallas de preferencias también deben tener un android:key definido. La lista de claves de la pantalla de preferencias se mantiene en preference_screen_keys.xml. Las claves de la pantalla de preferencias también deben ser únicas.
    3. Si la preferencia solo muestra información estática (por ejemplo, no hay una lógica empresarial especial), configura el controlador de preferencias como com.android.car.settings.common.DefaultRestrictionsPreferenceController.
    4. Si la preferencia requiere lógica empresarial, configura el controlador de preferencias con un nombre nuevo.
  2. (Si es necesario) Crea el controlador de preferencias en el paquete apropiado, que extiende PreferenceController. Consulta Javadoc si es necesario.
  3. Crea un fragmento con getPreferenceScreenResId que devuelva el archivo en formato XML definido en el paso 1.
  4. Crea una actividad en CarSettingActivities que extienda BaseCarSettingsActivity y, luego, implementa getInitialFragment() para mostrar el fragmento definido en el paso 3.
  5. Actualiza AndroidManifest.xml para incluir la actividad definida en el paso 4.

Ejemplo

En el siguiente material, se ilustra este proceso.

  1. Define un archivo en formato XML llamado demo_fragment.xml:
    <PreferenceScreen
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:settings="http://schemas.android.com/apk/res-auto"
        android:title="@string/demo_label"
        android:key="@string/psk_demo">
        <Preference
            android:icon="@drawable/ic_settings_demo_preference_1"
            android:key="@string/pk_demo_preference_1"
            android:title="@string/demo_preference_1_title"
    settings:controller="com.android.car.settings.common.DefaultRestrictionsPreferenceController">
            <intent android:targetPackage="com.android.car.settings"
    android:targetClass="com.android.car.settings.common.CarSettingActivities$DemoSetting1Activity"/>
        </Preference>
        <Preference
            android:icon="@drawable/ic_settings_demo_preference_2"
            android:key="@string/pk_demo_preference_2"
            android:title="@string/demo_preference_2_title"
    settings:controller="com.android.car.settings.example.MyCustomRestrictionsPreferenceController">
            <intent android:targetPackage="com.android.car.settings"
    android:targetClass="com.android.car.settings.common.CarSettingActivities$DemoSetting2Activity"/>
        </Preference>
    </PreferenceScreen>
  2. Agrega las claves de preferencia a preference_keys:
    <resources>
        [...]
        <string name="pk_demo_preference_1" translatable="false">demo_preference_1</string>
        <string name="pk_demo_preference_2" translatable="false">demo_preference_2</string>
    </resources>
  3. Agrega la clave de la pantalla de preferencias a preference_screen_keys.xml:
    <resources>
        [...]
        <string name="psk_demo" translatable="false">demo_screen</string>
    </resources>

    Para la primera preferencia de ejemplo, usa DefaultRestrictionsPreferenceController. Para la segunda preferencia, usa un controlador de preferencias personalizado, que se debe definir. En este ejemplo, puedes personalizar esta preferencia para los usuarios administradores disponibles únicamente. Para ello, define el siguiente controlador personalizado:

    public class MyCustomRestrictionsPreferenceController extends 
        PreferenceController<Preference> {
    
        private final UserManager mUserManager;
    
        public MyCustomRestrictionsPreferenceController(Context context, String 
            preferenceKey, FragmentController fragmentController, 
            CarUxRestrictions uxRestrictions) {
            super(context, preferenceKey, fragmentController, uxRestrictions);
            mUserManager = UserManager.get(context);
        }
    
        @Override
        protected Class<Preference> getPreferenceType() {
            return Preference.class;
        }
    
        @Override
        public int getAvailabilityStatus() {
            return mUserManager.isAdminUser() ? AVAILABLE : DISABLED_FOR_USER;
        }
    }
  4. Para crear un fragmento, anula getPreferenceScreenResId:
  5. public class DemoFragment extends SettingsFragment {
    
        @Override
        @XmlRes
        protected int getPreferenceScreenResId() {
            return R.xml.demo_fragment;
        }
    }
  6. Para contener el fragmento nuevo, crea una actividad en CarSettingActivities:
  7. public class CarSettingActivities {
        [...]
        public static class DemoActivity extends BaseCarSettingsActivity {
            @Nullable
            @Override
            protected Fragment getInitialFragment() {
                return new DemoFragment();
            }
        }
    }
  8. Actualiza el archivo de manifiesto con la actividad nueva:
  9. <application
        [...]
        <activity
            android:name=".common.CarSettingActivities$DemoActivity"
            android:exported="true">
            <meta-data android:name="distractionOptimized" android:value="true"/>
        </activity>
        [...]
    </application>

    Cómo agregar una preferencia de intent externo en la configuración del vehículo

    Como alternativa a las preferencias insertadas, también es posible insertar una preferencia directamente en la configuración de Car que se envíe a otra app. Para ello, simplemente agrega una preferencia a una pantalla de preferencias con una acción de intent que se resuelva en una app externa. Al igual que otras preferencias en la configuración de Car, estas preferencias tienen los mismos atributos XML disponibles.

    <Preference
        android:key="@string/pk_demo_preference"
        android:title="@string/demo_preference_title"
        android:summary="@string/demo_preference_summary"
    settings:controller="com.android.car.settings.common.DefaultRestrictionsPreferenceController">
            <intent android:action="android.intent.action.DEMO_ACTION"/>
    </Preference>

    Agrega una preferencia insertada

    Las preferencias insertadas contienen intents que dirigen a actividades internas o externas. A modo de ejemplo, el elemento de configuración Google en la página principal de Configuración es una preferencia insertada. Las preferencias insertadas son particularmente útiles cuando se cumple alguna de las siguientes condiciones: La configuración:

    • No se implementa directamente en la app de CarSettings (como la inserción de un parámetro de configuración implementado por los OEM).
    • Debería aparecer en la app de CarSettings.

    Para configurar una actividad como un parámetro de configuración insertado, sigue estos pasos:

    1. Para marcar la actividad como un parámetro de configuración insertado, agrega un filtro de intents a la actividad.
    2. Dile a la app de CarSettings a qué categoría pertenece. La categoría es una constante, definida en CategoryKey, y se usa para indicar en qué nivel de CarSettings debe aparecer el parámetro de configuración insertado. Proporcionamos un conjunto de categorías dentro de CategoryKey, pero no hay restricciones para que los OEM definan sus propias categorías.
    3. (opcional) Agrega texto de resumen cuando se muestre el parámetro de configuración:
      <activity android:name="Settings$DemoSettingsActivity"
          <!-- Mark the activity as an injected setting -->
          <intent-filter>
              <action android:name="com.android.settings.action.EXTRA_SETTINGS"/>
          </intent-filter>
          <!-- Tell CarSettings app which category it belongs to -->
          <meta-data android:name="com.android.settings.category"
                     android:value="com.android.settings.category.demo_category"/>
          <!-- Tell CarSettings the what the preference title should be -->
          <meta-data android:name="com.android.settings.title"
                     android:value="@string/app_name" />
          <!-- Optional: specify the icon to show with the preference -->
          <meta-data android:name="com.android.settings.icon"
                     android:resource="@drawable/ic_demo"
                     android:value="true"/>
          <!-- Optional: Add a summary text when the string is displayed -->
          <meta-data android:name="com.android.settings.summary"
                     android:resource="@string/demo_summary"/>
      </activity>

    Para que el parámetro de configuración insertado aparezca en una página específica de la app de CarSettings, incluye el siguiente código de muestra en el archivo en formato XML y modifica las variables según corresponda:

    <com.android.car.settings.common.LogicalPreferenceGroup
        <!-- Replace key string -->
        android:key="@string/pk_system_extra_settings"
        <!-- Indicates the preferences in the group should be injected in.
             ExtraSettingsPreferenceController contains the logic to pull in injected
             preferences. -->
    settings:controller="com.android.settings.common.ExtraSettingsPreferenceController">
        <!-- Tells the controller what activities should be pulled into this preference
             group. -->
        <intent android:action="com.android.settings.action.EXTRA_SETTINGS">
            <!-- Name and value should match the metadata in your activity -->
            <extra android:name="com.android.settings.category"
                   android:value="com.android.settings.category.demo_category"/>
        </intent>
    </com.android.car.settings.common.LogicalPreferenceGroup>