Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Wear の通知スタイル

Wear OS by Google がサポートしている通知スタイルを使用することで、スマートウォッチのユーザー エクスペリエンスを改善できます。

一般的な通知スタイルを以下に示します。

  • BIG_TEXT_STYLE
  • BIG_PICTURE_STYLE
  • INBOX_STYLE
  • MESSAGING_STYLE

以下のセクションで、MESSAGING_STYLEBIG_TEXT_STYLE を通知に追加する方法について説明します。他の通知スタイルを採用する場合は、Wear の通知のサンプルをご覧ください。

以下の関連リソースもご覧ください。

MessagingStyle の通知を作成する

チャットアプリがインストールされている場合は、Android 7.0 で追加された NotificationCompat.MessagingStyle を通知で使用する必要があります。Wear は、MessagingStyle の通知(addMessage() を参照)に含まれているチャット メッセージを使用することで、展開可能な通知においてチャットアプリのような高度なエクスペリエンスを実現します。

注: MessagingStyle の展開可能な通知を作成するには、ペア設定されている Android スマートフォンにバージョン 1.5.0.2861804 以上の Wear コンパニオン アプリがインストールされている必要があります。

スマート リプライ

Wear には、MessagingStyle の通知用にスマート リプライが導入されています。スマート リプライは、状況に関連するタップ可能な選択肢を、展開可能な通知と RemoteInput に表示します。これらは選択肢の固定リストを強化するものであり、デベロッパーは setChoices() メソッドを使用して RemoteInput に表示できます。

スマート リプライでは、迅速(1 回のタップ)、控えめ(声を出す必要なし)、プライベート(ユーザーが受け取ったメッセージがスマートウォッチから送信されることがない)、確実(インターネット接続の必要なし)な方法でチャット メッセージに応答できます。

スマート リプライの応答は、MessagingStyle の通知から提供されたコンテキストを使用して、完全にスマートウォッチ上で動作する機械学習モデルによって生成されます。スマート リプライの応答を生成するために、Google のサーバーにユーザー通知データが送信されることはありません。

通知の操作用にスマート リプライを有効にするには、次の手順を行う必要があります。

  1. NotificationCompat.MessagingStyle を使用します。
  2. 通知の操作用に setAllowGeneratedReplies(true) メソッドを呼び出します。
  3. 通知の操作に RemoteInput が定義されていることを確認します(ここに応答が格納されます)。

次の例は、スマート リプライの応答を使用して MessagingStyle の通知を作成する方法を示しています。

Kotlin

    // Create an intent for the reply action
    val replyPendingIntent = Intent(this, ReplyActivity::class.java).let { replyIntent ->
        PendingIntent.getActivity(this, 0, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT)
    }

    // Create the reply action and add the remote input
    val action = NotificationCompat.Action.Builder(
            R.drawable.ic_reply_icon,
            getString(R.string.label),
            replyPendingIntent
    )
            .addRemoteInput(remoteInput)
            // 1) allow generated replies
            .setAllowGeneratedReplies(true)
            .build()

    val noti = NotificationCompat.Builder(context, channelId)
            .setContentTitle("${messages.size} new messages with $sender")
            .setContentText(subject)
            .setSmallIcon(R.drawable.new_message)
            .setLargeIcon(aBitmap)
            // 2) set the style to MessagingStyle
            .setStyle(
                    NotificationCompat.MessagingStyle(resources.getString(R.string.reply_name))
                            .addMessage(messages[0].text, messages[0].time, messages[0].sender)
                            .addMessage(messages[1].text, messages[1].time, messages[1].sender)
            )
            // 3) add an action with RemoteInput
            .extend(NotificationCompat.WearableExtender().addAction(action)).build()
    

Java

    // Create an intent for the reply action
    Intent replyIntent = new Intent(this, ReplyActivity.class);
    PendingIntent replyPendingIntent =
       PendingIntent.getActivity(this, 0, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    // Create the reply action and add the remote input
    NotificationCompat.Action action =
       new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
       getString(R.string.label), replyPendingIntent)
      .addRemoteInput(remoteInput)
       // 1) allow generated replies
      .setAllowGeneratedReplies(true)
      .build();

    Notification noti = new NotificationCompat.Builder()
        .setContentTitle(messages.length + " new messages with " + sender.toString())
        .setContentText(subject)
        .setSmallIcon(R.drawable.new_message)
        .setLargeIcon(aBitmap)
        // 2) set the style to MessagingStyle
        .setStyle(new NotificationCompat.MessagingStyle(resources.getString(R.string.reply_name))
        .addMessage(messages[0].getText(), messages[0].getTime(), messages[0].getSender())
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getSender()))
        // 3) add an action with RemoteInput
        .extend(new WearableExtender().addAction(action)).build();
    

