通知からアクティビティを起動する場合、ユーザーが想定しているナビゲーション機能を維持する必要があります。[戻る] がタップされたら、アプリの通常のフローを通してホーム画面までユーザーを戻す必要があり、[最近] 画面が開かれたら、そのアクティビティを個別のタスクとして表示する必要があります。このようなナビゲーション機能を維持するには、アクティビティを新しいタスクとして起動する必要があります。
通知のタップ動作を設定する基本的な方法については、通知を作成するをご覧ください。このページでは、通知のアクション用の PendingIntent
をセットアップして、新しいタスクとバックスタックを作成する方法について説明します。ただし、起動するアクティビティのタイプによって、手順が異なります。
- 標準アクティビティ
- これは、アプリの通常のユーザー エクスペリエンス フローの一部として存在するアクティビティです。そのため、ユーザーが通知からこのアクティビティに到達した場合、新しいタスクに完全なバックスタックが含まれている必要があります。これにより、ユーザーは [戻る] を押したときに、アプリ階層を上に移動できます。
- 特殊なアクティビティ
- これは、通知から起動された場合に限りユーザーに表示されるアクティビティです。このアクティビティは、通知そのものには表示しにくい情報を提供することにより、ある意味、通知 UI を拡張するものです。そのため、このアクティビティにはバックスタックは必要ありません。
標準アクティビティの PendingIntent をセットアップする
通知から「標準アクティビティ」を起動するには、下記のように、TaskStackBuilder
を使用して PendingIntent
をセットアップし、新しいバックスタックが作成されるようにします。
アプリのアクティビティ階層を定義する
アクティビティの自然な階層を定義するには、アプリのマニフェスト ファイル内の各 <activity>
要素に android:parentActivityName
属性を追加します。たとえば、次のようになります。
<activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- MainActivity is the parent for ResultActivity --> <activity android:name=".ResultActivity" android:parentActivityName=".MainActivity" /> ... </activity>
バックスタックを備えた PendingIntent を作成する
アクティビティのバックスタックを含むアクティビティを起動するには、TaskStackBuilder
のインスタンスを作成し、addNextIntentWithParentStack()
を呼び出して、起動するアクティビティの Intent
を渡します。
上記のように、アクティビティごとに親アクティビティを定義している限り、getPendingIntent()
を呼び出すことで、バックスタック全体を含む PendingIntent
を受け取ることができます。
Kotlin
// Create an Intent for the activity you want to start val resultIntent = Intent(this, ResultActivity::class.java) // Create the TaskStackBuilder val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(this).run { // Add the intent, which inflates the back stack addNextIntentWithParentStack(resultIntent) // Get the PendingIntent containing the entire back stack getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT) }
Java
// Create an Intent for the activity you want to start Intent resultIntent = new Intent(this, ResultActivity.class); // Create the TaskStackBuilder and add the intent, which inflates the back stack TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); stackBuilder.addNextIntentWithParentStack(resultIntent); // Get the PendingIntent containing the entire back stack PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
必要に応じて、TaskStackBuilder.editIntentAt()
を呼び出すことで、スタック内の Intent
オブジェクトに引数を追加できます。これは、ユーザーが階層を上に移動してくる際に、バックスタック内のアクティビティが意味のあるデータを表示できるようにするために必要になることがあります。
後は、通常どおり PendingIntent
を通知に渡すことができます。
Kotlin
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply { setContentIntent(resultPendingIntent) ... } with(NotificationManagerCompat.from(this)) { notify(NOTIFICATION_ID, builder.build()) }
Java
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID); builder.setContentIntent(resultPendingIntent); ... NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(NOTIFICATION_ID, builder.build());
特殊アクティビティの PendingIntent をセットアップする
通知から起動される「特殊アクティビティ」にはバックスタックは必要ありません。そのため、getActivity()
を呼び出すことで PendingIntent
を作成できますが、マニフェスト内で適切なタスク オプションを定義しておく必要があります。
- マニフェスト内で、
<activity>
要素に以下の属性を追加します。-
android:taskAffinity=""
- コード内で使用する
FLAG_ACTIVITY_NEW_TASK
フラグと組み合わせて、この属性を空に設定することで、このアクティビティがアプリのデフォルト タスクに含まれないようにします。アプリのデフォルト アフィニティを持つ既存のタスクには影響がありません。 -
android:excludeFromRecents="true"
- [履歴] からその新しいタスクを除外して、ユーザーがそこに偶発的に戻らないようにします。
たとえば、次のようになります。
<activity android:name=".ResultActivity" android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true"> </activity>
-
- 通知を作成して発行します。
Activity
を起動するIntent
を作成します。FLAG_ACTIVITY_NEW_TASK
フラグとFLAG_ACTIVITY_CLEAR_TASK
フラグを指定してsetFlags()
を呼び出すことで、新しい空のタスクで起動するようにActivity
を設定します。getActivity()
を呼び出してPendingIntent
を作成します。
たとえば、次のようになります。
Kotlin
val notifyIntent = Intent(this, ResultActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } val notifyPendingIntent = PendingIntent.getActivity( this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT )
Java
Intent notifyIntent = new Intent(this, ResultActivity.class); // Set the Activity to start in a new, empty task notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // Create the PendingIntent PendingIntent notifyPendingIntent = PendingIntent.getActivity( this, 0, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT );
- 後は、通常どおり
PendingIntent
を通知に渡すことができます。Kotlin
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply { setContentIntent(notifyPendingIntent) ... } with(NotificationManagerCompat.from(this)) { notify(NOTIFICATION_ID, builder.build()) }
Java
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID); builder.setContentIntent(notifyPendingIntent); ... NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(NOTIFICATION_ID, builder.build());
さまざまなタスク オプションと、バックスタックの仕組みについては、タスクとバックスタックをご覧ください。通知を使用するサンプルコードについては、Android 通知サンプルをご覧ください。