Android 12以降でのPendingIntentのFLAG_IMMUTABLE要件
問題
Android 12(APIレベル31)以降をターゲットとするアプリケーションで、MediaSessionCompat
を使用している場合、次のようなランタイム例外が発生することがあります:
java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
この問題は、Android 12で導入された新しいセキュリティ要件によるものです。Android 12以降では、PendingIntent
を作成する際に、明示的にFLAG_IMMUTABLE
またはFLAG_MUTABLE
のいずれかを指定する必要があります。
解決策
1. MediaSessionCompatの明示的な初期化
最も直接的な解決方法は、MediaSessionCompat
を初期化する際に、明示的にPendingIntent
を渡すことです:
override fun onCreate() {
super.onCreate()
val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
val pendingIntent = PendingIntent.getBroadcast(
applicationContext,
0,
mediaButtonIntent,
PendingIntent.FLAG_IMMUTABLE
)
mediaSession = MediaSessionCompat(this, TAG, null, pendingIntent).apply {
setCallback(mediaSessionCallback)
isActive = true
}
sessionToken = mediaSession.sessionToken
}
2. 依存ライブラリの更新
多くの場合、この問題はサードパーティライブラリが古いバージョンのAndroid WorkManagerに依存していることが原因です。以下の依存関係を追加または更新してください:
// Kotlinの場合
implementation 'androidx.work:work-runtime-ktx:2.7.1'
// Javaの場合
implementation 'androidx.work:work-runtime:2.7.1'
また、メディアライブラリを最新版に更新することも効果的です:
implementation 'androidx.media:media:1.4.1'
INFO
バージョン1.4.1では、Android Sをターゲットとする場合のPendingIntentのmutabilityフラグの問題が修正されています。
3. 他のライブラリのチェックと更新
以下のような一般的なライブラリもこの問題を引き起こす可能性があります。最新バージョンに更新してください:
// Firebase Cloud Messaging
implementation 'com.google.firebase:firebase-messaging:23.0.0'
// Google Play Services Ads
implementation 'com.google.android.gms:play-services-ads:22.2.0'
// Chuckライブラリ(ネットワーク監視)
debugImplementation "com.github.chuckerteam.chucker:library:3.5.2"
releaseImplementation "com.github.chuckerteam.chucker:library-no-op:3.5.2"
4. 一般的なPendingIntentの扱い方
アプリ内で直接PendingIntent
を作成する場合は、Androidのバージョンに応じて適切なフラグを設定してください:
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
} else {
PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
WARNING
FLAG_MUTABLE
は、インライン返信やバブルなどの機能でPendingIntentの変更が必要な場合にのみ使用してください。それ以外の場合は、セキュリティ上FLAG_IMMUTABLE
を使用することが推奨されます。
根本原因
この問題は、Android 12で導入された新しいセキュリティ対策によるものです。不変(immutable)なPendingIntentのみを許可することにより、悪意のあるアプリがアプリのPendingIntentを改ざんすることを防ぎます。
MediaSessionCompat
内部では、メディアボタンイベントを処理するためにPendingIntentが作成されますが、古いバージョンのライブラリではこの新しい要件に対応していませんでした。
デバッグのヒント
依存関係の分析:ターミナルで
./gradlew app:dependencies
を実行し、古いバージョンのwork-runtimeライブラリに依存しているライブラリを特定します。マニフェストの設定:Android 12では、ブロードキャストレシーバーやサービスに
android:exported
属性の明示的な設定が必要です:
<service
android:name=".MediaService"
android:exported="true" />
<receiver
android:name=".MyBroadcastReceiver"
android:exported="true" />
まとめ
Android 12以降では、PendingIntentの作成時にmutabilityフラグの明示的な指定が必須となりました。この問題に対処するには:
- 直接PendingIntentを作成する場合は、適切なフラグ(通常は
FLAG_IMMUTABLE
)を指定する - 関連するAndroidXライブラリを最新バージョンに更新する
- サードパーティライブラリの互換性を確認し、必要に応じて更新する
これらの対策により、Android 12以降のデバイスでもアプリが正常に動作するようになります。