일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 도약전환
- 희망적금전환
- Flutter #Stream #dart
- Flutter #Stream
- 조립 후 재부팅
- 플러터 #안드로이드 #플레이콘솔 #앱내리기
- flutter #dart #stream
- 도약계좌전환
- 청년도약계좌환승
- 희망적금연계
- 도약연계
- 안드로이드 #코틀린 #코루틴 #콜백 #채널
- Today
- Total
Flutter 개발 상자
Android12 version31 이슈) Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. 본문
Android12 version31 이슈) Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
망고상자 2022. 1. 29. 14:36나는 플레이스토어에 앱을 2개를 올려놨다.
하나는 처음 안드로이드를 배우면서 만들어본 주변 관광지 탐색 어플이고
두번째는 내가 정말 실사용 하려고 만든 수면타이머 어플이다.
그런데 이번에 내 핸드폰이 Android12 업데이트가 된 이후에 수면타이머 앱을 켜자마자 바로 크래쉬 현상이 나는 현상이 발생했다!!
바로 휴대폰을 연결하고 안드로이드 스튜디오에서 에러 로그를 확인해보니 해당 코드에서 다음과 같은 오류가 발생하고 있었다.
에러 내용 :
Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
S+(버전 31 이상)를 타겟팅하려면 PendingIntent를 생성할 때 FLAG_IMMUTABLE 또는 FLAG_MUTABLE 중 하나를 지정해야 합니다.
S라는건 Android12를 뜻하는 알파벳 코드명이다.
에러 내용이 굉장히 구체적이기 때문에 수정은 쉬울것같다. 일단 빠르게 수정부터 해보자.
다음과 같이 Flag 변수부분을 권장하는 방법대로 수정했다.
그리고 앱 구동 결과는?
음... 이번에는 또 다른 에러가 발생하기 시작한다.
다른 권장 방법인 FLAG_MUTABLE를 사용해도 결과는 마찬가지였다.
뭔가 이번에는 안드로이드12와 관련 없는 에러가 뜨는것같다.
일단 해당 에러를 잡기 위해서 AlarmManager와 PendingIntent개념부터 다시 살펴봐야겠다.
일단 PendingIntent라는건 Intent를 바로 수행하지 않고
특정 작업이 다 완료된 후에 수행을 할 수 있게 해주는 기능이다.
이는 푸시알림이나 위젯 AlarmManager에서 쓰인다.
내가 수정한 매개변수인 PendingIntent 플래그의 종류는
FLAG_CANCEL_CURRENT : 이전에 생성한 PendingIntent는 취소하고 새롭게 만든다.
FLAG_NO_CERATE : 이미 생성된 PenddingIntent가 없다면 null을 return 하고 생성된게 있다면 재사용한다.
FLAG_ONE_SHOT : 이 PendingIntent를 한번만 사용할 수 있다.
FLAG_UPDATE_CURRENT : PenddingIntent가 이미 존재하는 경우 유지하되 추가 데이터를 새로운 Intent에 있는것으로 대체한다.
FLAG_IMMUTABLE : 생성된 PendingIntent가 변경할 수 없음을 나타낸다.
FLAG_MUTABLE : 생성된 PendingIntent가 변경 가능함을 나타낸다.
이렇고 내가 기존에 사용하던 Flag는 FLAG_UPDATE_CURRENT 기존에 FLAG_UPDATE_CURRENT를 사용하고 있었다면 다음과 같은 코드가 권장된다고 한다.
다음과 같이 or 비트연산자를 통해서 플래그를 넣어준다.
음... 이렇게 해도 에러가 수정되진 않는다.
에러 내용은
Context.startForegroundService() did not then call Service.startForeground()
Context.startForegroundService()는 Service.startForeground()를 호출하지 않았습니다.
에러 내용만 봤을때는 startForegroundService를 호출하지 않았다는것같은데
분명 서비스 실행 코드에 startForegroundService() 메서드로 제대로 intent와 context가 삽입되고 있으며
API30 디바이스로 테스트시 제대로 작동한다...
구글링을 해봐도 쉽게 발견되지 않는다. 구글링에서 발견되는 해결책은 죄다 API26일 경우 startForegroundService을 사용하라는것이고 나의 사례는 발견되지 않았다.
일단 이럴때 가장중요한건 에러가 발생하는 정확한 코드라인을 찾는것이다. ContextCompat.startForegroundService()
해당 라인을 주석처리 해본다.
결과는 크러시 발생하지 않음.
그렇다면 이제 서비스클래스에서 에러가 발생하는 코드를 찾아보자.
onStartCommand()에 있는 코드를 모두다 주석처리 하고 실행해봤다.
그랬더니 10초 후에 앱이 크러시됐다.
에러 내용은 똑같다.
Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord
이는 Notification을 띄워주는 코드가 없기 때문에 발생한것으로 추정된다.
그렇다면 다시 코드의 주석을 하나하나 풀어보자
그런데....
코드를 보자마자 아차싶다.
쓰레드 안의 running 코드 블록에 penddingIntent를 사용하는곳이 또 보였고, 이곳은 버전별 분기처리가 되어있지 않았다.
그런데 try catch블록 안에 들어가 있어서 익셉션이 발생하지 않고 있었으며
특정 에러를 잡는것이 아닌 모든 에러를 다 처리하고 있었기에 penddingIntent 관련 에러가 아닌 엉뚱한 에러를 계속 뱉어내고 있었던것이다.
바로 아까와 마찬가지로 버전별 분기처리를 해줬다.
그 뒤로는 역시나....
정상구동을 확인했다 !
이번 오류를 고치면서 배운점은
1. API31 이상일경우 PendingIntent Flag에 불변/가변 설정을 꼭 해줘야한다.
2. try catch문을 사용할 경우 익셉션을 광범위하게 잡지 말자. 광범위하게 잡는다면 디버깅 자체가 힘들어질 수 있다.
일단 Android12의 크래시 에러를 바로잡았고, 이젠 Android12 스플래시 화면을 대응해봐야겠다.
두개의 대응이 끝나면 앱 업데이트를 진행할 예정이다.
'Android' 카테고리의 다른 글
Exoplayer에서 이어폰이 해제되었을때 영상 일시중지하기 (유선, 블루투스) (0) | 2021.04.09 |
---|---|
[Android] Coroutine과 CallBack을 동시에 사용해보자 (0) | 2021.03.25 |