通知を作成する

通知は、アプリが使用されていないときに、アプリ内のイベントに関する短いタイムリーな情報を提供します。このドキュメントでは、さまざまな機能を備えた通知の作成方法について説明します。Android で通知がどのように表示されるかについては、通知の概要をご覧ください。通知を使用するサンプルコードについては、GitHub の People サンプルをご覧ください。

このページのコードでは、AndroidX ライブラリの NotificationCompat API を使用しています。これらの API を使用すると、Android 9(API レベル 28)との互換性を維持しながら、新しいバージョンの Android でのみ使用できる機能を追加できます。ただし、インライン返信アクションなどの一部の機能は、以前のバージョンでは動作しません。

AndroidX Core Library を追加する

Android Studio で作成されたほとんどのプロジェクトには、NotificationCompat を使用するために必要な依存関係が含まれていますが、モジュール レベルの build.gradle ファイルに次の依存関係が含まれていることを確認してください。

Groovy

dependencies {
    implementation "androidx.core:core:2.2.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-ktx:2.2.0")
}

基本的な通知を作成する

最も基本的でコンパクトな通知(折りたたみフォームとも呼ばれます)では、アイコン、タイトル、少量のテキスト コンテンツが表示されます。このセクションでは、ユーザーがタップしてアプリでアクティビティを起動できる通知を作成する方法について説明します。

図 1. アイコン、タイトル、テキストを含む通知。

通知の各部分の詳細については、通知の構造をご覧ください。

実行時の権限を宣言する

Android 13(API レベル 33)以降では、免除対象外(フォアグラウンド サービス(FGS)を含む)の通知をアプリから投稿するための実行時の権限がサポートされています。

アプリのマニフェスト ファイルで宣言する必要がある権限を、次のコード スニペットに示します。

<manifest ...>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application ...>
        ...
    </application>
</manifest>

実行時の権限の詳細については、通知に関する実行時の権限をご覧ください。

通知のコンテンツを設定する

まず、NotificationCompat.Builder オブジェクトを使用して通知のコンテンツとチャンネルを設定します。次の例は、以下を使用して通知を作成する方法を示しています。

  • setSmallIcon() で設定する小さなアイコン。これは、ユーザーに表示されるコンテンツのうち、唯一必須な要素です。

  • タイトル。setContentTitle() で設定します。

  • setContentText() で設定される本文。

  • setPriority() で設定される通知の優先度。Android 7.1 以前では、優先度によって通知の煩わしさが決まります。Android 8.0 以降では、次のセクションに示すように、チャネルの重要度を設定します。

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

NotificationCompat.Builder コンストラクタには、チャネル ID を指定する必要があります。これは Android 8.0(API レベル 26)以降との互換性のために必要ですが、それより前のバージョンでは無視されます。

デフォルトでは、通知のテキスト コンテンツは 1 行に収まるように切り捨てられます。展開可能な通知を作成すると、追加情報を表示できます。

図 2. 折りたたみフォームと展開フォームでの展開可能な通知。

通知を長くしたい場合は、setStyle() でスタイル テンプレートを追加して、展開可能な通知を有効にします。たとえば、次のコードはより大きなテキスト領域を作成します。

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(new NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

画像やメディア再生コントロールを追加する方法など、その他の大きな通知スタイルの詳細については、展開可能な通知を作成するをご覧ください。

チャネルを作成して重要度を設定する

Android 8.0 以降で通知を配信するには、NotificationChannel のインスタンスを createNotificationChannel() に渡して、アプリの通知チャンネルをシステムに登録します。次のコードは、SDK_INT バージョンの条件によってブロックされます。

Kotlin

private fun createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = getString(R.string.channel_name)
        val descriptionText = getString(R.string.channel_description)
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
            description = descriptionText
        }
        // Register the channel with the system.
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

Java

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this.
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

Android 8.0 以降では通知を送信する前に通知チャンネルを作成する必要があるため、アプリが起動したらすぐにこのコードを実行します。既存の通知チャンネルを作成してもオペレーションは実行されないため、これを繰り返しても安全です。

