Adicionar configurações do carro

A maioria das páginas em "Configurações do carro" é implementada como uma série de fragmentos que estendem SettingsFragment, cada um deles com a própria atividade definida em CarSettingActivities. Essas atividades estáticas são estendidas de BaseCarSettingsActivity. Além dessas configurações, é possível injetar preferências de outros apps do sistema para que elas apareçam no CarSettings.

Adicionar uma nova preferência nas configurações do carro

Para adicionar uma nova configuração:

  1. Defina um arquivo XML:
    1. Verifique se todas as preferências têm android:key definido. A lista de chaves é mantida em preference_keys.xml. As chaves de preferências precisam ser exclusivas.
    2. Para fins de indexação de pesquisa, as telas de preferência também precisam ter um android:key definido. A lista de chaves da tela de preferência é mantida em preference_screen_keys.xml. As chaves da tela de preferências também precisam ser exclusivas.
    3. Se a preferência mostrar apenas informações estáticas (por exemplo, sem uma lógica de negócios especial), defina o controlador de preferência como com.android.car.settings.common.DefaultRestrictionsPreferenceController.
    4. Se a preferência exigir lógica de negócios, defina o controlador de preferência com um novo nome.
  2. (Se necessário) Crie o controlador de preferência no pacote adequado, que estende PreferenceController. Consulte o Javadoc, se necessário.
  3. Crie um fragmento com getPreferenceScreenResId retornando o arquivo XML definido na Etapa 1.
  4. Crie uma atividade em CarSettingActivities que estenda BaseCarSettingsActivity e implemente getInitialFragment(), retornando o fragmento definido na etapa 3.
  5. Atualize AndroidManifest.xml para incluir a atividade definida na etapa 4.

Exemplo

O material a seguir ilustra esse processo.

  1. Defina um arquivo XML chamado 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. Adicione as chaves de preferência 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. Adicione a chave da tela de preferência a preference_screen_keys.xml:
    <resources>
        [...]
        <string name="psk_demo" translatable="false">demo_screen</string>
    </resources>

    Para o primeiro exemplo de preferência, use DefaultRestrictionsPreferenceController. Para a segunda preferência, use um controlador de preferências personalizado, que precisa ser definido. Neste exemplo, você pode personalizar essa preferência somente para os usuários administradores disponíveis. Para fazer isso, defina o seguinte 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 criar um fragmento, substitua getPreferenceScreenResId:
  5. public class DemoFragment extends SettingsFragment {
    
        @Override
        @XmlRes
        protected int getPreferenceScreenResId() {
            return R.xml.demo_fragment;
        }
    }
  6. Para manter o novo fragmento, crie uma atividade em CarSettingActivities:
  7. public class CarSettingActivities {
        [...]
        public static class DemoActivity extends BaseCarSettingsActivity {
            @Nullable
            @Override
            protected Fragment getInitialFragment() {
                return new DemoFragment();
            }
        }
    }
  8. Atualize o arquivo de manifesto com a nova atividade:
  9. <application
        [...]
        <activity
            android:name=".common.CarSettingActivities$DemoActivity"
            android:exported="true">
            <meta-data android:name="distractionOptimized" android:value="true"/>
        </activity>
        [...]
    </application>

    Adicionar uma preferência de intent externa nas configurações do carro

    Como alternativa às preferências injetadas, também é possível inserir uma preferência diretamente nas configurações do carro que se destina a outro app. Isso pode ser feito simplesmente adicionando uma preferência a uma tela de preferência com uma ação de intent que é resolvida em um app externo. Como outras preferências nas configurações do carro, essas preferências têm os mesmos atributos XML disponíveis.

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

    Adicionar uma preferência injetada

    As preferências injetadas contêm intents que levam a atividades externas ou internas. Por exemplo, o item de configuração Google na página inicial de Configurações é uma preferência injetada. As preferências injetadas são particularmente úteis quando uma das seguintes condições é verdadeira. A configuração:

    • Não é implementado diretamente no app CarSettings, como injetar uma configuração implementada por OEMs.
    • Deve aparecer no app CarSettings.

    Para configurar uma atividade como uma configuração injetada:

    1. Para marcar a atividade como uma configuração injetada, adicione um filtro de intent à atividade.
    2. Informe ao app CarSettings a categoria a que ele pertence. A categoria é uma constante, definida em CategoryKey, e é usada para indicar em qual nível de CarSettings a configuração injetada precisa aparecer. Fornecemos um conjunto de categorias em CategoryKey, mas não há restrições para que os OEMs definam as próprias categorias.
    3. (opcional) Adicione um texto de resumo quando a configuração for exibida:
      <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 a configuração injetada apareça em uma página específica no app CarSettings, inclua o seguinte código de exemplo no XML, modificando as variáveis, quando apropriado:

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