通知は、アプリが使用されていないときに、アプリのイベントに関する短いタイムリーな情報を提供します。このドキュメントでは、さまざまな機能を備えた通知を作成する方法について説明します。Android で通知がどのように表示されるかについては、通知の概要をご覧ください。通知を使用するサンプルコードについては、GitHub の People サンプルをご覧ください。
このページのコードでは、AndroidX ライブラリの NotificationCompat
API を使用しています。これらの API を使用すると、Android 9(API レベル 28)との下位互換性を維持しながら、新しいバージョンの Android でのみ利用可能な機能を追加できます。ただし、以前のバージョンでは、インライン返信アクションなどの一部の機能は何も実行しません。
AndroidX コアライブラリを追加する
Android Studio で作成されたほとんどのプロジェクトには、NotificationCompat
を使用するために必要な依存関係が含まれていますが、モジュール レベルの build.gradle
ファイルに次の依存関係が含まれていることを確認します。
Groovy
dependencies { implementation "androidx.core:core:2.2.0" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:2.2.0") }
基本的な通知を作成する
最も基本的かつコンパクトな形式(折りたたみフォームとも呼ばれます)の通知は、アイコン、タイトル、少量のテキスト コンテンツを表示します。このセクションでは、ユーザーがタップしてアプリ内のアクティビティを起動できる通知を作成する方法について説明します。
通知の各部分の詳細については、通知の構造をご覧ください。
実行時の権限を宣言する
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 行に収まるように切り捨てられます。展開可能な通知を作成すると、追加情報を表示できます。
通知を長くしたい場合は、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 以前をサポートするには、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 つまで設定できます。ただし、これらのアクション ボタンは、ユーザーが通知をタップしたときに実行されるアクションと重複しないようにする必要があります。
アクション ボタンを追加するには、PendingIntent
を addAction()
メソッドに渡します。これは、通知のデフォルトのタップ アクションを設定することに似ています。ただし、アクティビティを起動する代わりに、バックグラウンドでジョブを実行する 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)で導入されたダイレクト返信アクションを使用すると、ユーザーは通知に直接テキストを入力できます。テキストは、アクティビティを開かずにアプリに配信されます。たとえば、ダイレクト返信アクションを使用して、ユーザーが通知内からテキスト メッセージに返信したり、タスクリストを更新できるようにします。
ダイレクト返信アクションは、テキスト入力を開く追加ボタンとして通知に表示されます。ユーザーが入力を終了すると、通知アクション用に指定したインテントにテキスト レスポンスが添付され、アプリにインテントが送信されます。
返信ボタンを追加する
ダイレクト返信をサポートする通知アクションを作成する手順は次のとおりです。
- 通知アクションに追加できる
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();
- 返信アクションの
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);
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();
- アクションを通知に適用して通知を発行します。
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()
を呼び出して、通知の下部に返信を追加します。ただし、メッセージ アプリを作成する場合は、メッセージ スタイルの通知を作成して、新しいメッセージを会話に追加します。
メッセージ アプリからの通知に関するアドバイスについては、メッセージ アプリのベスト プラクティスに関するセクションをご覧ください。
進行状況バーを追加する
通知には、進行中のオペレーションのステータスをユーザーに示すアニメーションの進行状況インジケーターを含めることができます。
オペレーションの完了量をいつでも見積もることができる場合は、setProgress(max, progress,
false)
を呼び出して、「確定」形式のインジケーターを使用します(図 5 を参照)。最初のパラメータは「完全な」値(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());
オペレーションの終了時には、progress
が max
と等しくなる必要があります。進行状況バーを残して、オペレーションの完了を示すことも、削除することもできます。いずれの場合も、通知テキストを更新して、オペレーションが完了したことを示します。進行状況バーを削除するには、setProgress(0, 0, false)
を呼び出します。
不確定の進行状況バー(完了率を示さないバー)を表示するには、setProgress(0, 0, true)
を呼び出します。結果は、完了を示さない連続アニメーションであることを除き、前の進行状況バーと同じスタイルのインジケーターになります。進行状況アニメーションは、setProgress(0, 0, false)
を呼び出してから通知を更新してアクティビティ インジケーターを削除するまで実行されます。
オペレーションが完了したことを示すために、通知テキストを必ず変更してください。
システムレベルのカテゴリを設定する
Android は、事前定義されたシステム全体のカテゴリを使用して、ユーザーがサイレント モードを有効にしたときに特定の通知でユーザーの操作に割り込むかどうかを決定します。
通知が、NotificationCompat
で定義された通知カテゴリ(CATEGORY_ALARM
、CATEGORY_REMINDER
、CATEGORY_EVENT
、CATEGORY_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)以降では、メッセージング コンテンツ専用の通知スタイル テンプレートが用意されています。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
通知によって提供されるコンテキストを使用して、完全にスマートウォッチ上で動作する機械学習モデルによって生成されます。レスポンスを生成するためにデータがインターネットにアップロードされることはありません。
通知メタデータを追加する
- 通知メタデータを割り当てて、デバイスが
Do Not Disturb mode
のときのアプリ通知の処理方法をシステムに指示します。たとえば、addPerson()
メソッドまたはsetCategory(Notification.CATEGORY_MESSAGE)
メソッドを使用して、サイレント モードをオーバーライドします。