NotificationChannel コンストラクタには、NotificationManager クラスの定数のいずれかを使用した importance が必要です。このパラメータは、このチャンネルに属する通知のユーザー割り込み方法を決定します。前の例に示すように、Android 7.1 以前をサポートするには、prioritysetPriority() を設定します。

次の例に示すように、通知の重要度または優先度を設定する必要がありますが、システムはアラートの動作を保証しません。場合によっては、システムが他の要因に基づいて重要度レベルを変更することがあります。ユーザーは常に特定のチャネルの重要度レベルを再定義できます。

各レベルの意味については、通知の重要度レベルをご覧ください。

通知のタップ アクションを設定する

すべての通知はタップに反応する必要があります。通常は、通知に対応するアクティビティがアプリで開きます。そのためには、PendingIntent オブジェクトで定義されたコンテンツ インテントを指定し、setContentIntent() に渡します。

次のスニペットは、ユーザーが通知をタップしたときにアクティビティを開く基本的なインテントを作成する方法を示しています。

Kotlin

// Create an explicit intent for an Activity in your app.
val intent = Intent(this, AlertDetails::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)

val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)

Java

// Create an explicit intent for an Activity in your app.
Intent intent = new Intent(this, AlertDetails.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true);

このコードは setAutoCancel() を呼び出し、ユーザーが通知をタップすると自動的に通知を削除します。

上記の例の setFlags() メソッドは、ユーザーが通知を使用してアプリを起動した後、ユーザーが期待するナビゲーション エクスペリエンスを保持します。開始するアクティビティの種類(次のいずれか)に応じて使用することをおすすめします。

  • 通知へのレスポンスのためだけに存在するアクティビティ。通常のアプリの使用中にユーザーがこのアクティビティに移動する理由はないため、アクティビティはアプリの既存のタスクとバックスタックに追加されるのではなく、新しいタスクを開始します。これは、前のサンプルで作成したインテントのタイプです。

  • アプリの通常のアプリフロー内に存在するアクティビティ。この場合、アクティビティを開始するとバックスタックが作成され、ユーザーが期待する [戻る] ボタンと [上へ] ボタンが維持されます。

通知のインテントを構成するさまざまな方法については、通知からアクティビティを開始するをご覧ください。

通知を表示する

通知を表示するには、NotificationManagerCompat.notify() を呼び出して、通知の一意の ID と NotificationCompat.Builder.build() の結果を渡します。これを次の例に示します。

Kotlin

with(NotificationManagerCompat.from(this)) {
    if (ActivityCompat.checkSelfPermission(
            this@MainActivity,
            Manifest.permission.POST_NOTIFICATIONS
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        // TODO: Consider calling
        // ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        // public fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
        //                                        grantResults: IntArray)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.

        return@with
    }
    // notificationId is a unique int for each notification that you must define.
    notify(NOTIFICATION_ID, builder.build())
}

Java

with(NotificationManagerCompat.from(this)) {
   if (ActivityCompat.checkSelfPermission(
           this@MainActivity,
           Manifest.permission.POST_NOTIFICATIONS
       ) != PackageManager.PERMISSION_GRANTED
   ) {
       // TODO: Consider calling
       // ActivityCompat#requestPermissions
       // here to request the missing permissions, and then overriding
       // public void onRequestPermissionsResult(int requestCode, String[] permissions,
       //                                        int[] grantResults)
       // to handle the case where the user grants the permission. See the documentation
       // for ActivityCompat#requestPermissions for more details.

       return
   }
   // notificationId is a unique int for each notification that you must define.
   notify(NOTIFICATION_ID, builder.build())
}

NotificationManagerCompat.notify() に渡す通知 ID は、通知を更新または通知を削除するときに必要になるため、保存します。

また、Android 13 以降を搭載したデバイスで基本的な通知をテストするには、通知を手動でオンにするか、通知をリクエストするダイアログを作成します。

アクション ボタンを追加する

通知には、リマインダーのスヌーズやテキスト メッセージの返信など、ユーザーが迅速に応答できるアクション ボタンが最大 3 つ用意されています。ただし、ユーザーが通知をタップしたときに実行されるアクションと同じアクション ボタンは認められません。

図 3. アクション ボタンが 1 つの通知。

アクション ボタンを追加するには、PendingIntentaddAction() メソッドに渡します。これは通知のデフォルトのタップ アクションの設定に似ていますが、アクティビティを起動する代わりに、すでに開いているアプリを中断しないように、バックグラウンドでジョブを実行する BroadcastReceiver を開始できる点が異なります。

たとえば、次のコードは、特定のレシーバにブロードキャストを送信する方法を示しています。

Kotlin


val ACTION_SNOOZE = "snooze"

val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {
    action = ACTION_SNOOZE
    putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val snoozePendingIntent: PendingIntent =
    PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent)

Java


String ACTION_SNOOZE = "snooze"

Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(ACTION_SNOOZE);
snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
PendingIntent snoozePendingIntent =
        PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent);

