Android PendingIntentとは?FLAG_IMMUTABLE・MUTABLEの違いとエラー対処
初回掲載日:
最終更新日:
PendingIntentは、アプリが作った処理をAndroidシステムや別のアプリへ後から実行してもらうための「委任トークン」です。通知タップやアラームで使われますが、通常のIntentそのものではありません。
Android 12(API 31)以降をtargetにするアプリでは、作成時にFLAG_IMMUTABLEまたはFLAG_MUTABLEを明示します。迷った場合は、受け取り側によるIntentの変更が本当に必要かを確認し、原則としてFLAG_IMMUTABLEを選びます。
- 通常の通知タップ、明示的なActivity起動、固定内容のアラームはまず
FLAG_IMMUTABLEを検討する - インライン返信やBubbleなど、受け取り時の入力をPendingIntentへ反映する用途では
FLAG_MUTABLEが必要になる場合がある - Android 14(API 34)以上をtargetにしたアプリで、mutableなPendingIntentに暗黙的Intentを渡すと例外になる
FLAG_UPDATE_CURRENTはFLAG_IMMUTABLEと併用でき、作成元アプリ自身によるextras更新まで禁止するものではない
PendingIntentとは?通常のIntentとの違い
Intentは、Activity・Service・BroadcastReceiverなどへ「この処理を実行してほしい」と伝えるメッセージです。一方のPendingIntentは、作成元アプリが処理の実行権をAndroidシステムなどへ安全に委任するためのトークンです。
例えば通知を表示した時点ではアプリ画面を開かず、ユーザーが通知をタップした時にActivityを起動します。この「後で実行する処理」を、通知システムへ渡すときにPendingIntentを使います。主なファクトリメソッドは次の3つです。
| メソッド | 用途 | 例 |
|---|---|---|
getActivity() | Activityを起動 | 通知タップで詳細画面を開く |
getBroadcast() | BroadcastReceiverへ通知 | アラームや操作ボタンのイベント |
getService() | Serviceを起動 | バックグラウンド処理の開始依頼 |
IMMUTABLEとMUTABLEの違い
| フラグ | 意味 | 向いているケース | 注意点 |
|---|---|---|---|
FLAG_IMMUTABLE | 送信側がfill-in Intentで処理の意味を変更できない | 通知タップ、固定された明示的Activity、固定内容のアラーム | 受け取り時の入力を反映したい用途には合わない場合がある |
FLAG_MUTABLE | 受け取り時に一部のIntent情報を変更できる | インライン返信、Bubbleなど可変性が必要な用途 | 必要な場合だけ使用。暗黙的Intentとの組み合わせはAndroid 14以降で制限 |
Android公式APIリファレンスは、可変性を必要としないPendingIntentではFLAG_IMMUTABLEを強く推奨しています。FLAG_MUTABLEは「通知だから必要」「アラームだから必要」と用途名だけで決めず、誰がどの値を後から埋める必要があるかで判断します。

