Android

[안드로이드] 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  |  Android Developers

android.net.wifi.hotspot2.omadm

developer.android.com

  • 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);
}

[관련 정보]

동작 변경사항: Android 12를 타겟팅하는 앱  |  Android Developers

Android 12를 타겟팅하는 앱에 영향을 주는 Android 12의 변경사항을 알아봅니다.

developer.android.com

안드로이드 SDK31 에서 PendingIntent 관련 이슈

안드로이드 SDK 31 버전에서 앱이 실행될 때 최초 KakaoSDK.init()을 실행하는중 PendingIntent 관련 에러가 납니다. 하기는 에러 로그 입니다. Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_

devtalk.kakao.com

[reference]

Leave a Reply

error: Content is protected !!