バックグラウンド処理を実行する BroadcastReceiver の作成について詳しくは、ブロードキャストの概要をご覧ください。

トラックの一時停止やスキップなど、メディア再生ボタンを含む通知を作成する場合は、メディア コントロールを使用した通知の作成方法をご覧ください。

ダイレクト返信アクションを追加する

Android 7.0(API レベル 24)で導入されたダイレクト返信アクションでは、ユーザーが通知に直接テキストを入力できます。テキストはその後、アクティビティを開かずにアプリに配信されます。たとえば、ダイレクト返信アクションを使用して、ユーザーが通知内からテキスト メッセージに返信したり、タスクリストを更新したりできるようにします。

図 4. [返信]ボタンをタップすると テキスト入力欄が開きます

ダイレクト返信アクションは、テキスト入力を開く通知に追加ボタンとして表示されます。ユーザーが入力を終了すると、通知アクション用に指定したインテントにテキスト レスポンスが添付され、そのインテントがアプリに送信されます。

返信ボタンを追加する

ダイレクト返信をサポートする通知アクションを作成する手順は次のとおりです。

  1. 通知アクションに追加できる RemoteInput.Builder のインスタンスを作成します。このクラスのコンストラクタは、システムがテキスト入力のキーとして使用する文字列を受け入れます。後でアプリは、そのキーを使用して入力テキストを取得します。

    Kotlin

      // Key for the string that's delivered in the action's intent.
      private val KEY_TEXT_REPLY = "key_text_reply"
      var replyLabel: String = resources.getString(R.string.reply_label)
      var remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {
          setLabel(replyLabel)
          build()
      }
      

    Java

      // Key for the string that's delivered in the action's intent.
      private static final String KEY_TEXT_REPLY = "key_text_reply";
    
      String replyLabel = getResources().getString(R.string.reply_label);
      RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
              .setLabel(replyLabel)
              .build();
      
  2. 返信アクションの PendingIntent を作成します。

    Kotlin

      // Build a PendingIntent for the reply action to trigger.
      var replyPendingIntent: PendingIntent =
          PendingIntent.getBroadcast(applicationContext,
              conversation.getConversationId(),
              getMessageReplyIntent(conversation.getConversationId()),
              PendingIntent.FLAG_UPDATE_CURRENT)
      

    Java

      // Build a PendingIntent for the reply action to trigger.
      PendingIntent replyPendingIntent =
              PendingIntent.getBroadcast(getApplicationContext(),
                      conversation.getConversationId(),
                      getMessageReplyIntent(conversation.getConversationId()),
                      PendingIntent.FLAG_UPDATE_CURRENT);
      
  3. addRemoteInput() を使用して、RemoteInput オブジェクトをアクションにアタッチします。

    Kotlin

      // Create the reply action and add the remote input.
      var action: NotificationCompat.Action =
          NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
              getString(R.string.label), replyPendingIntent)
              .addRemoteInput(remoteInput)
              .build()
      

    Java

      // 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)
                      .build();
      
  4. 通知にアクションを適用し、通知を発行します。

    Kotlin

      // Build the notification and add the action.
      val newMessageNotification = Notification.Builder(context, CHANNEL_ID)
              .setSmallIcon(R.drawable.ic_message)
              .setContentTitle(getString(R.string.title))
              .setContentText(getString(R.string.content))
              .addAction(action)
              .build()
    
      // Issue the notification.
      with(NotificationManagerCompat.from(this)) {
          notificationManager.notify(notificationId, newMessageNotification)
      }
      

    Java

      // Build the notification and add the action.
      Notification newMessageNotification = new Notification.Builder(context, CHANNEL_ID)
              .setSmallIcon(R.drawable.ic_message)
              .setContentTitle(getString(R.string.title))
              .setContentText(getString(R.string.content))
              .addAction(action)
              .build();
    
      // Issue the notification.
      NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
      notificationManager.notify(notificationId, newMessageNotification);
      

