自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
配置 AppCard 主机
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
使用 AppCardHost
与显示 AppCard 的应用进行通信。
权限
任何使用 AppCardHost
的应用都必须具有以下权限:
android.permission.INTERACT_ACROSS_USERS_FULL
android.permission.QUERY_ALL_PACKAGES
- (仅在 API 级别 34 及更高级别中)
android.car.permission.BIND_APP_CARD_PROVIDER
初始化
如需初始化主机,请提供以下信息:
- 背景信息
updateRate
AppCard 更新速率(以毫秒为单位)。
fastUpdateRate
标记为 EnforceFastUpdateRate
的组件的更新速率(以毫秒为单位)
responseExecutor
您希望从 AppCard 应用接收响应的线程。
设计
您可以通过以下两种方式之一与 AppCardHost
进行交互:
或
AppCardListener
AppCardListener
组件会向 AppCardHost
注册自己,以接收来自 AppCardHost
和 AppCard 应用的通信更新。此处详细介绍了 AppCardListener
的接口函数。
fun onAppCardReceived(AppCardContainer)
当从应用收到 AppCard 时,系统会触发此函数。该函数会作为 AppCardContainer
发送,其中包含 AppCard 和 appIdentifier
,用于标识发送 AppCard 的应用
fun onComponentReceived(AppCardComponentContainer)
当从应用收到 AppCard 组件时,系统会触发此函数。该函数会作为 AppCardComponentContainer
发送,其中包含一个 AppCard 组件 Identifier
,用于识别发送 AppCard 的应用,以及一个字符串 ID,用于指向与该组件相关联的 AppCard。
fun onProviderRemoved(String, String?)
当 AppCard 提供程序被移除或停用时,系统会触发此函数。使用此方法可清理与给定软件包名称和提供方授权相关的所有有效 AppCard。
如果 authority 为 {@code null}
,则表示移除了整个软件包。
fun onProviderAdded(String, String?)
添加或启用 AppCard 提供程序时,系统会触发此函数。
用法示例。您可以将此函数用作触发器,以刷新 AppCard 选择器中的所有可用 AppCard。如果 authority 为 {@code null}
,则表示添加了整个软件包。
fun onPackageCommunicationError(appIdentifier, Throwable)
当 AppCardHost
在与 AppCard 提供程序通信时遇到错误时,系统会触发此函数。
用法示例。使用此方法可向用户显示其所选的 AppCard 遇到了错误。
API
fun refreshCompatibleapp()
每当使用托管应用的 activity 被恢复时,都应调用此方法,以便托管应用可以刷新其支持 AppCard 的应用列表。
fun destroy()
在使用宿主的 activity 被销毁时调用此方法,以便宿主可以清理所有连接和内部成员。
fun registerListener(AppCardListener)
用于注册 AppCardListener
。
fun unregisterListener(AppCardListener)
用于取消注册 AppCardListener
。
fun getAllAppCards(AppCardContext)
调用此方法可向已注册的 AppCardListener
提供系统中提供的所有 AppCard,并提供给定 AppCardContext
,以向提供方提供有关如何构建其 AppCard 的提示。
fun requestAppCard(AppCardContext, appIdentifier, String)
调用此方法可向已注册的 AppCardListener
提供特定的 AppCard,前提是提供一个 AppCardContext
,以向提供方提供有关如何构建其 AppCard 的提示。
fun notifyAppCardRemoved(appIdentifier, String)
通知 AppCard 提供商其 AppCard 已失效。
fun notifyAppCardInteraction(appIdentifier, String, String, String)
通知 AppCard 提供商其 AppCard 已被互动。
唯一支持的互动是按钮点击,以 AppCardMessageConstants.InteractionMessageConstants.MSG_INTERACTION_ON_CLICK
表示。
我们建议为 AppCard 创建一个带有 onClick
监听器的按钮,该监听器使用 appIdentifier
、AppCard ID、组件 ID 和互动 ID 调用此函数。
fun sendAppCardContextUpdate(AppCardContext, appIdentifier, String)
为特定 AppCard 发送 AppCardContext
更新。例如,从停车模式切换到驾驶模式时,请使用此方法发送 AppCardContext
更新,其中每个有效的 AppCard 的 isInteractable
都设置为 false
。
常见问题解答
在哪里可以找到示例实现?
每个 AppCardContentProvider
可以支持多少个 AppCard?
AppCardContentProvider
可以支持无限数量的 AppCard。不过,请务必在 AppCard 数量、性能下降和良好用户体验之间取得平衡。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-06-26。
[null,null,["最后更新时间 (UTC):2025-06-26。"],[],[],null,["# Configure an AppCard host\n\nUse `AppCardHost` to communicate with apps that show AppCards.\n\nPermissions\n-----------\n\nAny app that uses an `AppCardHost` must have the following permissions:\n\n- `android.permission.INTERACT_ACROSS_USERS_FULL`\n- `android.permission.QUERY_ALL_PACKAGES`\n- (In API level 34 and higher **only** ) `android.car.permission.BIND_APP_CARD_PROVIDER`\n\nInitialize\n----------\n\nTo initialize the host, provide:\n\n- Context\n- `updateRate` AppCard update rate in milliseconds.\n- `fastUpdateRate` Update rate in milliseconds for components tagged with `EnforceFastUpdateRate`\n- `responseExecutor` A thread on which you want to receive responses from AppCard apps.\n\nDesign\n------\n\nAn `AppCardHost` can be interacted with in one of two ways:\n\n- Register as an [`AppCardListener`](#appcardlistener)\n\nOR,\n\n- Interact with the [`AppCardHost` APIs](#api)\n\n### AppCardListener\n\nThe `AppCardListener` component registers itself with an `AppCardHost`\nto receive communication updates from the `AppCardHost` and AppCard apps.\nThe interface functions of an `AppCardListener` are detailed here.\n\n\u003cbr /\u003e\n\n`fun onAppCardReceived(AppCardContainer)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nThis function is triggered when an AppCard has been received from an app. It's sent as an `AppCardContainer` which provides an AppCard and an `appIdentifier` to identify the app that sent the AppCard\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun onComponentReceived(AppCardComponentContainer)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nThis function is triggered when an AppCard component is received from an app. It's sent as an `AppCardComponentContainer`, which provides an AppCards component, `Identifier` to identify the app that sent the AppCard, and a string ID to point to the AppCard to which the component is related.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun onProviderRemoved(String, String?)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nThis function is triggered when an AppCard provider has been removed or disabled. Use this method to clean up any active AppCard related to the given package name and provider authority.\u003cbr /\u003e\n\nIf authority is `{@code null}`, then an entire package was removed.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun onProviderAdded(String, String?)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nThis function is triggered when an AppCard provider has been added or enabled.\u003cbr /\u003e\n\n**Sample usage.** Use this function as a trigger to refresh all available\nAppCards in an AppCard picker. If authority is `{@code null}`, then an entire\npackage was added.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun onPackageCommunicationError(appIdentifier, Throwable)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nThis function is triggered when the `AppCardHost` encounters an error when communicating with an AppCard provider.\n\n\u003cbr /\u003e\n\n**Sample usage.** Use this method to show to the user that an AppCard they have\nselected has encountered an error.\n\n\u003cbr /\u003e\n\n### APIs\n\n\u003cbr /\u003e\n\n`fun refreshCompatibleapp()`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nThis method should be called whenever the activity that is using the host is resumed so that the host can refresh its list of apps that support AppCards.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun destroy()`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nCall this method when an activity that is using a host is destroyed so that the host can clean up all connections and internal members.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun registerListener(AppCardListener)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nUsed to register an `AppCardListener`.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun unregisterListener(AppCardListener)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nUsed to unregister an `AppCardListener`.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun getAllAppCards(AppCardContext)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nCall this method to supply a registered `AppCardListener` with all the AppCards provided in the system with a given `AppCardContext` that provides hints to the providers on how to structure their AppCard.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun requestAppCard(AppCardContext, appIdentifier, String)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nCall this method to supply a registered `AppCardListener` with a specific AppCard, given an `AppCardContext` that gives hints to the providers on how to structure their AppCard.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun notifyAppCardRemoved(appIdentifier, String)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nNotify an AppCard provider that its AppCard is no longer active.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun notifyAppCardInteraction(appIdentifier, String, String, String)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nNotify an AppCard provider that its AppCard has been interacted with. The only supported interaction is a button click, which is signified by a `AppCardMessageConstants.InteractionMessageConstants.MSG_INTERACTION_ON_CLICK`.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nWe recommend creating a button for an AppCard with an `onClick` listener that calls this function with `appIdentifier`, AppCard ID, component ID, and interaction ID.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n`fun sendAppCardContextUpdate(AppCardContext, appIdentifier, String)`\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nSend an `AppCardContext` update for a specific AppCard. For example, when shifting from Park mode to Drive mode, use this method to send an `AppCardContext` update in which `isInteractable` is set to `false` for each active AppCard.\n\n\u003cbr /\u003e\n\nFAQ\n---\n\n1. Where can I find sample implementations?\n\n - [Sample host](https://android.googlesource.com/platform/packages/apps/Car/libs/+/refs/tags/ub-automotive-master-20250418/car-app-card-host-lib/sample-host/). Shows all available AppCards in the system, along with\n testing capabilities.\n\n - DriverUI and [Pano manager](https://cs.android.com/android/platform/superproject/+/android-latest-release:packages/services/Car/car_product/distant_display/apps/CarDistantDisplayPanoManager/;l=1?q=CarDistantDisplayPanoManager&sq=&ss=android%2Fplatform%2Fsuperproject%2Fmain). Pano manager acts as the picker while\n DriverUI acts as the presenter.\n\n2. How many AppCards can each `AppCardContentProvider` support?\n\n An `AppCardContentProvider` can support an infinite number of AppCards.\n However, be sure to balance the number of AppCards with degraded performance\n versus a positive user experience."]]