Android 10で追加されたBubblesについて

本記事はリクルートライフスタイル Advent Calendar 2019の12日目の記事です。

ホットペッパービューティーのネイティブアプリ開発を担当している中里です。この記事では、Android 10で追加されたBubblesの使い方と、使ってみた感想を書きたいと思います。

Bubblesとは?

Bubblesとは、Facebook Messengerのように他のアプリの上に描画する機能で、日本語だと「ふきだし」と訳されています。
https://developer.android.com/guide/topics/ui/bubbles

従来このようなUIを実現するためには、 SYSTEM_ALERT_WINDOW という権限が必要でしたが、 SYSTEM_ALERT_WINDOW は強い権限であり、また電池消費の観点からも不利であるため、それを代替するためにAndroid 10から登場しました。

アプリの作成

プロジェクトの作成

まず、いつも通りにプロジェクトを作成します。当然ですが、APIレベルは29以降に設定する必要があります。

1
2
3
4
5
6
7
android {
    compileSdkVersion 29
    defaultConfig {
        minSdkVersion 29
        targetSdkVersion 29
    }
}

Bubble用のActivityを作成

Bubbleの中身として表示したい内容を、Activityとして作成します。

1
2
3
4
5
6
class BubbleActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_bubble)
    }
}

次に、作成したActivityをAndroidManifestに追加します。

1
2
3
4
5
<activity
    android:name=".BubbleActivity"
    android:allowEmbedded="true"
    android:documentLaunchMode="always"
    android:resizeableActivity="true" />

Bubbleとして表示するためには、以下の3つの値を設定する必要があります。

  • allowEmbedded
    • Activityを別のActivityの子として起動できるかどうか。
  • documentLaunchMode
    • Activity起動時のタスクの追加方法。always を指定すると、常に新しいタスクを作成する。
  • resizeableActivity
    • 画面分割のように、サイズ変更が可能なActivityかどうか。

Bubbleの呼び出し

Bubbleの呼び出しは、以下のように基本的には通知と同じような実装になります。

  1. 通知を送るチャンネルの作成
  2. 通知の送信
    1. PendingIntentの作成
    2. BubbleMetadataの作成
    3. Notificationの作成
    4. NotificationManagerによる通知

まず、通知を送るチャンネルを作成します。このとき、Bubblesとして表示するために setAllowBubbles(true) を設定します。

1
2
3
4
5
6
7
private fun createNotificationChannel() {
    val channel = NotificationChannel("Channel Id", "Channel Name", NotificationManager.IMPORTANCE_HIGH)
    channel.description = "Channel Description"
    channel.setAllowBubbles(true)
    val notificationManager: NotificationManager = getSystemService() ?: return
    notificationManager.createNotificationChannel(channel)
}

次に、実際に通知を送信する処理です。

そのためにまずは、PendingIntentを作成します。

1
2
val intent = Intent(this, BubbleActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)

次に、BubbleMetadataを作成します。ちなみにここで setAutoExpandBubble(false) にすると、Bubbleが閉じた状態で表示されます。

1
2
3
4
5
6
val bubbleMetadata = Notification.BubbleMetadata.Builder()
    .setDesiredHeight(600)
    .setIcon(Icon.createWithResource(this, R.drawable.ic_launcher_foreground))
    .setIntent(pendingIntent)
    .setAutoExpandBubble(true)
    .build()

最後に、Notificationを作成します。ドキュメントだとPersonを指定していますが、指定しなくてもBubbleの表示には特に関係ありませんでした。

1
2
3
4
val notification = Notification.Builder(this, "Channel Id")
    .setSmallIcon(R.drawable.ic_launcher_foreground)
    .setBubbleMetadata(bubbleMetadata)
    .build()

あとは、作成したNotificationをNotificationManagerに投げます。

1
2
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(0, notification)

ここまで、実装したらあとは実行!と行きたいところですが、このままだと普通の通知として表示されてしまいます。

Notification

Bubblesの設定

Bubblesは公式ドキュメントにも書いてある通り、デベロッパープレビューであり、デフォルトでは無効になっています。Bubblesを利用するためには、開発者向けオプションから有効にする必要があります。

Settings

あるいは、以下のadbコマンドを実行しても有効にすることができます。

1
adb shell settings put secure notification_bubbles 1

実行結果

以上の実装・設定をすると、以下のように表示することができます。

Bubble

戻るボタンや暗い部分をタップすることで、小さいアイコンだけの表示になります。

Small bubble

このアイコンは動かすことができ、下の方に持っていけばdismissすることができます。

Dismiss

また、通知IDを変えて複数回呼び出せば、複数表示することもできます。

Multi

別の画面への遷移

Bubbleとして表示しているActivityから startActivity で別のActivityに遷移することもできます。そのためには、遷移先のActivityも同様にAndroidManifestに定義する必要があります。ただし、画面遷移の場合は新しいタスクを作成する必要はないので、 documentLaunchMode は指定しません。

1
2
3
4
<activity
    android:name=".SecondActivity"
    android:allowEmbedded="true"
    android:resizeableActivity="true" />

Second

戻るボタンを押すことで、前のActivityに戻ることもできます。

ちなみにAndroidManifestを正しく書かないと、Bubbleは閉じて普通に全画面遷移してしまいます。また、このあと再びBubbleを開くと、以下のような真っ黒な表示になってしまいました😅

Second error

ライフサイクル

Bubbleとして表示しているActivityのライフサイクルについては、表示時は

1
onCreate → onStart → onResume

と走り、Bubbleを閉じて小さいアイコンの状態に変わるときは、

1
onPause → onStop

となり、再び表示する時はまたonStart(onRestart)から始まりました。また、dismissしたらonDestroyが走りました。ライフサイクルについては特に意外性はなさそうです。

まとめ

実装方法は通常の通知と大きく変わらないため、そこまで新しい知識は必要とせずに実装することができました。ただ、古いユーザー向けには通知として表示されてしまうので、使い方は工夫する必要がありそうです。個人的には、チャットなどのアプリ以外でもBubblesは便利そうだなと感じたので、早く正式版になって欲しいなーと思いました。

それでは良いお年を🎄