将 Android Automotive OS 支持添加到模板化应用

Android Automotive OS 允许用户在车内安装应用。要在此平台触达用户,您需要分发一个经过驾驶优化且与 Android Automotive OS 兼容的应用。您可以重用 Android Auto 应用中几乎所有的代码和资源,但必须创建一个单独的版本,以满足本页所述的要求。

要在 Android Automotive OS 上运行您的车载应用,您需要最新的模板宿主 (Templates Host),它作为系统应用提供。

开发概览

添加 Android Automotive OS 支持只需几个步骤,如本页各部分所述:

  1. 创建汽车模块
  2. 声明对 Android Automotive OS 的支持
  3. 声明您的 CarAppServiceCarAppActivity
  4. 更新您的 Gradle 依赖项

使用 Android Studio Bumblebee 或更高版本,以确保所有 Automotive OS 功能都已启用。

创建汽车模块

Android Automotive OS 的某些组件(例如清单)具有平台特定的要求。创建一个模块,将这些组件的代码与项目中的其他代码(例如用于手机应用的代码)分离开来。

对于现有项目,请按照以下步骤将汽车模块添加到您的项目:

  1. 在 Android Studio 中,点击 文件 > 新建 > 新模块
  2. 选择 Automotive Module,然后点击 下一步
  3. 提供 应用/库名称。这是用户在 Android Automotive OS 上看到的您的应用名称。
  4. 输入 模块名称
  5. 编辑 软件包名称 以匹配您现有的应用。
  6. 对于 最低 SDK,选择 API 29: Android 10 (Q),然后点击 下一步。所有在 Android Automotive OS 上支持车载应用库的汽车都运行在 Android 10 API 级别 29 或更高版本,因此选择此值可定位所有兼容汽车。

  7. 选择 添加无 Activity,然后点击 完成

如果您要开始一个新项目:

  1. 在 Android Studio 中,点击 文件 > 新建 > 新项目
  2. 对于 项目类型,选择 Automotive
  3. 选择 无 Activity,然后点击 下一步
  4. 为您的项目提供一个 名称。这是用户在 Android Automotive OS 上看到的您的应用名称。
  5. 输入 软件包名称。有关选择软件包名称的更多详细信息,请参阅软件包名称部分。
  6. 对于 最低 SDK,选择 API 29: Android 10 (Q),然后点击 下一步

    所有在 Android Automotive OS 上支持车载应用库的汽车都运行在 Android 10 API 级别 29 或更高版本,因此选择此值可定位所有兼容汽车。

在 Android Studio 中创建模块后,打开新汽车模块中的 AndroidManifest.xml 文件。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.car.app">

    <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> 元素包含一些标准应用信息,以及一个声明支持 Android Automotive OS 的 <uses-feature> 元素。请注意,清单中未声明任何 activity。

声明功能要求

接下来,将以下 uses-feature 元素添加到您的清单中,以表明它需要模板宿主才能正常运行:

<application ...>
    ...
    <uses-feature
        android:name="android.software.car.templates_host"
        android:required="true" />
</application>

此外,请确保您的应用符合适用于所有 Android Automotive OS 应用的 Google Play 功能要求

更新您的 Gradle 依赖项

在您的汽车模块中,您必须添加对 androidx.car.app:app-automotive 工件的依赖,该工件包含您的应用在 Android Automotive OS 上运行所需的 CarAppActivity 实现。

如果您正在开发的应用同时支持 Android Auto 和 Android Automotive OS,我们建议您将 CarAppService 保留在一个单独的模块中,并在您的移动和汽车模块之间共享。如果您采用这种方法,您需要使用 Gradle 的项目依赖项来更新您的汽车模块以包含共享模块,如以下代码段所示:

Groovy

buildscript {
    ...
    dependencies {
        ...
        implementation "androidx.car.app:app-automotive:car_app_library_version"
        implementation project(':shared_module_name')
    }
}

Kotlin

buildscript {
    ...
    dependencies {
        ...
        implementation("androidx.car.app:app-automotive:car_app_library_version")
        implementation(project(":shared_module_name"))
    }
}

声明对 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 文件添加到您的 Android Automotive OS 模块的 res/xml/ 目录中。此文件应包含以下内容:

<automotiveApp>
    <uses name="template"/>
</automotiveApp>

声明您的 CarAppService 和 CarAppActivity

与 Android Auto 一样,Android Automotive OS 使用您的 CarAppService 实现来运行您的应用。有关实现和声明您的 CarAppService 的说明,请参阅创建您的 CarAppService 和 Session 以及声明您的 CarAppService

与 Android Auto 不同,您必须包含一个额外的应用组件 CarAppActivity,作为您的 Android Automotive OS 应用的入口点。此 activity 的实现包含在 androidx.car.app:app-automotive 工件中,负责与模板宿主应用通信以渲染您的应用 UI。您的清单中应该只有一个此 activity 的实例,并且必须按如下方式声明:

<activity
    android:exported="true"
    android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
    android:name="androidx.car.app.activity.CarAppActivity"
    android:launchMode="singleTask"
    android:label="Your app name">

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <meta-data android:name="distractionOptimized" android:value="true" />

