Android Automotive OS 允许用户在汽车中安装应用。要在此平台上触达用户,您需要分发一个经过驾驶员优化的、与 Android Automotive OS 兼容的应用。您可以重用 Android Auto 应用中的几乎所有代码和资源,但必须创建一个符合本页要求的独立 build。
开发概览
添加 Android Automotive OS 支持只需几个步骤,详见以下各部分
设计注意事项
Android Automotive OS 负责布局从您的应用的媒体浏览器服务接收到的媒体内容。这意味着当用户触发媒体播放时,您的应用不会绘制 UI,也不会启动任何 Activity。
如果您正在实现设置或登录 Activity,这些 Activity 必须是针对车辆优化的。在设计应用的这些区域时,请参阅Android Automotive OS 设计指南。
设置您的项目
您需要设置应用项目的几个部分,以启用对 Android Automotive OS 的支持。
在 Android Studio 中启用车载功能
使用 Android Studio 4.0 或更高版本,以确保启用所有 Automotive OS 功能。
创建车载模块
Android Automotive OS 的某些组件(例如清单)具有平台特定的要求。创建一个模块,使这些组件的代码与项目中的其他代码(例如用于手机应用的代码)分开。
按照以下步骤将车载模块添加到您的项目中
- 在 Android Studio 中,点击 文件 > 新建 > 新建模块。
- 选择 Automotive Module,然后点击 下一步。
- 输入应用/库名称。这是用户在 Android Automotive OS 上看到的您的应用的名称。
- 输入模块名称。
- 调整软件包名称以匹配您的应用。
选择 API 28: Android 9.0 (Pie) 作为最低 SDK,然后点击 下一步。
所有支持 Android Automotive OS 的汽车都运行 Android 9 (API 级别 28) 或更高版本,因此选择此值会针对所有兼容的汽车。
选择 No Activity,然后点击 完成。
在 Android Studio 中创建模块后,打开新车载模块中的 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.media">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" />
<uses-feature
android:name="android.hardware.type.automotive"
android:required="true" />
</manifest>
<application>
元素包含一些标准应用信息,以及一个<uses-feature>
元素,用于声明对 Android Automotive OS 的支持。请注意,清单中没有声明任何 Activity。
如果您实现设置或登录 Activity,请在此处添加它们。这些 Activity 由系统使用显式 Intent 触发,是您在 Android Automotive OS 应用的清单中声明的唯一 Activity。
添加任何设置或登录 Activity 后,通过将 <application>
元素的 android:appCategory
属性设置为 "audio"
来完成您的清单文件。
<application
...
android:appCategory="audio" />
声明功能要求
所有为 Android Automotive OS 构建的应用都必须满足通过 Google Play 分发的某些要求。有关详情,请参阅满足 Google Play 功能要求。
声明对 Android Automotive OS 的媒体支持
使用以下清单条目声明您的应用支持 Android Automotive OS
<application>
...
<meta-data android:name="com.android.automotive"
android:resource="@xml/automotive_app_desc"/>
...
</application>
此清单条目引用了一个 XML 文件,该文件声明了您的应用支持的车载功能。
要指明您拥有一个媒体应用,请在您的项目中将一个名为 automotive_app_desc.xml
的 XML 文件添加到 res/xml/
目录。此文件中包含以下内容
<automotiveApp>
<uses name="media"/>
</automotiveApp>
Intent 过滤器
Android Automotive OS 使用显式 Intent 触发媒体应用中的 Activity。不要在清单文件中包含任何具有 CATEGORY_LAUNCHER
或 ACTION_MAIN
Intent 过滤器的 Activity。
如下例所示的 Activity 通常面向手机或其他移动设备。在构建手机应用的模块中声明这些 Activity,而不是在构建 Android Automotive OS 应用的模块中声明。
<activity android:name=".MyActivity">
<intent-filter>
<!-- You can't use either of these intents for Android Automotive OS -->
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!--
In their place, you can include other intent filters for any activities
that your app needs for Android Automotive OS, such as settings or
sign-in activities.
-->
</intent-filter>
</activity>
更新您的 Gradle 依赖项
我们建议您将媒体浏览器服务放在一个单独的模块中,该模块在您的手机应用和车载模块之间共享。如果您采用此方法,则需要更新您的车载模块以包含共享模块,如以下代码片段所示
my-auto-module/build.gradle
Groovy
buildscript { ... dependencies { ... implementation project(':shared_module_name') } }
Kotlin
buildscript { ... dependencies { ... implementation(project(":shared_module_name")) } }
实现设置和登录 Activity
除了您的媒体浏览器服务之外,您还可以为您的 Android Automotive OS 应用提供针对车辆优化的设置和登录 Activity。这些 Activity 让您可以提供 Android 媒体 API 中未包含的应用功能。
仅当您的 Android Automotive OS 应用需要让用户登录或指定应用设置时,才实现这些 Activity。Android Auto 不会使用这些 Activity。
Activity 工作流程
下图显示了用户如何使用 Android Automotive OS 与您的设置和登录 Activity 交互
图 1. 设置和登录 Activity 工作流程。
避免在设置和登录 Activity 中出现干扰
为确保您的设置和/或登录 Activity 仅在用户车辆驻车时可用,请验证 <activity>
元素不包含以下 <meta-data>
元素。如果存在此类元素,您的应用在审核期间将被拒绝。
<!-- NOT ALLOWED -->
<meta-data
android:name="distractionOptimized"
android:value="true"/>
添加设置 Activity
您可以添加一个针对车辆优化的设置 Activity,以便用户可以在汽车中配置您的应用设置。您的设置 Activity 还可以提供其他工作流程,例如登录或退出用户帐号,或切换用户帐号。请记住,此 Activity 仅由运行在 Android Automotive OS 上的应用触发。连接到 Android Auto 的手机应用不会使用它。
声明设置 Activity
您必须在应用的清单文件中声明您的设置 Activity,如以下代码片段所示
<application>
...
<activity android:name=".AppSettingsActivity"
android:exported="true"
android:theme="@style/SettingsActivity"
android:label="@string/app_settings_activity_title">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES"/>
</intent-filter>
</activity>
...
</application>
实现您的设置 Activity
当用户启动您的应用时,Android Automotive OS 会检测您声明的设置 Activity 并显示一个可供操作的元素(例如图标)。用户可以使用汽车的显示屏点按或选择此可供操作的元素以导航到该 Activity。Android Automotive OS 会发送 ACTION_APPLICATION_PREFERENCES
Intent,告知您的应用启动您的设置 Activity。
本节的其余部分将介绍如何根据通用 Android 音乐播放器 (UAMP) 示例应用中的代码调整以实现您应用的设置 Activity。
首先,下载示例代码
# Clone the UAMP repositorygit clone https://github.com/android/uamp.git
# Fetch the appropriate pull request to your local repositorygit fetch origin pull/323/head:NEW_LOCAL_BRANCH_NAME
# Switch to the new branchgit checkout NEW_LOCAL_BRANCH_NAME
要实现您的 Activity,请按照以下步骤操作
- 将
automotive/automotive-lib
文件夹复制到您的车载模块中。 - 定义一个偏好设置树,如
automotive/src/main/res/xml/preferences.xml
中所示。 实现一个
PreferenceFragmentCompat
,您的设置 Activity 将显示它。有关详情,请参阅 UAMP 中的SettingsFragment.kt
和SettingsActivity.kt
文件以及Android 设置指南。
在实现设置 Activity 时,请考虑使用 Preference 库中某些组件的最佳实践
- 您的设置 Activity 中的主视图下方不得超过两级深度。
- 不要使用
DropDownPreference
。请改用ListPreference
。 - 组织组件
PreferenceScreen
- 这必须是您的偏好设置树的顶层。
PreferenceCategory
- 用于将
Preference
对象组合在一起。 - 包含
title
。
- 用于将
- 在所有以下组件中包含
key
和title
。您还可以包含summary
、icon
或两者Preference
- 自定义您的
PreferenceFragmentCompat
实现的onPreferenceTreeClick()
回调中的逻辑。
- 自定义您的
CheckBoxPreference
- 可以具有
summaryOn
或summaryOff
而不是summary
用于条件文本。
- 可以具有
SwitchPreference
- 可以具有
summaryOn
或summaryOff
而不是summary
用于条件文本。 - 可以具有
switchTextOn
或switchTextOff
。
- 可以具有
SeekBarPreference
- 包含
min
、max
和defaultValue
。
- 包含
EditTextPreference
- 包含
dialogTitle
、positiveButtonText
和negativeButtonText
。 - 可以具有
dialogMessage
和/或dialogLayoutResource
。
- 包含
com.example.android.uamp.automotive.lib.ListPreference
- 主要派生自
ListPreference
。 - 用于显示
Preference
对象的单选列表。 - 必须具有
entries
数组和相应的entryValues
。
- 主要派生自
com.example.android.uamp.automotive.lib.MultiSelectListPreference
- 主要派生自
MultiSelectListPreference
- 用于显示
Preference
对象的复选列表。 - 必须具有
entries
数组和相应的entryValues
。
- 主要派生自
添加登录 Activity
如果您的应用要求用户在使用前登录,您可以添加一个针对车辆优化的登录 Activity,用于处理应用的登录和退出。您还可以将登录和退出工作流程添加到设置 Activity,但如果您的应用在用户登录前无法使用,则请使用专用的登录 Activity。请记住,此 Activity 仅由运行在 Android Automotive OS 上的应用触发。连接到 Android Auto 的手机应用不会使用它。
应用启动时要求登录
要要求用户在使用您的应用前登录,您的媒体浏览器服务必须执行以下操作
- 在您的服务的
onLoadChildren()
方法中,使用sendResult()
方法发送null
结果。 - 使用
setState()
方法,将媒体会话的PlaybackStateCompat
设置为STATE_ERROR
。这会告知 Android Automotive OS,在错误解决之前无法执行其他操作。 - 将媒体会话的
PlaybackStateCompat
错误代码设置为ERROR_CODE_AUTHENTICATION_EXPIRED
。这会告知 Android Automotive OS 用户需要进行身份验证。 - 使用
setErrorMessage()
方法设置媒体会话的PlaybackStateCompat
错误消息。由于此错误消息面向用户,因此请针对用户的当前语言区域进行本地化。 使用
setExtras()
方法设置媒体会话的PlaybackStateCompat
额外数据。包括以下两个键PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL
:一个字符串,显示在开始登录工作流程的按钮上。由于此字符串面向用户,因此请针对用户的当前语言区域进行本地化。PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT
:一个PendingIntent
,当用户点按PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL
引用的按钮时,将用户定向到您的登录 Activity。
以下代码片段展示了您的应用如何要求用户在使用前登录
Kotlin
import androidx.media.utils.MediaConstants val signInIntent = Intent(this, SignInActivity::class.java) val signInActivityPendingIntent = PendingIntent.getActivity(this, 0, signInIntent, 0) val extras = Bundle().apply { putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL, "Sign in" ) putParcelable( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT, signInActivityPendingIntent ) } val playbackState = PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR, 0, 0f) .setErrorMessage( PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED, "Authentication required" ) .setExtras(extras) .build() mediaSession.setPlaybackState(playbackState)
Java
import androidx.media.utils.MediaConstants; Intent signInIntent = new Intent(this, SignInActivity.class); PendingIntent signInActivityPendingIntent = PendingIntent.getActivity(this, 0, signInIntent, 0); Bundle extras = new Bundle(); extras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL, "Sign in"); extras.putParcelable( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT, signInActivityPendingIntent); PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR, 0, 0f) .setErrorMessage( PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED, "Authentication required" ) .setExtras(extras) .build(); mediaSession.setPlaybackState(playbackState);
用户成功通过身份验证后,将 PlaybackStateCompat
恢复到除 STATE_ERROR
之外的状态,然后通过调用 Activity 的 finish()
方法将用户带回 Android Automotive OS。
实现您的登录 Activity
Google 提供了各种身份工具,可用于帮助用户在汽车中登录您的应用。某些工具(例如 Firebase Authentication)提供了全栈工具包,可帮助您构建自定义的身份验证体验。其他工具则利用用户的现有凭据或其他技术,帮助您为用户构建无缝的登录体验。
以下工具可以帮助您为以前在其他设备上登录过的用户构建更简单的登录体验
- 一触式登录和注册:如果您已为其他设备(例如您的手机应用)实现了一触式,请为您的 Android Automotive OS 应用实现它,以支持现有的一触式用户。
- Google 登录:如果您已为其他设备(例如您的手机应用)实现了Google 登录,请为您的 Android Automotive OS 应用实现 Google 登录,以支持现有 Google 登录用户。
- Google 自动填充:如果用户已在其他 Android 设备上选择启用 Google 自动填充功能,则其凭据会保存到Google 密码管理工具中。当这些用户登录到您的 Android Automotive OS 应用时,Google 自动填充功能会推荐相关的已保存凭据。使用 Google 自动填充无需应用开发工作。但是,应用开发者可以优化其应用以获得更好的结果。Google 自动填充功能受所有运行 Android 8.0 (API 级别 26) 或更高版本的设备支持,包括 Android Automotive OS。
使用 AccountManager
具有身份验证功能的 Android Automotive OS 应用必须使用AccountManager,原因如下
- 更好的用户体验和更轻松的帐号管理:用户可以通过系统设置中的帐号菜单轻松管理其所有帐号,包括登录和退出。
- “访客”体验:汽车是共享设备,这意味着 OEM 可以在车辆中启用“访客”体验,其中无法添加帐号。此限制是使用
DISALLOW_MODIFY_ACCOUNTS
通过AccountManager
实现的。
权限
如果您需要向用户请求权限,请使用与上一节中Activity 工作流程图中所示的身份验证 Activity 或设置 Activity 相同的工作流程。
启动媒体主机应用
您可以创建 Intent,以在媒体主机应用中打开您的应用或应用内的内容。例如
- 您的应用可以发布包含 Pending Intent 的通知,让用户可以打开您的应用收听新的内容。
- 您的应用可以处理深层链接并将主机应用打开到最合适的视图。
确定媒体主机功能
媒体主机应用的不同版本支持不同的功能。主机通过包含以下 Intent 操作的 Intent 过滤器来指示对不同功能的支持
所有媒体主机应用都支持 MEDIA_TEMPLATE
Intent。要确定媒体主机是否支持 MEDIA_TEMPLATE_V2
Intent,您可以使用 queryIntentActivities()
如下:
val isMediaTemplateV2Supported = packageManager.queryIntentActivities(
Intent(MediaIntentExtras.ACTION_MEDIA_TEMPLATE_V2),
// MATCH_DEFAULT_ONLY since the host should be started with implicit intents
// MATCH_SYSTEM_ONLY excludes any apps that aren't preinstalled
PackageManager.MATCH_DEFAULT_ONLY or PackageManager.MATCH_SYSTEM_ONLY
).size > 0
构建和使用 Intent
根据媒体主机支持的 Intent 操作以及您的具体用例,在构建用于启动媒体主机应用的 Intent 时,您可以提供以下额外数据。
额外数据键 | 类型 | 说明 | 支持的操作 |
---|---|---|---|
EXTRA_KEY_MEDIA_COMPONENT |
字符串 |
媒体主机应用应连接到的扁平化组件名称的MediaBrowserService – 通常是您应用的 MediaBrowserService。如果未指定此额外数据,媒体主机将默认使用活跃的媒体源。 |
MEDIA_TEMPLATE , MEDIA_TEMPLATE_V2 |
EXTRA_KEY_SEARCH_QUERY |
字符串 |
调用时使用的搜索查询 | MEDIA_TEMPLATE , MEDIA_TEMPLATE_V2 |
EXTRA_KEY_MEDIA_ID |
字符串 |
在浏览视图中打开的媒体 ID。 | MEDIA_TEMPLATE_V2 |
EXTRA_KEY_SEARCH_ACTION |
整数 |
搜索 EXTRA_KEY_SEARCH_QUERY 完成后要执行的操作。 |
MEDIA_TEMPLATE_V2 |
例如,对于支持 MEDIA_TEMPLATE_V2
操作的主机,以下代码将打开媒体主机应用,使其连接到 MyMediaBrowserService
,执行“爵士乐”搜索,然后播放搜索结果中的第一个项目。在所有其他主机上,它只会打开媒体主机应用并执行“爵士乐”搜索,让用户从结果中选择要播放的项目。
val startMediaHostIntent = Intent(ACTION_MEDIA_TEMPLATE)
.putExtra(MediaIntentExtras.EXTRA_KEY_MEDIA_COMPONENT, MyMediaBrowserService::class.java)
.putExtra(MediaIntentExtras.EXTRA_KEY_SEARCH_QUERY, "Jazz")
.putExtra(MediaIntentExtras.EXTRA_KEY_SEARCH_ACTION, MediaIntentExtras.EXTRA_VALUE_PLAY_FIRST_ITEM_FROM_SEARCH)
context.startActivity(startMediaHostIntent)
支持深层链接
为了改善您的媒体应用在 Android Automotive OS 设备上的体验,您可以为您的应用添加对深层链接的支持。例如,这允许用户直接从浏览器打开您的应用,或者在使用“附近共享”从手机接收共享的 URL 时打开您的应用。
添加深层链接 Intent 过滤器
为了告知操作系统您的应用能够处理深层链接,它需要具有带有相应 Intent 过滤器的 Activity。有关用于深层链接的 Intent 过滤器的格式指南,请参阅为传入链接添加 Intent 过滤器。
为获得最佳用户体验,请支持您的移动应用支持的所有深层链接,前提是您的车载应用能够合理地支持它们。如果您的应用具有设置或登录 Activity,则处理设置和登录深层链接的 Intent 过滤器应在相应的 <activity>
清单元素中声明。对于媒体播放和浏览深层链接,您可以使用本节后面所述的跳板 Activity。
处理深层链接 Intent
有关如何读取并响应用于启动您的应用 Activity 的 Intent 的指南,请参阅从传入 Intent 读取数据。
处理媒体播放和浏览深层链接
由于浏览和播放的 UI 由主机应用绘制,因此用于处理播放和浏览操作的深层链接的 Activity 不应具有自己的任何 UI。
相反,它应主要用于构建并使用 Intent 以启动媒体主机应用。如有必要,它还可以处理应用状态的任何其他更改,例如将媒体项目添加到队列。以下代码片段显示了跳板 Activity 的示例实现
fun DeepLinkTrampolineActivity : ComponentActivity() {
override fun onCreate() {
handleIntent(intent)
}
override fun onNewIntent(intent: Intent) {
handleIntent(intent)
}
private fun handleIntent(intent: Intent) {
// Handle any side effects, such as adding a song to the queue
...
// Build the intent used to start the media host app
val startMediaHostIntent = ...
startActivity(intent)
// Finish the activity immediately so it isn't shown on screen
finish()
}
}
读取媒体主机提示
根据连接到您的媒体浏览器服务的系统应用(包括其版本),您的应用可能会收到以下额外数据
错误处理
Android Automotive OS 上的媒体应用中的错误通过媒体会话的 PlaybackStateCompat
进行通信。对于所有错误,请在 PlaybackStateCompat
中设置相应的错误代码和错误消息。这会导致 UI 中出现 Toast
消息。
当发生错误但播放可以继续时,请发出非致命错误。例如,用户可能在登录前就可以在应用中播放音乐,但必须登录才能跳过歌曲。当您使用非致命错误时,系统可以建议用户登录,而不会中断当前媒体项目的播放。
发出非致命错误时,除了错误代码和错误消息外,请保留 PlaybackStateCompat
的其余部分。使用此方法可以让当前媒体项目的播放继续,同时用户决定是否登录。
当无法播放时,例如没有互联网连接且没有离线内容时,将 PlaybackStateCompat
状态设置为 STATE_ERROR
。
在后续更新 PlaybackStateCompat
时,清除任何错误代码和错误消息,以避免对同一错误显示多个警告。
如果在任何时候无法加载浏览树(例如,如果需要身份验证且用户未登录),请发送一个空的浏览树。要表示这一点,请为根媒体节点从 onLoadChildren()
返回空结果。发生这种情况时,系统将显示一个全屏错误,其中包含在 PlaybackStateCompat
中设置的错误消息。
可操作错误
如果错误是可操作的,请在 PlaybackStateCompat
中额外设置以下两个额外数据
PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL
:用于点击按钮以解决错误的标签。由于此字符串面向用户,因此请针对用户的当前语言区域进行本地化。PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT
:按钮运行的PendingIntent
,以解决错误,例如启动您的登录 Activity。
可操作错误显示为 Dialog
,并且只有在汽车停止时才能由用户解决。
测试错误情况
验证您的应用是否在所有场景中都能正常处理错误,包括
- 产品的不同层级:例如,免费版与高级版,或已登录与已退出。
- 不同的驾驶状态:例如,驻车与驾驶。
- 不同的连接状态:例如,在线与离线。
其他注意事项
在开发 Android Automotive OS 应用时,请记住以下其他注意事项
离线内容
如果适用,请实现离线播放支持。配备 Android Automotive OS 的汽车预计将拥有自己的数据连接功能,这意味着数据套餐已包含在车辆成本中或由用户付费。然而,汽车的连接性预计比移动设备更具可变性。
在考虑离线支持策略时,请牢记以下几点
- 下载内容的最佳时机是您的应用正在使用时。
- 不要假设 WiFi 可用。汽车可能永远不会进入 WiFi 范围,或者 OEM 可能已禁用 WiFi 而选择蜂窝网络。
- 虽然可以智能缓存用户期望使用的内容,但我们建议您通过设置 Activity 让用户更改此行为。
- 汽车上的磁盘空间各不相同,因此请为用户提供删除离线内容的方式,例如通过您的设置 Activity 中的选项。
WebView 支持
Android Automotive OS 支持 WebView,但仅限于您的设置和登录 Activity。使用 WebView 的 Activity 必须在 WebView 外部具有“关闭”或“返回”功能。
以下是一些可接受的 WebView 用例示例
- 在您的设置 Activity 中显示您的隐私政策、服务条款或其他法律相关链接。
- 您的登录 Activity 中的基于 Web 的流程。
使用 WebView 时,您可以启用 Javascript。
保护您的 WebView
采取一切可能的预防措施,确保您的 WebView 不会成为进入更广阔互联网的入口。以下代码片段展示了如何将 WebView 锁定到 loadUrl()
调用中使用的 URL 并防止重定向的示例。我们强烈建议您在可行时实施此类保护措施,例如在显示法律相关链接时。
Kotlin
override fun shouldOverrideUrlLoading(webView: WebView, webResourceRequest: WebResourceRequest): Boolean { val originalUri: Uri = Uri.parse(webView.originalUrl) // Check for allowed URLs if (originalUri.equals(Uri.parse(BLANK_URL)) || originalUri.equals(webResourceRequest.url)) { return false } if (webResourceRequest.isRedirect) { logger.w("Redirect detected, not following") return true } setupWizardWebViewClientListener.onUriBlocked(webResourceRequest.url) logger.w( String.format( "Navigation prevented to %s original is %s", webResourceRequest.url, originalUri)) return true }
Java
@Override public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest webResourceRequest) { Uri originalUri = Uri.parse(webView.getOriginalUrl()); // Check for allowed URLs if (originalUri.equals(Uri.parse(BLANK_URL)) || originalUri.equals(webResourceRequest.getUrl())) { return false; } if (webResourceRequest.isRedirect()) { logger.w("Redirect detected, not following"); return true; } setupWizardWebViewClientListener.onUriBlocked(webResourceRequest.getUrl()); logger.w( String.format( "Navigation prevented to %s original is %s", webResourceRequest.getUrl(), originalUri)); return true; }
软件包名称
由于您分发的是单独的 Android Automotive OS 版 Android 应用包 (APK),因此您可以重用移动应用中的软件包名称,也可以创建新的软件包名称。如果您使用不同的软件包名称,您的应用将在 Play 商店中有两个独立的商品详情。如果您重用当前的软件包名称,您的应用将在这两个平台中拥有一个商品详情。
这主要是业务决策。例如,如果有一个团队负责移动应用,另一个独立的团队负责您的 Android Automotive OS 应用,那么拥有单独的软件包名称并让每个团队管理自己的 Play 商店商品详情可能是有意义的。使用这两种方法所需的技术工作量没有太大差异。
下表总结了保留当前软件包名称和使用新软件包名称之间的一些其他主要区别
功能 | 相同软件包名称 | 新软件包名称 |
---|---|---|
商店商品详情 | 单一 | 多个 |
镜像安装 | 是:“设置向导期间快速应用重新安装” | 否 |
Play 商店审核流程 | 阻止审核:如果一个 APK 的审核失败,则同一版本中提交的其他 APK 将被阻止 | 单独审核 |
统计信息、指标和核心指标 | 组合:您可以筛选车载专用数据。 | 单独 |
索引和搜索排名 | 基于当前排名构建 | 无继承 |
与其他应用集成 | 如果媒体代码在两个 APK 之间共享,则很可能无需更改 | 可能需要更新相应的应用,例如 Google 助理的 URI 播放。 |
常见问题
请参阅以下部分,了解有关 Android Automotive OS 的一些常见问题的解答。
硬件
我的应用可以访问麦克风吗?
对于以 Android 10 (API 级别 29) 或更高版本为目标的应用,请参阅共享音频输入文档。在 API 级别 29 之前无法实现此功能。
我们可以访问哪些车载 API 以及如何访问?
您只能访问 OEM 公开的 API。目前正在开发流程以规范您访问这些 API 的方式。
应用可以使用 SetProperty()
和 GetProperty()
在 CarPropertyManager
中访问车载 API。请参阅源代码或参考文档查看所有可用属性的列表。如果属性标有 @SystemApi
,则仅限于预加载的系统应用。
支持哪些类型的音频编解码器?
请参阅 Android CDD 中的音频编解码器详情。
是否支持 Widevine DRM?
是的。Widevine DRM 受支持。
开发和测试
使用第三方 SDK 和库有什么限制或建议吗?
我们没有关于使用第三方 SDK 和库的具体指南。如果您选择使用第三方 SDK 和库,您仍有责任遵守所有车载应用质量要求。
我可以使用前台服务吗?
前台服务的唯一允许用例是下载内容以供离线使用。如果您有其他希望获得支持的前台服务用例,请使用Android Automotive OS 讨论组与我们联系。
发布 Android Automotive OS 应用
如何使用 Google Play 管理中心发布我的 Android Automotive OS 应用?
有关如何使用 Google Play 管理中心发布您的 Android Automotive OS 应用的详情,请参阅分发到汽车。
更多资源
要了解有关 Android Automotive OS 的更多信息,请参阅以下更多资源。
示例
指南
博客
视频
报告 Android Automotive OS 媒体问题
如果您在开发适用于 Android Automotive OS 的媒体应用时遇到问题,可以使用Google 问题跟踪器报告。请务必填写问题模板中请求的所有信息。
在提交新问题之前,请检查问题列表中是否已报告该问题。您可以通过点击跟踪器中问题旁的星标来订阅和投票。有关详情,请参阅订阅问题。