概览

我们为 Android Automotive OS (AAOS) 提供了汽车设置 (packages/apps/Car/Settings)。汽车设置与手机设置 (packages/apps/Settings) 不同。虽然汽车设置包含大家熟悉的一些手机设置,但提供的是车辆化的视觉界面,经过了防注意力分散优化,并且为原始设备制造商 (OEM) 提供很多自定义入口点。

除了下面介绍的汽车设置概览外,您还可以参考以下相关主题,详细了解汽车设置:

架构和准则

汽车设置中的大多数页面都是作为一系列扩展 SettingsFragment 的 fragment 实现的,每个 fragment 都在 CarSettingActivities 中定义自己的 activity。这些静态 activity 从 BaseCarSettingsActivity 进行扩展。此规则有一些例外情况,例如某些特殊 fragment 从 BaseFragment 而非 SettingsFragment 进行扩展,而一些 activity 位于 CarSettingActivities 之外,这些都应该视为例外情况(并非要遵循的模式)。

静态偏好设置

静态偏好设置在 XML 中使用 PreferenceCarUiPreference 标记定义。SettingsFragment 实现使用 getPreferenceScreenResId() 方法定义哪个 XML 文件包含要显示的静态偏好设置列表。

动态偏好设置

动态偏好设置使用 PreferenceGroup 标记或 PreferenceGroup 的实现(例如 LogicalPreferenceGroup)来定义一组通过偏好设置控制器生成和控制的偏好设置。

在汽车设置应用中,动态偏好设置表示一组常规偏好设置,可引导用户访问 CarSettings 中的其他页面,不过这些页面是通过偏好设置控制器添加的,而不是在 XML 中添加的。例如,“语言和输入偏好设置”下的“管理键盘偏好设置”基于系统是否允许使用这些输入法,将这些输入法动态添加到偏好设置页面。

操作栏

每个设置屏幕的顶部都有一个操作栏,其中可能包含“返回”导航、屏幕标题和辅助性操作微件(例如按钮和开关)。这些操作栏类似于 Android 提供的 ActionBar,但实际上属于自定义视图。在 Android 11 及更高版本中,此工具栏已纳入底盘基本布局中,该布局包含工具栏视图以及其余应用内容的帧布局。

辅助性操作微件是 MenuItem 类,应在相应 SettingsFragmentBaseFragmentonCreate 内创建。可见性、状态等属性应由 SettingsFragment 的业务逻辑中的 setter 进行控制。

// ExampleSettingsFragment.java
public class ExampleSettingsFragment extends SettingsFragment {

    @Override
    protected List<MenuItem> getToolbarMenuItems() {
        return Collections.singletonList(mClearConfirmButton);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mButton = new MenuItem.Builder(getContext())
                .setTitle(R.string.text)
                .setOnClickListener(mOnClickListener)
                .setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP)
                .build();
    }

    private void updateState() {
        button.setVisible(false);
    }
}

操作栏支持汽车设置中的“防分心优化”。 创建时,在 MenuItem.Builder 中设置 UXRestrictions。

偏好设置控制器

每个设置页面都可以包含多个偏好设置。 为了帮助维护代码结构,每个偏好设置或相关偏好设置组均具有与之关联的 PreferenceController

有关这些组件之间的关系,请参阅下图:

CarSettings 组件

图 1. CarSettings 组件

PreferenceController 是一个具有生命周期感知能力的组件,有助于封装与特定偏好设置相关的业务逻辑。PreferenceControllers 只能通过 XML 附加到相关偏好设置。

// example_settings_fragment.xml
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto"
    android:title="@string/example_settings_title">
  <Preference
    android:key="@string/pk_example_preference_key"
    android:title="@string/example_preference_title"
    settings:controller="com.android.car.settings.example.ExamplePreferenceController"/>
</PreferenceScreen>

汽车设置明确禁止通过代码创建 PreferenceController,以便您可以更轻松地修改设置层次结构,只需对 Java 代码做出极少的改动即可。

PreferenceController 可能需要一些动态数据才能正常运行。例如,用于关闭某个应用的通知的 PreferenceController 需要知道应该对哪个应用执行操作。由于 PreferenceControllers 始终在 XML 中定义,因此无法提供其他构造函数参数。这些附加值通过 PreferenceController 上的公共 setter 方法提供,并使用 SettingsFragment 中的 use(...) 方法进行设置。

// ExamplePreferenceController.java
public class ExamplePreferenceContorller extends PreferenceController<Preference> {

  private ExampleArg mExampleArg;

  public ExamplePreferenceController(...) {
    ...
  }

  public void setExampleArg(ExampleArg exampleArg) {
    mExampleArg = exampleArg;
  }
}

// ExampleSettingsFragment.java
public class ExampleSettingsFragment extends SettingsFragment {

  @Override
  @XmlRes
  protected int getPreferenceScreenResId() {
    Return R.xml.example_settings_fragment;
  }

  @Override
  public void onAttach(Context context) {
    ExampleArg arg = (ExampleArg) getArguments().getSerializeable(ARG_KEY);
    ExamplePreferenceController controller =
        use(ExamplePreferenceController.class, R.string.pk_example_preference_key);
    controller.setExampleArg(arg);
  }
}

使用 use(...) 方法的频率越高,以极少改动 Java 代码的方式重新安排设置层次结构的初始目标就越难实现,因为需要将现有 fragment 代码的较大部分复制到新创建的 fragment 中。有一种方法可以最大限度降低这样做的难度,那就是:

  • 尽量减少 use(...) 的使用。
  • 尝试每次都在 Fragment 中的某个位置(例如,在 onAttach() 方法中)调用 use(...)

Intent 处理

应由汽车设置应用处理的所有 intent 均在清单文件中定义。通常,intent 的定义和处理方式与大多数标准 Android 应用相同,但所有 activity 和 intent 过滤器均在清单中定义。

更改根 fragment

默认情况下,汽车设置会在应用启动时显示 HomepageFragment。可以通过反转 config_is_quick_settings_rootconfig_enable_home_settings_iconconfig_enable_quick_settings_icon 的布尔值将其配置为 QuickSettingFragment

如果需要,可使用 config_show_settings_root_exit_icon 显示或隐藏“退出”图标。

自定义主题

自定义其他属性和资源

汽车设置应用主要使用 CarSettingThemeTheme.CarUi 的扩展)。此主题用于对系统应用的外观和风格进行标准化,以确保整个系统的一致性。

自定义偏好设置

自定义偏好设置涵盖以下附加位置:

  • 某些基本偏好设置类的布局在 car_preference 中定义,并针对汽车 build 进行叠加。此处可替换为基本偏好设置类的任何自定义布局。
  • 汽车设置使用主要在 common 软件包中定义的自定义偏好设置。这些设置应在汽车设置模块中独立于基本偏好设置类进行叠加。