使用气泡让用户参与对话

气泡使用户更容易查看和参与对话。

图 1. 聊天气泡。

气泡内置于通知系统中。它们浮在其他应用内容之上,并且无论用户走到哪里都会跟随用户。用户可以展开气泡以显示和交互应用内容,也可以在不使用时将其折叠。

当设备被锁定或始终显示屏幕处于活动状态时,气泡会像普通通知一样显示。

气泡是一项选择退出功能。当应用显示其第一个气泡时,权限对话框提供两个选择

  • 阻止应用的所有气泡。通知不会被阻止,但它们永远不会以气泡的形式显示。
  • 允许应用的所有气泡。所有使用 BubbleMetaData 发送的通知都将显示为气泡。

气泡 API

气泡是使用通知 API 创建的,因此像往常一样发送您的通知。如果希望您的通知显示为气泡,请附加额外数据。

气泡的展开视图由您选择的活动创建。配置活动以正确显示为气泡。该活动必须是 可调整大小的嵌入式的。如果缺少其中任何一项要求,它将显示为通知。

以下代码演示了如何实现气泡

<activity
  android:name=".bubbles.BubbleActivity"
  android:theme="@style/AppTheme.NoActionBar"
  android:label="@string/title_activity_bubble"
  android:allowEmbedded="true"
  android:resizeableActivity="true"
/>

如果您的应用显示多种相同类型的气泡,例如与不同联系人进行的多项聊天对话,则该活动必须能够启动多个实例。在运行 Android 10 及更低版本的设备上,除非您显式将 documentLaunchMode 设置为 "always",否则通知不会显示为气泡。从 Android 11 开始,您无需显式设置此值,因为系统会自动将所有对话的 documentLaunchMode 设置为 "always"

要发送气泡,请按照以下步骤操作

  1. 像往常一样创建通知
  2. 调用 BubbleMetadata.Builder(PendingIntent, Icon)BubbleMetadata.Builder(String) 以创建 BubbleMetadata 对象。
  3. 使用 setBubbleMetadata() 将元数据添加到通知。
  4. 如果目标是 Android 11 或更高版本,请确保气泡元数据或通知引用共享快捷方式。
  5. 修改您的应用以取消显示为气泡的通知。要检查通知活动是否作为气泡启动,请调用 Activity#isLaunchedFromBubble()。取消通知会将气泡从屏幕上移除。打开气泡会自动隐藏与其关联的通知。

以下示例显示了这些步骤

Kotlin

// Create a bubble intent.
val target = Intent(context, BubbleActivity::class.java)
val bubbleIntent = PendingIntent.getActivity(context, 0, target, 0 /* flags */)
val category = "com.example.category.IMG_SHARE_TARGET"

val chatPartner = Person.Builder()
    .setName("Chat partner")
    .setImportant(true)
    .build()

// Create a sharing shortcut.
val shortcutId = generateShortcutId()
val shortcut =
   ShortcutInfo.Builder(mContext, shortcutId)
       .setCategories(setOf(category))
       .setIntent(Intent(Intent.ACTION_DEFAULT))
       .setLongLived(true)
       .setShortLabel(chatPartner.name)
       .build()

// Create a bubble metadata.
val bubbleData = Notification.BubbleMetadata.Builder(bubbleIntent,
            Icon.createWithResource(context, R.drawable.icon))
    .setDesiredHeight(600)
    .build()

// Create a notification, referencing the sharing shortcut.
val builder = Notification.Builder(context, CHANNEL_ID)
    .setContentIntent(contentIntent)
    .setSmallIcon(smallIcon)
    .setBubbleMetadata(bubbleData)
    .setShortcutId(shortcutId)
    .addPerson(chatPartner)

Java

// Create a bubble intent.
Intent target = new Intent(mContext, BubbleActivity.class);
PendingIntent bubbleIntent =
    PendingIntent.getActivity(mContext, 0, target, 0 /* flags */);

private val CATEGORY_TEXT_SHARE_TARGET =
    "com.example.category.IMG_SHARE_TARGET"

Person chatPartner = new Person.Builder()
        .setName("Chat partner")
        .setImportant(true)
        .build();

