将应用分发到 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 skills
在 GitHub 上查看Android for Cars 停车状态下使用的应用
android skills add android-for-cars-parked-apps配置应用的清单文件
如需以 Android Automotive OS 设备为目标平台,应用必须具有特定的清单条目。在您选择加入向 Android Automotive OS 设备分发应用的计划后,Google Play 会审核兼容的应用,以确保其可以在汽车上安全地使用。如需了解详情,请参阅分发至汽车。
必需的 Android Automotive OS 功能
所有专为 Android Automotive OS 构建的应用都必须满足特定要求,才能通过 Google Play 分发。如需了解详情,请参阅满足 Google Play 功能要求。
特定于类别的清单条目
除了上述适用于所有停车时使用的应用的要求之外,视频和游戏类别还有其他要求:
- 对于视频应用,请参阅将应用标记为视频应用。
- 对于游戏,请参阅将应用标记为游戏。
满足驾驶员分心要求
在将应用引入汽车时,避免驾驶员分心至关重要。对于停车状态下使用的应用,这主要是通过在用户体验 (UX) 限制处于启用状态时阻止应用使用或播放音频来实现的,如 DD-2 和 DD-3 质量指南中所述。
在用户体验限制处于已启用状态时阻止使用
默认情况下,当用户体验限制处于有效状态时,无法使用或启动 activity。为确保此行为适用于您的应用,清单中的任何 <activity> 元素都不得包含以下 <meta-data> 元素:
<!-- NOT ALLOWED -->
<meta-data
android:name="distractionOptimized"
android:value="true"/>
如果用户体验限制生效时,应用中的 activity 处于已恢复状态,则该 activity 会被操作系统拥有的 activity 遮挡。
至少,应用的 activity 会转换为“已暂停”生命周期状态。此操作会作为 onPause 生命周期回调发生,在此期间,您必须暂停播放应用中的视频和音频。
在包含 Android Automotive OS 兼容模式的设备上,系统屏蔽会导致应用的 activity 从已暂停状态转换为已停止状态。
停止播放并防止恢复播放
对于某些应用,在 onPause() 期间暂停播放并跟踪状态以防止在 onResume() 之前恢复播放,就足以满足驾驶员分心要求。
如果对生命周期回调做出响应对您的应用来说还不够,您可以直接监听用户体验限制状态,如以下部分所述。例如,支持画中画的应用可能更愿意直接监听,而不是在生命周期回调中进行条件检查。
监听用户体验限制
如需监听用户体验限制,请先在应用模块的 build.gradle 文件中添加对 android.car 库的依赖项。这是 Android SDK 的扩展,可提供特定于 Android Automotive OS 的 API。
android {
...
useLibrary("android.car")
}
使用 CarUxRestrictionsManager 读取用户体验限制状态。请勿尝试根据其他硬件状态(例如档位或速度)确定用户体验限制状态,因为用户体验限制可能因车辆内的显示屏而异。
val car = Car.createCar(context) ?: return val carUxRestrictionsManager = car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE) as? CarUxRestrictionsManager ?: return // You can either read the state directly ... val currentUxRestrictions = carUxRestrictionsManager.currentCarUxRestrictions // or listen to state changes carUxRestrictionsManager.registerListener { carUxRestrictions: CarUxRestrictions -> // Handle UX restrictions } // Don't forget to teardown and release resources when they're no longer needed carUxRestrictionsManager.unregisterListener() car.disconnect()
您的应用引用的 CarUxRestrictions 提供的唯一值是 isRequiresDistractionOptimization 的返回值。其他值仅与标记为经过防分心优化的 activity 相关。
测试实现效果
使用以下过程验证您的应用是否符合驾驶员分心要求:
- 在不含 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,某些特性和功能可能不相关或不可用。例如,汽车通常不提供对摄像头的访问权限。此外,只有部分 Google Play 服务适用于 Android Automotive OS;如需了解详情,请参阅适用于汽车的 Google Play 服务。
您可以使用 PackageManager.hasSystemFeature API,通过检查有无 FEATURE_AUTOMOTIVE 功能来检测应用是否正在 Android Automotive OS 上运行,如以下示例所示:
val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) if (isCar) { // Enable or disable a given feature }
或者,如果您的应用还包含 Android Auto 组件,您可以使用 Android for Cars 应用库中的 CarConnection API 来检测应用是在 Android Automotive OS 还是 Android Auto 上运行,还是根本未关联到汽车。
对于画中画 (PiP) 功能,请遵循既有的最佳实践来检查该功能是否可用并做出适当的回应。
处理离线场景
尽管汽车的联网程度越来越高,但我们建议应用具备在没有互联网连接的情况下处理运行的能力,例如以下情况:
- 用户可能会选择停用汽车制造商提供的订阅套餐中的移动流量服务。
- 在某些区域,使用移动流量可能会受到限制。
- 配有 Wi-Fi 无线装置的汽车可能不在 Wi-Fi 覆盖范围内,或者原始设备制造商 (OEM) 可能会停用 Wi-Fi,改为使用移动网络。
请优雅降级依赖于访问互联网的功能(例如提供离线内容),准备好在您的应用中处理这些场景。如需了解详情,请参阅网络优化最佳实践。
使用备用资源
为了有助于您的应用在汽车上运行,当在 Android Automotive OS 车辆上运行时,您可以使用 car 资源限定符提供备用资源。例如,如果您使用尺寸资源来存储内边距值,则可以为 car 资源集使用较大的值,以增大触摸目标。