</activity>
  • android:name 设置为来自 app-automotive 工件的 CarAppActivity 类的完全限定类名。
  • android:exported 设置为 true,因为该 activity 必须能够被自身以外的应用(即启动器)启动。
  • android:launchMode 设置为 singleTask,以便用户在离开后可以从启动器返回到同一 activity 实例。
  • android:theme 设置为 @android:style/Theme.DeviceDefault.NoActionBar,以便应用占用其可用的整个屏幕空间。
  • Intent 过滤器表明这是应用的启动器 activity。
  • 有一个 <meta-data> 元素,它向操作系统指示该应用可以在用户体验限制生效时使用,例如当车辆行驶时。

对于导航应用,CarAppActivity 还有一些必需的清单条目,如以下代码段所示:

<activity
    android:exported="true"
    android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
    android:name="androidx.car.app.activity.CarAppActivity"
    android:launchMode="singleTask"
    android:label="Your app name">

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <!-- Include the category below ONLY for navigation apps -->
        <category android:name="android.intent.category.APP_MAPS" />
    </intent-filter>

    <!-- Include the intent-filter below ONLY for navigation apps -->
    <intent-filter>
        <action android:name="androidx.car.app.action.NAVIGATE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="geo" />
    </intent-filter>

    <meta-data android:name="distractionOptimized" android:value="true" />

</activity>
  • 额外的 android.intent.category.APP_MAPS 类别会通知系统您的应用能够显示用户的位置。
  • androidx.car.app.action.NAVIGATE Intent 过滤器可确保用户在处理来自另一个车载应用的隐式导航 Intent 时可以选择使用您的应用。

为了改善您的模板化应用在 Android Automotive OS 设备上的体验,您可以支持将深层链接添加到您的 CarAppActivity。例如,这允许用户直接从浏览器打开您的应用,或在通过 快速分享 接收来自手机共享的 URL 时打开您的应用。

添加深层链接 Intent 过滤器

要通知操作系统您的应用能够处理深层链接,您需要在应用的 CarAppActivity<activity> 元素中添加适当的 Intent 过滤器。有关更多指导,请参阅为传入链接添加 Intent 过滤器

为了获得最佳用户体验,我们建议支持您的移动应用支持的所有深层链接,这些链接也可以合理地由您的车载应用支持。

为了处理 Intent,您的应用应在车载应用的 SessiononCreateScreen() 期间创建时以及在 onNewIntent() 期间收到新 Intent 时读取传入 Intent 中的数据

class MySession : Session() {

  ...

  override fun onCreateScreen(intent: Intent) : Screen {
    // Handle the intent when the app is being started for the first time
  }

  override fun onNewIntent(intent: Intent) {
    // Handle the intent when the app is already running
  }
}

其他注意事项

在开发您的 Android Automotive OS 应用时,请牢记以下其他注意事项:

软件包名称

由于您为 Android Automotive OS 分发单独的 Android 应用包 (APK),您可以重用移动应用的软件包名称或创建一个新的软件包名称。如果您使用不同的软件包名称,您的应用将在 Play 商店中显示两个单独的列表。如果您重用当前的软件包名称,您的应用将在两个平台中拥有一个统一的列表。

这主要是一个业务决策。例如,如果您有一个团队负责移动应用,另一个团队负责 Android Automotive OS 应用,那么使用单独的软件包名称并让每个团队管理自己的 Play 商店列表可能是有意义的。使用这两种方法所需的技术工作量没有太大差异。

下表总结了保留当前软件包名称或使用新软件包名称之间的一些其他主要区别:

功能 相同软件包名称 新软件包名称
商店列表 单一 多个
镜像安装 是:在设置向导期间快速重新安装应用
Play 商店审核流程 阻止审核:如果一个 APK 的审核失败,同一版本中提交的其他 APK 将被阻止 单独审核
统计数据、指标和核心指标 组合:您可以按设备名称过滤汽车特定数据。 单独
索引和搜索排名 基于现有排名构建 无继承
与其他应用集成 假设媒体代码在两个 APK 之间共享,则很可能不需要更改 可能需要更新相应的应用,例如使用 Google 助理进行 URI 播放时

离线内容

如果适用,在您的应用中实现离线支持。搭载 Android Automotive OS 的汽车预计将拥有自己的数据连接,这意味着数据流量套餐已包含在车辆成本中或由用户支付。然而,与移动设备相比,汽车的连接性预计会更具可变性。

在考虑您的离线支持策略时,请记住以下几点:

  • 下载内容的最佳时机是在您的应用使用期间。
  • 不要假设 WiFi 可用。汽车可能永远不会进入 WiFi 范围,或者原始设备制造商 (OEM) 可能已禁用 WiFi 而优先使用蜂窝网络。
  • 虽然智能缓存用户预期会使用的内容是可行的,但我们建议您让用户更改此行为。
  • 汽车上的磁盘空间各不相同,因此请为用户提供一种删除离线内容的方式。

常见问题

请参阅以下部分,了解有关 Android Automotive OS 的一些常见问题的答案。

使用第三方 SDK 和库是否有任何限制或建议?

对于使用第三方 SDK 和库没有具体指导。如果您选择使用第三方 SDK 和库,您仍需负责遵守所有车载应用质量要求。

如何使用 Google Play 管理中心发布我的 Android Automotive OS 应用?

有关如何使用 Google Play 管理中心发布 Android Automotive OS 应用的详细信息,请参阅分发到车载设备

疑难解答

请参阅以下内容,以获取有关 Android Automotive OS 上一些常见疑难解答方案的帮助。

  • 即使从系统设置中卸载了车载应用库应用,在尝试安装新版本时仍会收到错误。

    为确保应用已卸载,请使用命令 adb uninstall app.package.name