図 4 に示すように、ユーザーが通知アクションをトリガーすると、レスポンスの入力を求めるメッセージがユーザーに表示されます。

返信からユーザー入力を取得する

通知の返信 UI からユーザー入力を受け取るには、RemoteInput.getResultsFromIntent() を呼び出して、BroadcastReceiver で受け取った Intent を渡します。

Kotlin

private fun getMessageText(intent: Intent): CharSequence? {
    return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)
}

Java

private CharSequence getMessageText(Intent intent) {
    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
    if (remoteInput != null) {
        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
    }
    return null;
 }

テキストを処理したら、同じ ID とタグ(使用されている場合)で NotificationManagerCompat.notify() を呼び出して、通知を更新します。これは、ダイレクト リプライの UI を非表示にして、返信が正しく受信され、処理されたことをユーザーに確認するために必要です。

Kotlin

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
val repliedNotification = Notification.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_message)
        .setContentText(getString(R.string.replied))
        .build()

// Issue the new notification.
NotificationManagerCompat.from(this).apply {
    notificationManager.notify(notificationId, repliedNotification)
}

Java

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
Notification repliedNotification = new Notification.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_message)
        .setContentText(getString(R.string.replied))
        .build();

// Issue the new notification.
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, repliedNotification);

この新しい通知を操作するときは、レシーバーの onReceive() メソッドに渡されたコンテキストを使用します。

setRemoteInputHistory() を呼び出して、通知の下部に返信を追加します。ただし、メッセージ アプリを作成する場合は、メッセージ スタイルの通知を作成し、新しいメッセージを会話に追加します。

メッセージ アプリからの通知に関するその他のアドバイスについては、メッセージ アプリのおすすめの方法をご覧ください。

進行状況バーを追加する

通知に、進行中のオペレーションのステータスをアニメーションで表示する進行状況インジケーターを表示できます。

図 5. オペレーション中の進行状況バー。

オペレーションの完了状況をいつでも見積もることができる場合は、setProgress(max, progress, false) を呼び出して、「確定」形式のインジケーターを使用します(図 5 を参照)。最初のパラメータは「complete」値です(100 など)。2 つ目は完了状況です最後は確定的な進行状況バーであることを示します。

オペレーションの進行中は、次の例のように、更新された progress の値で setProgress(max, progress, false) を継続的に呼び出し、通知を再発行します。

Kotlin

val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
    setContentTitle("Picture Download")
    setContentText("Download in progress")
    setSmallIcon(R.drawable.ic_notification)
    setPriority(NotificationCompat.PRIORITY_LOW)
}
val PROGRESS_MAX = 100
val PROGRESS_CURRENT = 0
NotificationManagerCompat.from(this).apply {
    // Issue the initial notification with zero progress.
    builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
    notify(notificationId, builder.build())

    // Do the job that tracks the progress here.
    // Usually, this is in a worker thread.
    // To show progress, update PROGRESS_CURRENT and update the notification with:
    // builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
    // notificationManager.notify(notificationId, builder.build());

    // When done, update the notification once more to remove the progress bar.
    builder.setContentText("Download complete")
            .setProgress(0, 0, false)
    notify(notificationId, builder.build())
}

Java

...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setContentTitle("Picture Download")
        .setContentText("Download in progress")
        .setSmallIcon(R.drawable.ic_notification)
        .setPriority(NotificationCompat.PRIORITY_LOW);

// Issue the initial notification with zero progress.
int PROGRESS_MAX = 100;
int PROGRESS_CURRENT = 0;
builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
notificationManager.notify(notificationId, builder.build());

