会話に通知バブルを使用する

通知バブルを使用すると、ユーザーは会話を簡単に確認して参加できます。

図 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(API レベル 30)以降をターゲットとする場合は、バブル メタデータまたは通知が共有ショートカットを参照していることを確認します。
  5. バブルとして表示される通知をキャンセルしないようにアプリを変更します。通知をキャンセルすると、画面からバブルが削除されます。バブルを開くと、それに関連付けられている通知が自動的に非表示になります。

次の例はそれらの手順を示しています。

// Create a bubble intent.
val target = Intent(context, BubbleActivity::class.java)
val bubbleIntent =
    PendingIntent.getActivity(context, 0, target, PendingIntent.FLAG_IMMUTABLE /* 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 =
    ShortcutInfoCompat.Builder(context, shortcutId)
        .setCategories(setOf(category))
        .setIntent(Intent(Intent.ACTION_DEFAULT))
        .setLongLived(true)
        .setShortLabel("Chat partner name")
        .build()
// Publish the shortcut, otherwise the bubble metadata will not apply.
ShortcutManagerCompat.pushDynamicShortcut(context, shortcut)

// Create a bubble metadata.
val bubbleData = NotificationCompat.BubbleMetadata.Builder(bubbleIntent,
    IconCompat.createWithResource(context, R.drawable.ic_logo))
    .setDesiredHeight(600)
    .build()

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

バブルが送信されたときにアプリがフォアグラウンドにある場合、重要度は無視され、バブルは常に表示されます。ただし、ユーザーがアプリからのバブルまたは通知をブロックしている場合は表示されません。

展開されたバブルを作成する

バブルを自動的に展開状態で表示するように設定できます。この機能は、ユーザーが新しいチャットを開始するボタンをタップするなど、バブルを生成するアクションを実行した場合にのみ使用することをおすすめします。この場合、バブルの作成時に送信される最初の通知を抑制することも理にかなっています。

これらの動作を有効にするフラグを設定するには、setAutoExpandBubble() と setSuppressNotification() のメソッドを使用します。

次の例は、展開された状態で自動的に表示されるようにバブルを構成する方法を示しています。

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

バブル コンテンツのライフサイクル

バブルが展開されると、コンテンツ アクティビティは通常のプロセス ライフサイクルをたどり、アプリがフォアグラウンド プロセスになります(まだなっていない場合)。

バブルが折りたたまれるか閉じられると、アクティビティは破棄されます。これにより、アプリで他のフォアグラウンド コンポーネントが実行されているかどうかに応じて、プロセスがキャッシュに保存され、後で強制終了される可能性があります。

バブルが表示されるタイミング

ユーザーの操作を妨げないように、バブルは特定の状況でのみ表示されます。

Android 11(API レベル 30)以降をターゲットとするアプリの場合、会話の要件を満たしていない限り、通知はバブルとして表示されません。アプリが Android 10(API レベル 29)以前をターゲットとしている場合、通知がバブルとして表示されるのは、次の条件を 1 つ以上満たしている場合のみです。

これらの条件のいずれも満たされない場合、バブルではなく通知が表示されます。

バブルからアクティビティを起動する

バブルが新しいアクティビティを起動すると、新しいアクティビティは、同じタスクと同じバブル ウィンドウ内で起動するか、新しいタスクで全画面表示で起動し、起動したバブルを折りたたみます。

バブルと同じタスクで新しいアクティビティを起動するには: 1. インテントを起動するときにアクティビティ コンテキストを使用する。 activity.startActivity(intent) 1. インテントに FLAG_ACTIVITY_NEW_TASK フラグを設定しないでください。

それ以外の場合、新しいアクティビティは新しいタスクで開始され、バブルは閉じられます。

バブルは特定の会話を表すため、バブル内で起動されるアクティビティはその会話に関連している必要があります。また、バブル内でアクティビティを起動すると、バブルのタスクスタックが増加し、ユーザー エクスペリエンス(特にナビゲーション関連)が複雑になる可能性があります。

ベスト プラクティス

  • 通知をバブルとして送信するのは、重要な場合(進行中のコミュニケーションの一部である場合や、ユーザーがコンテンツのバブルを明示的にリクエストした場合など)のみにしてください。バブルは画面領域を使用し、他のアプリのコンテンツを覆います。
  • バブル通知が通常の通知としても機能することを確認します。ユーザーがバブルを無効にすると、バブル通知は通常の通知として表示されます。
  • BackHandler コンポーザブルを使用し、その enabled パラメータを UI 状態に関連付けて、必要な場合にのみ「戻る」ボタンの押下をインターセプトするようにします。ハンドラが無効になると、バブルは閉じます。

折りたたまれたバブルが更新されたメッセージを受信すると、バブルにバッジアイコンが表示され、未読メッセージがあることを示します。ユーザーが関連付けられたアプリでメッセージを開いた場合は、次の手順を行います。

サンプルアプリ

SociaLite サンプルアプリは、バブルを使用する会話型アプリです。デモ用に、このアプリでは chatbot を使用します。実際のアプリでは、人間によるメッセージにバブルを使用します。