通知を作成する

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

このページのコードでは、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 クラスの定数の 1 つを使用する importance が必要です。このパラメータは、このチャネルに属する通知でユーザーの操作に割り込む方法を決定します。前述の例に示すように、Android 7.1 以前をサポートするために setPriority() で優先度を設定します。

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

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

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

すべての通知はタップに応答する必要があります。一般的には、通知に対応するアクティビティをアプリで開きます。そのためには、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 を参照)。最初のパラメータは「完了」を表す値(たとえば 100)です。2 つ目は、どの程度完了しているかです。last は、これが確定的な進行状況バーであることを示します。

オペレーションの進行とともに継続的に setProgress(max, progress, false) を呼び出し(更新された progress の値を指定)、通知を再発行します。次の例をご覧ください。

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 の通知から提供されたコンテキストを使用して、完全にスマートウォッチ上で動作する機械学習モデルによって生成されます。応答の生成のためにデータがインターネットにアップロードされることはありません。

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