画像を MessagingStyle の通知に追加する

画像を通知メッセージに追加するには、適切な MIME タイプを設定し、NotificationCompat.MessagingStyle.Message.setData() メソッドで画像の URI を設定します。

以下に、通知に画像データを設定するコード スニペットを示します。

Kotlin

    val message = NotificationCompat.MessagingStyle.Message("sticker", 1, "Jeff")
            .setData("image/png", stickerUri)

    val notification = NotificationCompat.Builder(context, channelId)
            .setStyle(
                    NotificationCompat.MessagingStyle("Me").addMessage(message)
            )
            .build()
    

Java

    NotificationCompat.MessagingStyle.Message message = new Message("sticker", 1, "Jeff")
       .setData("image/png", stickerUri);

    NotificationCompat notification = new NotificationCompat.Builder()
        .setStyle(new NotificationCompat.MessagingStyle("Me")
            .addMessage(message))
        .build();
    

上のコード スニペットの変数 stickerUri は、一般公開されている場所を指す URI です。詳しくは、こちらをご覧ください。

BigTextStyle の通知を作成する

BIG_TEXT_STYLE を使用すると、拡張テキスト コンテンツを通知に挿入できます。ハンドヘルド デバイスでは、通知を展開することによって拡張コンテンツを表示できます。ウェアラブル デバイスで BigTextStyle を使用すると、拡張コンテンツがデフォルトで表示されます。

拡張コンテンツを通知に追加するには、NotificationCompat.Builder オブジェクトで setStyle() を呼び出して、BigTextStyle または InboxStyle のインスタンスを渡します。

たとえば次のコードは、イベントの詳細な説明を含めるために、NotificationCompat.BigTextStyle のインスタンスをイベント通知に追加しています(これにより、setContentText() 用に提供されているスペースに入りきらないテキストを含めることができます)。

Kotlin

    // Specify the 'big view' content to display the long
    // event description that may not fit the normal content text.
    val bigStyle = NotificationCompat.BigTextStyle().run {
        bigText(eventDescription)
    }

    val notificationBuilder = NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_event)
            .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.notif_background))
            .setContentTitle(eventTitle)
            .setContentText(eventLocation)
            .setContentIntent(viewPendingIntent)
            .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent)
            .setStyle(bigStyle)
    

Java

    // Specify the 'big view' content to display the long
    // event description that may not fit the normal content text.
    BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
    bigStyle.bigText(eventDescription);

    NotificationCompat.Builder notificationBuilder =
        new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_event)
            .setLargeIcon(BitmapFactory.decodeResource(
                    getResources(), R.drawable.notif_background))
            .setContentTitle(eventTitle)
            .setContentText(eventLocation)
            .setContentIntent(viewPendingIntent)
            .addAction(R.drawable.ic_map,
                    getString(R.string.map), mapPendingIntent)
            .setStyle(bigStyle);
    

setLargeIcon() メソッドを使用すると、大きなアイコン画像を通知に追加できます。ただしそのアイコンは、ウェアラブルでは大きな背景画像として表示され、ウェアラブルの画面に合わせて拡大されるため、見た目がよくありません。ウェアラブル固有の背景画像を通知に追加する場合は、ウェアラブル固有の機能を通知用に追加するをご覧ください。大きな画像を含む通知のデザイン方法について詳しくは、Wear OS のデザインの原則をご覧ください。

MediaStyle の通知を作成する

NotificationCompat.MediaStyle クラスを使用すると、通知に再生コントロールを含めることができます。アクティブなメディア セッションを表す通知を特定し、それに応じて(たとえば、ロック画面にアルバムのアートワークを表示して)応答するシステム UI では、setMediaSession(MediaSession.Token) メソッドを使用して MediaSession.Token をアタッチします。

注: メディア セッションがアタッチされていないローカル通知で NotificationCompat.MediaStyle を使用すると、システムはその通知を通常の通知として表示し、メディア スタイルの詳細情報を無視します。