通知を作成する

通知は、アプリが使用されていないときに、アプリ内のイベントに関する簡潔な情報をタイムリーに提供します。このページでは、Android 4.0(API レベル 14)以上のさまざまな機能を使用して通知を作成する方法を説明します。Android で通知を表示する方法の概要については、通知の概要をご覧ください。通知を使用するサンプルコードについては、Android 通知のサンプルをご覧ください。

このページに掲載しているコードでは、Android サポート ライブラリの NotificationCompat API を使用していることに留意してください。これらの API を使用すると、Android 4.0(API レベル 14)との後方互換性を維持しつつ、新しいバージョンの Android でのみ使用可能な機能を追加できます。ただし、インライン返信アクションなどの一部の新機能は、古いバージョンでは何も実施しません。

サポート ライブラリを追加する

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

dependencies {
        implementation "com.android.support:support-compat:28.0.0"
    }
    

基本的な通知を作成する

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

図 1. タイトルとテキストを含む通知

通知を構成する各要素の詳細については、通知の構造をご覧ください。

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

最初に、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 new and 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 new and 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, 0)

    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 will fire 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, 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)
            // Set the intent that will fire when the user taps the notification
            .setContentIntent(pendingIntent)
            .setAutoCancel(true);
    

このコードは setAutoCancel() を呼び出すことに留意してください。これにより、ユーザーがタップすると、自動的に通知が消去されます。

上記の setFlags() メソッドは、ユーザーが通知を介してアプリを開いた後、ユーザーの予想されるナビゲーション エクスペリエンスを維持するのに役立ちます。ただし、これを使用するかどうかは、開始するアクティビティのタイプ(次のいずれか)によって異なります。

  • 通知への応答のためだけに存在するアクティビティ。アプリの通常の使用中にユーザーがこのアクティビティに移動する理由はないため、アクティビティはアプリの既存のタスクとバックスタックに追加される代わりに、新しいタスクを開始します。これは、上記のサンプルで作成されるインテントのタイプです。
  • アプリの通常のアプリフロー内に存在するアクティビティ。この場合、アクティビティを開始するとバックスタックが作成され、ユーザーが期待する 「戻る」ボタンと「上へ」ボタンが維持されます。

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

通知を表示する

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

Kotlin

    with(NotificationManagerCompat.from(this)) {
        // notificationId is a unique int for each notification that you must define
        notify(notificationId, builder.build())
    }
    

Java

    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

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

NotificationManagerCompat.notify() に渡す通知 ID は、後で通知を更新または通知を削除する場合に必要になるため、必ず保存しておいてください。

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

通知には、ユーザーがすばやく応答するためのアクション ボタン(リマインダーのスヌーズやテキスト メッセージへの返信など)を最大で 3 つ設定できます。ただし、これらのアクション ボタンは、ユーザーが通知をタップしたときに実行されるアクションと同じであってはなりません。

図 2. アクション ボタンが 1 つある通知

アクション ボタンを追加するには、addAction() メソッドに PendingIntent を渡します。これは、通知のデフォルトのタップ アクションを設定する場合と同様です。ただし、アクティビティを起動する代わりに、バックグラウンドでジョブを実行する BroadcastReceiver を開始するなどのさまざまな処理を実行でき、アクションはすでに開いているアプリを中断しません。

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

Kotlin

    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

    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)で導入されたダイレクト返信アクションでは、ユーザーは通知にテキストを直接入力できます。返信テキストは、アクティビティを開かずにアプリに配信されます。たとえば、ダイレクト返信アクションにより、ユーザーがテキスト メッセージに返信したり、通知内からタスクリストを更新したりすることが可能になります。

図 3. 返信ボタンをタップするとテキスト入力が開く

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

返信ボタンを追加する

ダイレクト返信をサポートする通知アクションを作成するには:

  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);
        

    注意: PendingIntent を再利用すると、ユーザーが自分が思っていた会話と異なる会話に返信してしまうことがあります。会話ごとに異なるリクエスト コードを提供するか、他の会話の返信インテントで equals() を呼び出したときに true を返さないインテントを提供する必要があります。会話 ID はインテントのエクストラ バンドルの一部として頻繁に渡されますが、equals() を呼び出すと無視されます。

  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);
        

図 3 に示すように、通知アクションをトリガーすると、システムは応答の入力をユーザーに促します。

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

通知の返信 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() を呼び出して、通知の下部に返信を付加する必要があります。ただし、メッセージング アプリを作成する場合は、メッセージング スタイルの通知を作成して、新しいメッセージを会話の最後に付加してください。

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

進行状況バーを追加する

進行中のオペレーションのステータスをユーザーに知らせるアニメーション形式の進捗インジケーターを通知に表示できます。

図 4. オペレーション中およびオペレーション後の進行状況バー

完了したオペレーションの量をいつでも見積もることができる場合は、setProgress(max, progress, false) を呼び出して、「確定」形式のインジケーターを使用します(図 4 を参照)。最初のパラメータは「完了」を表す値(たとえば 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 here that tracks the progress.
        // Usually, this should be 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 one more time 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 here that tracks the progress.
    // Usually, this should be 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 one more time 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

    var notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setStyle(NotificationCompat.MessagingStyle("Me")
                    .setConversationTitle("Team lunch")
                    .addMessage("Hi", timestamp1, null) // Pass in null for user.
                    .addMessage("What's up?", timestamp2, "Coworker")
                    .addMessage("Not much", timestamp3, null)
                    .addMessage("How about lunch?", timestamp4, "Coworker"))
            .build()
    

Java

    Notification notification = new Notification.Builder(this, CHANNEL_ID)
            .setStyle(new NotificationCompat.MessagingStyle("Me")
                    .setConversationTitle("Team lunch")
                    .addMessage("Hi", timestamp1, null) // Pass in null for user.
                    .addMessage("What's up?", timestamp2, "Coworker")
                    .addMessage("Not much", timestamp3, null)
                    .addMessage("How about lunch?", timestamp4, "Coworker"))
            .build();
    

Android 8.0(API レベル 26)以上では、NotificationCompat.MessagingStyle クラスを使用する通知は、折りたたみフォームに、より多くのコンテンツを表示します。また、addHistoricMessage() メソッドにより、メッセージング関連の通知に履歴メッセージを追加して、会話にコンテキストを提供することもできます。

NotificationCompat.MessagingStyle を使用すると、次のことができます。

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

ダイレクト返信を使用する

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

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

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

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

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