Android 12でフラグ指定が必要になった理由
Android 12(API 31、コードネームS)以降では、PendingIntentの可変性を作成時に明示する必要があります。指定がない既存コードは、targetSdkVersionを上げたタイミングでIllegalArgumentExceptionの原因になることがあります。
// 例:Android 12以降をtargetにした通知タップ
Intent intent = new Intent(context, DetailActivity.class);
intent.setPackage(context.getPackageName());
PendingIntent contentIntent = PendingIntent.getActivity(
context,
100,
intent,
PendingIntent.FLAG_IMMUTABLE
| PendingIntent.FLAG_UPDATE_CURRENT
);
この例では、Activityとpackageを指定した明示的Intentを使い、作成元アプリ以外が処理の宛先を変更できないようにしています。Android 12未満も動作対象にする場合でも、対応するcompileSdkやサポート方針を確認したうえで同じコードを基本形にできます。
FLAG_UPDATE_CURRENTはIMMUTABLEと併用できる
FLAG_IMMUTABLEは、PendingIntentを受け取った側がsend時にIntentの意味を変更することを制限します。作成元アプリ自身がFLAG_UPDATE_CURRENTでextrasを更新することまで禁止するものではありません。
Intent intent = new Intent(context, DetailActivity.class);
intent.setPackage(context.getPackageName());
intent.putExtra("item_id", itemId);
int flags = PendingIntent.FLAG_IMMUTABLE
| PendingIntent.FLAG_UPDATE_CURRENT;
PendingIntent pendingIntent = PendingIntent.getActivity(
context, 100, intent, flags);
同じPendingIntentを更新する場合、処理の種類、requestCode、Intentのaction・data・componentなどが同じかを意識します。extrasだけを変えても「別のPendingIntent」として新規作成されるとは限らないため、requestCodeやdataを設計上の識別子として使います。
FLAG_CANCEL_CURRENT・NO_CREATE・ONE_SHOT
| フラグ | 動作 | 使いどころ |
|---|---|---|
FLAG_UPDATE_CURRENT | 既存のPendingIntentを維持し、extrasを更新 | 同じ通知や画面への最新データを反映 |
FLAG_CANCEL_CURRENT | 既存のPendingIntentをキャンセルして新規作成 | 古いPendingIntentを確実に無効化したい場合 |
FLAG_NO_CREATE | 存在しなければ作らずnullを返す | 既存の登録状態を確認 |
FLAG_ONE_SHOT | 一度だけ利用可能にする | 一回限りの処理を委任 |
可変性フラグは、これらの動作フラグとは役割が異なります。例えばFLAG_IMMUTABLE | FLAG_UPDATE_CURRENTのように、可変性と更新方式を組み合わせることがあります。
通知・直接返信・アラームでの使い分け
| 用途 | 基本方針 | 確認すること |
|---|---|---|
| 通知タップ | 明示的Intent+FLAG_IMMUTABLEを第一候補 | 開くActivity、package、通知ごとのrequestCode |
| 通知アクション | BroadcastやServiceに固定の明示的Intentを渡す | 受け取り側のexport設定とintent内容 |
| インライン返信 | 受け取り時のRemoteInputなどが必要ならFLAG_MUTABLEを検討 | 本当に可変性が必要か、他の入力経路で代替できないか |
| AlarmManager | アラームだからMUTABLEとは限らない | 指定したBroadcastやServiceが固定されているか |
AndroidのアラームやWorkManagerの設計を検討している場合は、用途が異なるためWorkManagerの記事も参照してください。PendingIntentは実行の委任、WorkManagerは永続的なバックグラウンド作業のスケジューリングが中心です。
Android 14のmutable+暗黙的Intent制限
Android 14(API 34)以上をtargetにしたアプリでは、コンポーネントやpackageを指定しない暗黙的Intentを、mutableなPendingIntentに入れて作成すると例外になります。これは、内部コンポーネント向けのIntentが別のコンポーネントに解釈されるリスクを抑えるための制限です。
修正の基本は、Intentを明示的にすることです。自アプリのActivityなら、クラス指定やsetPackage()で宛先を固定します。FLAG_ALLOW_UNSAFE_IMPLICIT_INTENTは名前の通り安全性を緩める選択肢なので、例外を消すための一般的な回避策として推奨しません。
// Android 14以降をtargetにする場合の明示的Intent
Intent intent = new Intent(context, DetailActivity.class);
intent.setPackage(context.getPackageName());
PendingIntent pendingIntent = PendingIntent.getActivity(
context,
101,
intent,
PendingIntent.FLAG_IMMUTABLE
);
PendingIntentの可変性とBackground Activity Launchは別問題
PendingIntentを作成できても、バックグラウンドからActivityを起動できるとは限りません。AndroidのBackground Activity Launch(BAL)は、ユーザーを突然遮る画面表示を防ぐための別のセキュリティ制御です。
通知タップなどシステム起点の起動と、バックグラウンドアプリが任意のタイミングでActivityを開く処理は分けて考えます。Android 14以降はPendingIntentを送信する側のopt-inが関係し、Android 15以降は作成側の権限委譲も関係する公式説明があります。可変性フラグを変更するだけでBAL制限を解決できる、とは考えないでください。
この点は、Foreground Serviceの起動制限とも別の話です。長時間のユーザー可視処理についてはForeground Serviceの記事で役割を分けて確認してください。
よくあるエラーと確認順

