通知からアクティビティを開始する場合、ユーザーの期待するナビゲーション エクスペリエンスを維持する必要があります。[戻る] ボタンをタップするとアプリの通常のワークフローからホーム画面に戻る必要があり、履歴画面を開くとアクティビティは個別のタスクとして表示される必要があります。このナビゲーション エクスペリエンスを維持するには、新しいタスクでアクティビティを開始します。
通知のタップ動作を設定する基本的な方法については、基本的な通知を作成するをご覧ください。
このページでは、新しいタスクとバックスタックを作成するために、通知のアクションに 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 or PendingIntent.FLAG_IMMUTABLE) }
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 | PendingIntent.FLAG_IMMUTABLE);
必要に応じて、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 or PendingIntent.FLAG_IMMUTABLE )
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.FLAG_IMMUTABLE );
-
- 通常どおり
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());
さまざまなタスク オプションとバックスタックの仕組みの詳細については、タスクとバックスタックをご覧ください。