// Do the job that tracks the progress here.
// Usually, this is in a worker thread.
// To show progress, update PROGRESS_CURRENT and update the notification with:
// builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
// notificationManager.notify(notificationId, builder.build());

// When done, update the notification once more to remove the progress bar.
builder.setContentText("Download complete")
        .setProgress(0,0,false);
notificationManager.notify(notificationId, builder.build());

オペレーションの最後で、progressmax と等しくなる必要があります。進行状況バーを放置して、オペレーションの完了を表示するか、オペレーションを削除できます。いずれの場合も、通知テキストを更新して、オペレーションが完了したことを示します。進行状況バーを削除するには、setProgress(0, 0, false) を呼び出します。

不確定な進行状況バー(完了率を示さないバー)を表示するには、setProgress(0, 0, true) を呼び出します。結果は、完了を示さない連続アニメーションであることを除き、前の進行状況バーと同じスタイルのインジケーターになります。進行状況アニメーションは、setProgress(0, 0, false) を呼び出した後、通知を更新してアクティビティ インジケーターを削除するまで実行されます。

通知テキストを変更して、オペレーションが完了したことを示すことを忘れないでください。

システムレベルのカテゴリを設定する

Android は、システム全体の事前定義されたカテゴリを使用して、ユーザーがサイレント モードを有効にしたときに、特定の通知でユーザーの操作を妨げるかどうかを判断します。

通知が NotificationCompat で定義された通知カテゴリ(CATEGORY_ALARMCATEGORY_REMINDERCATEGORY_EVENTCATEGORY_CALL など)のいずれかに該当する場合は、適切なカテゴリを setCategory() に渡して、その旨を宣言します。

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE);

システムは、通知カテゴリに関するこの情報を使用して、デバイスがサイレント モードになっているときに通知を表示するかどうかを決定します。ただし、システム全体のカテゴリを設定する必要はありません。これは、通知が NotificationCompat で定義されたカテゴリのいずれかと一致する場合にのみ行ってください。

緊急メッセージを表示する

アプリで、電話の着信やアラーム音など、緊急で時間的制約のあるメッセージを表示しなければならない場合があります。このような場合は、全画面インテントを通知に関連付けることができます。

通知が呼び出されると、デバイスのロックステータスに応じて、次のいずれかが表示されます。

  • ユーザーのデバイスがロックされている場合は、ロック画面を覆う全画面表示のアクティビティが表示されます。
  • ユーザーのデバイスがロック解除されている場合、通知を処理または非表示にするオプションを含む展開された形式で通知が表示されます。

次のコード スニペットは、通知を全画面インテントに関連付ける方法を示しています。

Kotlin

val fullScreenIntent = Intent(this, ImportantActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
    fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true)

Java

Intent fullScreenIntent = new Intent(this, ImportantActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
        fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true);

ロック画面での可視性を設定する

ロック画面からの通知に表示される詳細レベルを制御するには、setVisibility() を呼び出して次のいずれかの値を指定します。

  • VISIBILITY_PUBLIC: 通知の全コンテンツがロック画面に表示されます。

  • VISIBILITY_SECRET: ロック画面に通知のどの部分も表示されません。

  • VISIBILITY_PRIVATE: 通知のアイコンやコンテンツ タイトルなどの基本情報のみがロック画面に表示されます。通知の全内容は表示されません。

VISIBILITY_PRIVATE を設定すると、特定の詳細を非表示にする代替バージョンの通知コンテンツを指定することもできます。たとえば、SMS アプリでは「新しいテキスト メッセージが 3 件あります」という通知は表示されますが、メッセージの内容と送信者は非表示になります。この代替通知を提供するには、まず NotificationCompat.Builder を使用して通常どおりに代替通知を作成します。次に、setPublicVersion() を使用して、代替通知を通常の通知に接続します。

ロック画面に自分の通知を表示するかどうかは、常にユーザー自身が制御でき、アプリの通知チャンネルに基づいて制御できることにご注意ください。

通知を更新する

通知を発行した後に通知を更新するには、NotificationManagerCompat.notify() を再度呼び出し、前に使用したのと同じ ID を渡します。前の通知が破棄された場合は、代わりに新しい通知が作成されます。

