通知からアクティビティを起動する

通知からアクティビティを起動する場合、ユーザーが想定しているナビゲーション機能を維持する必要があります。[戻る] がタップされたら、アプリの通常のフローを通してホーム画面までユーザーを戻す必要があり、[最近] 画面が開かれたら、そのアクティビティを個別のタスクとして表示する必要があります。このようなナビゲーション機能を維持するには、アクティビティを新しいタスクとして起動する必要があります。

通知のタップ動作を設定する基本的な方法については、通知を作成するをご覧ください。このページでは、通知のアクション用の 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 を作成できますが、マニフェスト内で適切なタスク オプションを定義しておく必要があります。

  1. マニフェスト内で、<activity> 要素に以下の属性を追加します。
    android:taskAffinity=""
    コード内で使用する FLAG_ACTIVITY_NEW_TASK フラグと組み合わせて、この属性を空に設定することで、このアクティビティがアプリのデフォルト タスクに含まれないようにします。アプリのデフォルト アフィニティを持つ既存のタスクには影響がありません。
    android:excludeFromRecents="true"
    [履歴] からその新しいタスクを除外して、ユーザーがそこに偶発的に戻らないようにします。

    たとえば、次のようになります。

        <activity
            android:name=".ResultActivity"
            android:launchMode="singleTask"
            android:taskAffinity=""
            android:excludeFromRecents="true">
        </activity>
        
  2. 通知を作成して発行します。
    1. Activity を起動する Intent を作成します。
    2. FLAG_ACTIVITY_NEW_TASK フラグと FLAG_ACTIVITY_CLEAR_TASK フラグを指定して setFlags() を呼び出すことで、新しい空のタスクで起動するように Activity を設定します。
    3. 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
        );
        
  3. 後は、通常どおり 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 通知サンプルをご覧ください。