// Create a sharing shortcut.
private String shortcutId = generateShortcutId();
ShortcutInfo shortcut =
   new ShortcutInfo.Builder(mContext, shortcutId)
       .setCategories(Collections.singleton(CATEGORY_TEXT_SHARE_TARGET))
       .setIntent(Intent(Intent.ACTION_DEFAULT))
       .setLongLived(true)
       .setShortLabel(chatPartner.getName())
       .build();

// Create a bubble metadata.
Notification.BubbleMetadata bubbleData =
    new Notification.BubbleMetadata.Builder(bubbleIntent,
            Icon.createWithResource(context, R.drawable.icon))
        .setDesiredHeight(600)
        .build();

// Create a notification, referencing the sharing shortcut.
Notification.Builder builder =
    new Notification.Builder(mContext, CHANNEL_ID)
        .setContentIntent(contentIntent)
        .setSmallIcon(smallIcon)
        .setBubbleMetadata(bubbleData)
        .setShortcutId(shortcutId)
        .addPerson(chatPartner);

如果您的应用在发送气泡时处于前台,则会忽略重要性,并且始终显示您的气泡,除非用户阻止了应用的气泡或通知。

创建展开的气泡

您可以配置气泡以自动以展开状态显示。我们建议仅在用户执行导致气泡的操作(例如点击按钮以开始新聊天)时使用此功能。在这种情况下,在创建气泡时抑制发送的初始通知也是有意义的。

您可以使用一些方法来设置启用这些行为的标志:setAutoExpandBubble()setSuppressNotification()

以下示例显示了如何配置气泡以自动以展开状态显示

Kotlin

val bubbleMetadata = Notification.BubbleMetadata.Builder()
    .setDesiredHeight(600)
    .setIntent(bubbleIntent)
    .setAutoExpandBubble(true)
    .setSuppressNotification(true)
    .build()

Java

Notification.BubbleMetadata bubbleData =
    new Notification.BubbleMetadata.Builder()
        .setDesiredHeight(600)
        .setIntent(bubbleIntent)
        .setAutoExpandBubble(true)
        .setSuppressNotification(true)
        .build();

气泡内容生命周期

当气泡展开时,内容活动会经历正常的 进程生命周期,如果应用尚未处于前台,则会导致应用成为前台进程。

当气泡折叠或关闭时,活动将被销毁。这可能会导致进程被缓存并随后被终止,具体取决于应用是否有其他正在运行的前台组件。

气泡何时出现

为了减少对用户的干扰,气泡仅在某些情况下才会出现。

如果应用的目标是 Android 11 或更高版本,则除非通知满足 对话要求,否则不会显示为气泡。如果应用的目标是 Android 10 或更低版本,则仅当满足以下一个或多个条件时,通知才会显示为气泡

如果未满足这些条件中的任何一个,则会显示通知而不是气泡。

从气泡启动活动

当气泡启动新活动时,新活动将要么在同一任务和同一气泡窗口中启动,要么在全屏的新任务中启动,从而折叠启动它的气泡。

要在与气泡相同的任务中启动新活动:1. 在启动意图时使用活动上下文,activity.startActivity(intent),以及 1. 不要在意图上设置 FLAG_ACTIVITY_NEW_TASK 标志。

否则,新活动将在新任务中启动,气泡将折叠。

请记住,气泡代表特定的对话,因此在气泡内启动的活动应与该对话相关。此外,在气泡内启动活动会增加气泡的任务堆栈,并且可能会使用户体验复杂化,尤其是在导航方面。

最佳实践

  • 仅当通知非常重要时才将其作为气泡发送,例如,当它是正在进行的通信的一部分,或用户明确请求将内容显示为气泡时。气泡会占用屏幕空间并覆盖其他应用内容。
  • 确保您的气泡通知也能作为普通通知使用。当用户禁用气泡时,气泡通知将显示为普通通知。
  • 在覆盖气泡活动中的onBackPressed时,调用super.onBackPressed。否则,您的气泡可能无法正常工作。

当折叠的气泡收到更新的消息时,气泡会显示一个徽章图标以指示未读消息。当用户在关联的应用中打开消息时,请按照以下步骤操作

示例应用

People示例应用是一个使用气泡的对话应用。出于演示目的,此应用使用聊天机器人。在实际应用中,请将气泡用于人类发送的消息。