必要に応じて setOnlyAlertOnce() を呼び出すことで、通知が最初に表示されたときにのみ、音、バイブレーション、視覚的な手がかりで通知をユーザーに知らせることができます。その後の更新では通知されません。

通知を消去する

通知は、次のいずれかが発生するまで表示されたままになります。

  • ユーザーが通知を閉じた。
  • 通知の作成時に setAutoCancel() を呼び出した場合、ユーザーが通知をタップします。
  • 特定の通知 ID を取得するには、cancel() を呼び出します。このメソッドは進行中の通知も削除されます。
  • cancelAll() を呼び出して、以前に発行したすべての通知を削除します。
  • 通知の作成時に setTimeoutAfter() を使用してタイムアウトを設定した場合は、指定した時間が経過します。必要に応じて、指定したタイムアウト時間が経過する前に通知をキャンセルできます。

メッセージング アプリのおすすめの方法

メッセージ アプリとチャットアプリの通知を作成する際は、ここに記載されているベスト プラクティスを検討してください。

MessagingStyle を使用する

Android 7.0(API レベル 24)以降、Android にはメッセージ コンテンツ専用の通知スタイル テンプレートが用意されています。NotificationCompat.MessagingStyle クラスを使用すると、会話のタイトル、追加のメッセージ、通知のコンテンツ ビューなど、通知に表示される複数のラベルを変更できます。

次のコード スニペットは、MessagingStyle クラスを使用して通知のスタイルをカスタマイズする方法を示しています。

Kotlin

val user = Person.Builder()
    .setIcon(userIcon)
    .setName(userName)
    .build()

val notification = NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("2 new messages with $sender")
    .setContentText(subject)
    .setSmallIcon(R.drawable.new_message)
    .setStyle(NotificationCompat.MessagingStyle(user)
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
        .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
    )
    .build()

Java

Person user = new Person.Builder()
    .setIcon(userIcon)
    .setName(userName)
    .build();

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("2 new messages with " + sender)
    .setContentText(subject)
    .setSmallIcon(R.drawable.new_message)
    .setStyle(new NotificationCompat.MessagingStyle(user)
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
        .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
    )
    .build();

Android 9.0(API レベル 28)以降では、通知とそのアバターを最適にレンダリングするために、Person クラスを使用する必要もあります。

NotificationCompat.MessagingStyle を使用する場合は、次の操作を行います。

  • 3 人以上が参加するグループ チャットのタイトルを設定するには、MessagingStyle.setConversationTitle() を呼び出します。会話のタイトルとしては、グループ チャットの名前や、名前がない場合は会話の参加者リストなどが適しています。これがないと、メッセージが、会話内の最新のメッセージの送信者との 1 対 1 の会話に属していると誤認される可能性があります。
  • 画像などのメディア メッセージを含めるには、MessagingStyle.setData() メソッドを使用します。パターン image/* の MIME タイプがサポートされています。

ダイレクト リプライを使用する

ダイレクト返信では、ユーザーがメッセージにインラインで返信できます。

  • ユーザーがインライン返信アクションで返信したら、MessagingStyle.addMessage() を使用して MessagingStyle 通知を更新し、通知を撤回またはキャンセルしないでください。通知をキャンセルしない場合、ユーザーは通知から複数の返信を送信できます。
  • インライン返信アクションを Wear OS に対応させるには、Action.WearableExtender.setHintDisplayInlineAction(true) を呼び出します。
  • addHistoricMessage() メソッドを使用して、通知に履歴メッセージを追加して、ダイレクト返信の会話にコンテキストを提供します。

スマート リプライを有効にする

  • スマート リプライを有効にするには、返信アクションで setAllowGeneratedResponses(true) を呼び出します。これにより、通知が Wear OS デバイスにブリッジされたときに、ユーザーがスマート リプライで応答を使用できるようになります。スマート リプライの応答は、NotificationCompat.MessagingStyle 通知で提供されるコンテキストを使用して、完全にスマートウォッチ上の機械学習モデルによって生成されます。応答を生成するためにデータがインターネットにアップロードされることはありません。

通知メタデータを追加する