将应用分发到 Android Automotive OS 设备时,您应注意一些该外形规格独有的注意事项。本指南将解释这些注意事项。
在 Android Automotive OS 模拟器上测试您现有的应用
要开始为 Android Automotive OS 构建应用,请首先在 Android Automotive OS 模拟器上测试您现有的应用。要设置模拟器,请按照使用 Android Automotive OS 模拟器进行测试中的步骤操作。然后,您可以按照在模拟器上运行您的应用中的说明运行应用。
运行应用时,请注意兼容性问题,例如以下问题:
- 车载信息娱乐屏幕具有固定方向。为了符合车载应用质量指南,应用必须同时支持纵向和横向。
- 其他设备上可用的 API 可能在 Android Automotive OS 上不可用。例如,部分 Google Play 服务 API 在 Android Automotive OS 上不可用。有关如何处理这些问题的详细信息,请参阅停用功能部分。
配置应用的清单文件
要以 Android Automotive OS 设备为目标,您的应用必须包含某些清单条目。选择分发到 Android Automotive OS 设备后,兼容的应用将通过人工审核流程,以帮助确保它们在汽车中安全使用。有关详情,请参阅分发到汽车。
必需的 Android Automotive OS 功能
所有为 Android Automotive OS 构建的应用都必须满足通过 Google Play 进行分发的特定要求。如需了解详情,请参阅满足 Google Play 功能要求。
类别专用清单条目
除了适用于所有驻车应用的上述要求之外,视频和游戏类别还有其他要求:
- 对于视频应用,请参阅将应用标记为视频应用。
- 对于游戏,请参阅将应用标记为游戏。
满足驾驶员分心要求
将应用引入汽车时,避免驾驶员分心至关重要。对于驻车应用,这主要是通过在用户体验 (UX) 限制处于活动状态时阻止应用被使用或播放音频来实现的,这符合 DD-2
和 DD-3
质量指南。
当用户体验限制处于活动状态时阻止使用
默认情况下,当 UX 限制处于活动状态时,活动无法使用或启动。为确保此行为适用于您的应用,您的清单中的任何 <activity>
元素都不得包含以下 <meta-data>
元素:
<!-- NOT ALLOWED -->
<meta-data
android:name="distractionOptimized"
android:value="true"/>
如果您的应用中的某个活动在 UX 限制变为活动状态时处于“已恢复”状态,则该活动会被操作系统拥有的活动遮盖。
至少,您的应用活动会转换到“已暂停”生命周期状态。这会作为 onPause()
生命周期回调发生,在此期间,您必须暂停应用中的视频和音频播放。
在包含Android Automotive OS 兼容模式的设备上,系统阻止会导致应用活动从“已暂停”状态转换到“已停止”状态。
停止播放并阻止播放恢复
对于某些应用,在 onPause()
期间暂停播放并跟踪状态以防止在 onResume()
之前恢复播放,足以满足驾驶员分心要求。
如果对生命周期回调作出反应不足以满足您的应用需求,您可以直接监听 UX 限制状态,如下一节所述。例如,支持画中画的应用可能更倾向于直接监听,而不是在生命周期回调中进行条件检查。
监听用户体验限制
要监听 UX 限制,请首先在应用模块的 build.gradle
文件中添加对 android.car
库的依赖项。这是 Android SDK 的一个扩展,提供 Android Automotive OS 专用的 API。
android {
...
useLibrary("android.car")
}
使用 CarUxRestrictionsManager
读取 UX 限制状态。请勿尝试从其他硬件状态(例如挡位或速度)确定 UX 限制状态,因为 UX 限制在车辆内可能因显示屏而异。
val car = Car.createCar(context)
val carUxRestrictionsManager =
car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE) as CarUxRestrictionsManager
// You can either read the state directly ...
val currentUxRestrictions = carUxRestrictionsManager.currentUxRestrictions
// or listen to state changes
carUxRestrictionsManager.registerListener { carUxRestrictions: CarUxRestrictions -> ...}
// Don't forget to teardown and release resources when they're no longer needed
carUxRestrictionsManager.unregisterListener()
car.disconnect()
您的应用应引用的 CarUxRestrictions
提供的唯一值是 isRequiresDistractionOptimization()
的返回值。其他值仅与被标记为“针对分心行为优化”的活动相关。
测试您的实现
使用以下步骤验证您的应用是否满足驾驶员分心要求:
- 将您的应用安装在不带 Google Play 商店或兼容模式的系统映像上。
- 在启动器应用网格打开的情况下,模拟驾驶并验证您的应用无法打开。
- 停止模拟驾驶,然后打开您的应用到播放屏幕并开始播放。
- 再次模拟驾驶,并验证播放是否暂停。
- 如果您的应用支持与
MediaSession
集成,请使用adb shell cmd media_session dispatch play
并验证播放不会恢复。
- 如果您的应用支持与
为 Android Automotive OS 优化您的应用
为了给用户在汽车中带来最佳体验,在为 Android Automotive OS 构建应用时,请牢记以下几点:
使用窗口内边距和显示屏切口
与其他外形规格一样,Android Automotive OS 包含系统界面元素(例如状态栏和导航栏),并支持非矩形显示屏。
默认情况下,应用在不与系统栏或显示屏切口重叠的区域中绘制。但是,您可能希望您的应用隐藏系统栏,在其后面绘制内容,或在显示屏切口中显示内容,如在窗口内边距内布置应用中所述。如果您的应用执行上述任何操作,请参阅以下小节,了解如何让您的应用在 Android Automotive OS 设备生态系统中良好运行的详细信息。
系统栏、沉浸模式和全屏渲染
汽车中的系统栏尺寸和位置可能与其他外形规格不同。例如,导航栏可能位于屏幕的左侧、右侧或底部。即使顶部有状态栏、底部有导航栏(大多数手机和平板电脑都是如此),这些元素在汽车中的尺寸也可能大得多。
此外,Android Automotive OS 允许 OEM 控制应用是否可以显示或隐藏系统栏以进入和退出沉浸模式。例如,通过阻止应用隐藏系统栏,OEM 可以确保车辆控制(如气候控制)始终在屏幕上可访问。如果 OEM 阻止应用控制系统栏,则当应用调用 WindowInsetsController
(或 WindowInsetsControllerCompat
)API 来显示或隐藏系统栏时,不会发生任何事情。请参阅 show
和 hide
的文档,详细了解如何检测您的应用是否能够修改内边距。
同样,OEM 还可以控制应用是否可以设置系统栏的颜色和半透明度,以确保系统栏及其包含的元素始终清晰可见。如果您的应用全屏绘制,请检查只有非关键内容绘制在系统栏后面。如果设备 OEM 阻止设置系统栏的颜色或半透明度,则此内容可能不可见。
<!-- Depending on OEM configuration, these style declarations
(and the corresponding runtime calls) may be ignored -->
<style name="...">
<item name="android:statusBarColor">...</item>
<item name="android:navigationBarColor">...</item>
<item name="android:windowTranslucentStatus">...</item>
<item name="android:windowTranslucentNavigation">...</status>
</style>
如果您的应用全屏显示,请不要对系统栏的大小、数量、类型或位置进行假设。相反,请使用窗口内边距 API 来相对于系统栏布置应用内容。有关如何使用这些 API 的详细信息,请参阅在应用中全屏显示内容。硬编码的内边距值在任何外形规格中都不建议使用,但在汽车中,它们很可能根本无法将内容保留在安全区域内。
适应不规则形状的显示屏
除了矩形显示屏之外,某些车辆可能还具有不规则形状的屏幕,如图 1 所示