| 症状 | 原因候補 | 確認・対処 |
|---|---|---|
| PendingIntent作成時にIllegalArgumentException | Android 12以降をtargetにして可変性フラグ未指定 | IMMUTABLEかMUTABLEを用途に合わせて明示 |
| Android 14でmutable作成時に例外 | mutableなPendingIntent内のIntentが暗黙的 | componentまたはpackageを設定した明示的Intentへ変更 |
| 通知タップで古いデータが開く | 同一PendingIntentが再利用されextrasが更新されていない | UPDATE_CURRENT、requestCode、data、通知IDの設計を確認 |
| アラームが新しい設定にならない | 既存PendingIntentの識別条件が同じ、または古い登録が残っている | UPDATE_CURRENTかCANCEL_CURRENTを意図に合わせて選択し、AlarmManager側も確認 |
| Activityが開かない | BAL、Activityのexport、Intentの宛先、通知状態 | 可変性とは別にLogcatとシステム制限を確認 |
実装前後のチェックリスト
- PendingIntentで委任する処理をActivity・Broadcast・Serviceのどれか決めた
- targetSdkVersionと端末のAndroidバージョンを確認した
FLAG_IMMUTABLEまたはFLAG_MUTABLEを明示した- MUTABLEにする理由をコードコメントや設計メモに残した
- 固定の処理には明示的Intentとpackageまたはcomponentを使った
FLAG_UPDATE_CURRENT、FLAG_CANCEL_CURRENT、requestCodeの役割を混同していない- 通知タップ、アクション、直接返信を別々に確認した
- Android 14以降のmutable+暗黙的Intent制限を確認した
- PendingIntentの問題とBackground Activity Launchの問題を切り分けた
- 実機テストでは古い通知やアラームをキャンセルしてから再確認した
FAQ
Q. FLAG_IMMUTABLEとFLAG_MUTABLEはどちらを使えばいいですか?
受け取り側がIntentの値を変更する必要がなければ、まずFLAG_IMMUTABLEです。直接返信やBubbleなど、可変性を必要とする用途だけFLAG_MUTABLEを検討します。
Q. 通知なら常にIMMUTABLEですか?
通常の通知タップや固定アクションはIMMUTABLEが基本ですが、通知の機能によって必要な入力が変わります。直接返信などでは公式仕様と使用APIを確認してください。
Q. FLAG_UPDATE_CURRENTとIMMUTABLEは併用できますか?
併用できます。IMMUTABLEは送信側の変更を制限し、UPDATE_CURRENTは作成元アプリが既存PendingIntentのextrasを更新する動作です。
Q. Android 14の例外を消すためMUTABLEを外せばよいですか?
まずIntentを明示的にしてください。可変性を不要にできるならIMMUTABLEへ変更できますが、機能上MUTABLEが必要な処理を単純に変更すると別の不具合になります。
Q. PendingIntentとBackground Activity Launchは同じ制限ですか?
別です。PendingIntentの可変性は委任されたIntentを変更できるか、BALはバックグラウンドからActivityを開始できるかの制御です。
まとめ
PendingIntentは、通知・アラーム・コンポーネント間連携のために、後から処理を実行できる権限を安全に委任する仕組みです。Android 12以降をtargetにするなら可変性を明示し、必要性がなければFLAG_IMMUTABLEを選びます。
Android 14以降のmutable+暗黙的Intent制限には、明示的Intentで対応するのが基本です。FLAG_UPDATE_CURRENTの動作、requestCode、Intentの識別条件、BAL制限まで分けて確認すれば、「とりあえずMUTABLEにする」修正を避けられます。