[안드로이드] Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. 오류 해결 방법
targetSdkVersion 31로 상향 조정하면서 여기저기서 오류가 튀어 나온다. 오류 내용은 다음과 같다.
2022-10-02 12:29:09.109 6268-6309/com.test E/AndroidRuntime: FATAL EXCEPTION: pool-9-thread-1
Process: com.test, PID: 6268
java.lang.IllegalArgumentException: com.test: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
at android.app.PendingIntent.checkFlags(PendingIntent.java:382)
at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:673)
at android.app.PendingIntent.getBroadcast(PendingIntent.java:660)
at androidx.work.impl.utils.ForceStopRunnable.c(:174)
at androidx.work.impl.utils.ForceStopRunnable.d(:108)
at androidx.work.impl.utils.ForceStopRunnable.run(:86)
at androidx.work.impl.utils.f$a.run(:75)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
at java.lang.Thread.run(Thread.java:1012)
S+(버전 31 이상)를 타겟팅하는 경우 PendingIntent를 생성할 때 FLAG_IMMUTABLE 또는 FLAG_MUTABLE 중 하나를 지정해야 한다는 오류 보고이다. Google 문서에서는 FLAG_IMMUTABLE 사용을 강력히 고려하고 일부 기능이 변경 가능한 PendingIntent에 의존하는 경우에만 FLAG_MUTABLE을 사용하라고 말한다.
FLAG_IMMUTABLE 개발자 가이드 문서 보기
- PendingIntent.FLAG_MUTABLE 변경 가능
- PendingIntent.FLAG_IMMUTABLE 는 변경 불가능
Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. 오류 해결 방법
앱 수준의 build.gradle 파일에 다음 라이브러리를 추가해준 후 Run app 하면 오류는 해결된다.
앱에서 AdMob 20.4.0 이하를 사용하는 경우 다음 작업 관리자 종속성을 추가해야 한다.
implementation 'androidx.work:work-runtime:2.7.1'
그러나 소스코드상에서
PendingIntent를 사용중인 코드가 있다면 반드시 플래그값 지정이 필요하다.
앱 실행결과 아래 코드에서 동일한 오류가 발생되었다. 기존에는 PendingIntent.FLAG_UPDATE_CURRENT 플래그 옵션을 사용하여 처리중이였지만 버전상향을 하면서 오류로 인식하는 것이다.
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(
context
, REQUEST_CODE_ALARM_MANAGER, intent
, PendingIntent.FLAG_UPDATE_CURRENT);
안드로이드 OS가 Android12 이고 targetSdk버전이 31인 이상인 경우 PendingIntent생성시 FLAG_IMMUTABLE 나 FLAG_MUTABLE 을 지정해줘야 오류 발생을 피할 수 있다.
앱이 Android 12에서 실행되도록 하면 PendingIntent에 대한 변경 가능성 플래그(FLAG_MUTABLE)가 추가되었다.
FLAG_IMMUTABLE값은 기존에 있던 플래그값이다
플래그 | 설명 |
FLAG_UPDATE_CURRENT | PendingIntent가 이미 존재하는 경우, Extra Data를 모두 변경 |
FLAG_CANCEL_CURRENT | PendingIntent가 이미 존재하는 경우, 기존 PendingIntent를 cancel하고 다시 생성 |
FLAG_IMMUTABLE | 기존 PendingIntent는 변경되지 않으며, 새로운 데이터를 추가한 PendingIntent를 보내도 무시함 |
FLAG_NO_CREATE | PendingIntent가 존재하지 않는 경우 NULL을 리턴 |
FLAG_ONE_SHOT | 한 번만 사용가능한 일회성 PendingIntent |
아래와 같은 형식으로 처리할 수 도 있으며
PendingIntent pendingIntent
= PendingIntent.getActivity(this, id, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
또는
PendingIntent pIntent = PendingIntent.getBroadcast(
context
, REQUEST_CODE_ALARM_MANAGER, intent
, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
또는
PendingIntent pIntent = PendingIntent.getBroadcast(
context
, REQUEST_CODE_ALARM_MANAGER, intent
, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
PendingIntent가 변경되는 것을 원하지 않으면 다음과 같이 코드를 분기처리한다. (기존방식과 동일하게 처리)
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}else {
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
만약 PendingIntent를 변경하려면 다음 코드를 사용하면 된다. (새롭게 추가된 기능이다.)
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
}else {
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
나의 해결방법은 다음과 같다
//android 12
PendingIntent sPpendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
sPpendingIntent = PendingIntent.getActivity(context,
NOTIFICATION_ID, sIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}else {
sPpendingIntent = PendingIntent.getActivity(context, NOTIFICATION_ID, sIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
[관련 정보]
[reference]
- https://stackoverflow.com/questions/67045607/how-to-resolve-missing-pendingintent-mutability-flag-lint-warning-in-android-a
- https://stackoverflow.com/questions/69783824/targeting-s-version-31-and-above-requires-that-one-of-flag-immutable-or-flag