如果您的应用不全屏渲染,则无需执行任何操作即可使其在安全区域内渲染。
如果您的应用全屏渲染,您可以选择其在显示屏切口方面的行为方式。您可以通过资源来实现此目的,方法是为应用的主题设置 android:windowLayoutInDisplayCutoutMode
属性,或者在运行时修改窗口的 layoutInDisplayCutoutMode
属性。
由于 Android Automotive OS 设备上存在的显示屏切口类型与移动设备上的不同,因此请勿使用针对移动设备上切口进行行为优化的 LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
或 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
。而是使用 LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
或 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
来始终避免或始终进入切口区域。选择后者时,请参阅支持显示屏切口,了解有关显示屏切口相关 API 的更多详细信息。
如果您的应用渲染到显示屏切口区域,并且您希望在 Android Automotive OS 和移动设备之间有不同的行为,请参阅停用功能以获取应用在运行时设置此行为的指导,如果您的应用使用资源文件设置此行为,请参阅使用备用资源。
停用功能
如果您要将现有移动应用提供给 Android Automotive OS 使用,某些功能和特性可能不相关或不可用。例如,汽车通常不提供对摄像头的访问权限。此外,Android Automotive OS 上仅提供部分 Google Play 服务;有关详细信息,请参阅适用于汽车的 Google Play 服务。
您可以使用 PackageManager.hasSystemFeature
API,通过检查 FEATURE_AUTOMOTIVE
功能来检测应用是否在 Android Automotive OS 上运行,示例如下:
Kotlin
val packageManager: PackageManager = ... // Get a PackageManager from a Context val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) if (isCar) { // Enable or disable a given feature }
Java
PackageManager packageManager = ... // Get a PackageManager from a Context boolean isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) if (isCar) { // Enable or disable a given feature }
或者,如果您的应用还包含 Android Auto 组件,则可以使用车载 Android 应用库中的 CarConnection
API 来检测应用是在 Android Automotive OS 还是 Android Auto 上运行,或者是否根本未连接到汽车。
对于画中画 (PiP),请遵循既定的最佳实践,检查该功能是否可用并做出适当的反应。
处理离线场景
虽然汽车与互联网的连接日益紧密,但仍建议应用处理无互联网连接运行的情况,例如以下情况:
- 用户可能会选择退出汽车制造商提供的订阅套餐中的移动数据。
- 在某些区域,移动数据访问可能受限。
- 配备 Wi-Fi 无线电的汽车可能超出 Wi-Fi 范围,或者 OEM 可能会关闭 Wi-Fi 以优先使用移动网络。
请准备好在您的应用中处理这些场景,方法是优雅地降级依赖互联网访问的功能,例如提供离线内容。如需了解详情,请参阅优化网络连接的最佳实践。
使用备用资源
为了帮助您的应用适应汽车,您可以使用 car
资源限定符,在 Android Automotive OS 车辆上运行时提供备用资源。例如,如果您使用尺寸资源来存储内边距值,则可以为 car
资源集使用更大的值,以使触摸目标更大。