汽车设置中的“防分心优化”

防分心优化 (DO) 是一种工具,旨在减少驾驶员在汽车行驶过程中与“设置”应用的交互。驾驶员在汽车行驶过程中可能需要更改某些设置,因此该应用没有被彻底屏蔽。但默认情况下,大多数偏好设置都处于停用状态,只有重要且易于更新的偏好设置处于启用状态。

汽车行驶过程中处于启用状态的应用

图 1. 汽车行驶过程中处于启用状态的应用

如果所有 activity 均未经过防分心优化,也可以将其全部屏蔽,如下所示。该方法目前主要用于设置搜索。

屏蔽所有 activity

图 2. 屏蔽所有 Activity

您可以通过配置叠加层对 DO 性能进行基本的自定义。如果需要进行更细化的自定义,可通过代码执行更多更改。

高级自定义

如果某个偏好设置在汽车行驶过程中处于停用状态,点按该偏好设置后,系统会显示一个消息框,提示驾驶员该偏好设置在汽车行驶过程中不可用,但前提是该偏好设置附加了偏好设置控制器。该消息使用的是 restricted_while_driving 字符串,可通过叠加层对其进行自定义(前提是该字符串的长度少于 60 个字符)。

自定义的叠加层

图 3. 自定义的叠加层

可使用 config_always_ignore_ux_restrictions 来停用整个 DO 框架。将其设置为 true 表示驾驶员可以与“设置”应用的各项功能交互。

<bool name="config_always_ignore_ux_restrictions">true</bool>

如果将其设置为 false,“设置”应用将回退到 config_ignore_ux_restrictions 来确定哪些偏好设置应在汽车行驶过程中处于启用状态。此处提供的字符串应指向 preference_keys.xml. 中定义的字符串

示例

为展示如何在汽车行驶过程中启用深层嵌套的设置,本示例演示了如何启用文字转语音 (TTS) 输出设置。要实现这一点,需要将层次结构中的所有设置都添加到 config_ignore_ux_restrictions 中。其中包括系统、语言和输入法以及配置的 TTS 偏好设置,因为我们的层次结构是“系统”->“语言和输入法”->“文字转语音 (TTS) 输出”。不过,文字转语音 Fragment 中的偏好设置仍处于停用状态。要使其处于启用状态,需要为相应偏好设置添加键。在本示例中,我们要启用“播放”偏好设置,但不启用引擎偏好设置,因此会在配置中添加 pk_tts_playback_group

<string-array name="config_ignore_ux_restrictions">
    [...]
    <item>@string/pk_system_settings_entry</item>
    <item>@string/pk_languages_and_input_settings</item>
    <item>@string/pk_tts_settings_entry</item>
    <item>@string/pk_tts_playback_group</item>
</string-array>

细化的自定义

某些偏好设置可能还需要比根据汽车行驶状态启用/停用某项偏好设置自定义程度更高的行为。例如,蓝牙和 Wi-Fi 经过了修改,可以在驾车时显示已保存的蓝牙设备或 Wi-Fi 接入点。

目前无法通过基于配置的解决方案来进行此类调整。不过,您可以创建一个可扩展 PreferenceController 并替换 onApplyUxRestrictions() 的自定义类,以进行所需的更改。

创建自定义偏好设置控制器后,您可以叠加相关的 XML 文件,从而将默认的偏好设置控制器替换为您自己的实现。

示例

CarSettings 中的某些偏好设置具有这种自定义程度更高的行为,进一步自定义时可以之为例。例如,对于 WLAN 接入点列表,我们希望在汽车行驶过程中仅显示所保存的接入点(隐藏其他接入点)。要实现这一点,请使用以下代码:

mAccessPoints = CarUxRestrictionsHelper.isNoSetup(getUxRestrictions())
               ? getCarWifiManager().getSavedAccessPoints()
               : getCarWifiManager().getAllAccessPoints();

列表中显示的接入点已受到限制,因此无需再为这些偏好设置应用 UxRestrictions。而是替换 onApplyUxRestrictions 并故意执行空操作:

@Override
protected void onApplyUxRestrictions(CarUxRestrictions uxRestrictions) {
    // Since the list dynamically changes based on the UX restrictions, we
    // enable this fragment regardless of the restriction. Intentional no-op.
}

绑定蓝牙的设备中提供了另一个示例。如果您希望继续支持连接和断开蓝牙设备,但停用这些设备的其他访问权限。要实现这一点,可再次替换 onApplyUxRestrictions,但此时如果已启用 NO_SETUP 限制,则隐藏针对相应偏好设置的次要操作。

@Override
protected void onApplyUxRestrictions(CarUxRestrictions uxRestrictions) {
    super.onApplyUxRestrictions(uxRestrictions);
    if (CarUxRestrictionsHelper.isNoSetup(uxRestrictions)) {
        updateActionVisibility(getPreference(), /* isActionVisible= */ false);
    }
}