Skip to content

Android 12以降でのPendingIntentのFLAG_IMMUTABLE要件

問題

Android 12(APIレベル31)以降をターゲットとするアプリケーションで、MediaSessionCompatを使用している場合、次のようなランタイム例外が発生することがあります:

java
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を渡すことです:

kotlin
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に依存していることが原因です。以下の依存関係を追加または更新してください:

gradle
// Kotlinの場合
implementation 'androidx.work:work-runtime-ktx:2.7.1'

// Javaの場合
implementation 'androidx.work:work-runtime:2.7.1'

また、メディアライブラリを最新版に更新することも効果的です:

gradle
implementation 'androidx.media:media:1.4.1'

INFO

バージョン1.4.1では、Android Sをターゲットとする場合のPendingIntentのmutabilityフラグの問題が修正されています。

3. 他のライブラリのチェックと更新

以下のような一般的なライブラリもこの問題を引き起こす可能性があります。最新バージョンに更新してください:

gradle
// 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のバージョンに応じて適切なフラグを設定してください:

kotlin
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が作成されますが、古いバージョンのライブラリではこの新しい要件に対応していませんでした。

デバッグのヒント

  1. 依存関係の分析:ターミナルで./gradlew app:dependenciesを実行し、古いバージョンのwork-runtimeライブラリに依存しているライブラリを特定します。

  2. マニフェストの設定:Android 12では、ブロードキャストレシーバーやサービスにandroid:exported属性の明示的な設定が必要です:

xml
<service
    android:name=".MediaService"
    android:exported="true" />
    
<receiver
    android:name=".MyBroadcastReceiver"
    android:exported="true" />

まとめ

Android 12以降では、PendingIntentの作成時にmutabilityフラグの明示的な指定が必須となりました。この問題に対処するには:

  1. 直接PendingIntentを作成する場合は、適切なフラグ(通常はFLAG_IMMUTABLE)を指定する
  2. 関連するAndroidXライブラリを最新バージョンに更新する
  3. サードパーティライブラリの互換性を確認し、必要に応じて更新する

これらの対策により、Android 12以降のデバイスでもアプリが正常に動作するようになります。