이제 개발하는 앱들은 모두 targetAPI를 31로 잡아야 하는데요.
오늘은 어떤 것들에 대응해야 하는지 정리해 보도록 하겠습니다.
1. TargetAPI 31(Android12)
22년 11월 부터는 TargetAPI가 31이하일 경우에는 아래와 같은 경고메시지를 보게됩니다.
신규제출하는 경우에는 이미 22년 8월부터 적용되어 있었구요.
기존앱들의 업데이트의 경우 targetAPI31을 반드시 지켜야 합니다.
2. TargetAPI 30(Android11) -> 31(Android12)
구글공식문서에 나온 사항들 중 중요하게 볼 것은 다음과 같습니다.
구분 | 내용 |
Location | 유저는 앱이 위치정보를 요구할 때, 대략의 위치정보만 앱이 요구하도록 변경할 수 있습니다. 따라서, 유저가 이렇게 대략의 위치정보만 요구하도록 할 때를 대비해, ACCESS_FINE_LOCATION 을 요구할 때, ACCESS_COARSE_LOCATION을 같이 request 해 주어야 합니다. |
Intent Filters | 만약, 앱이 intent filters를 사용하고 있는데, activities, services, or broadcast receiver 를 포함하고 있다면, android:exported attribute 를 명시적으로 선언해 주어야 합니다. |
Hibernation | 앱들은 모두 일정시간동안 사용되지 않을 경우, hibernation모드에 들어갈 수 있습니다. 이 모드에서는 runtime permission과 cache들이 모두 리셋됩니다. 따라서, jobs라든가 alerts들이 동작하지 않습니다. |
Pending intent mutability | 앱에서 만든, PendingIntent객체들에 대해서 mutability에 대해 정의해주어야 합니다. 이에 대해서 확인하기 위해서는, logcat에서 아래와 같은 워닝이 뜨고 있지 않은지 확인해 보면 됩니다. >> Warning: Missing PendingIntent mutability flag [UnspecifiedImmutableFlag] |
이 들중, Intent Filters와 Pending intent mutability 그리고 Location에 대해서 아래에서 자세히 알아보도록 하겠습니다.
3. Intent Filters
위 사항중 Intent Filters는 모든 앱에 적용되는 사항이 될 것 같은데요.
실행해 보면 아래와 같은 에러메시지를 보게 됩니다.
이것이 왜 모든 앱들에 적용되는가 하면,
앱이 론칭되어 첫번째 화면으로 지정된 액티비티의 경우,
intent-filter를 가지게 되기 때문입니다.
아래의 경우에는 true로 설정해 주었네요.
이 둘의 차이는 아래와 같은 차이를 가지게 됩니다.
exported | 의미 |
true | 해당 activity가 다른 앱에 의해서 액세스 할 수 있을 때 입니다. 위와 같이 론칭되는 첫 화면은 OS에 의해서 실행되어야 하므로, true로 설정되어야 합니다. |
false | 같은 앱의 컴포넌트에 의해서만 론칭되게 할 수 있습니다. |
Splash화면같은 첫 화면에서는 당연히 exported:true로 설정되어야 하는데요.
API31부터는 정확하게 선언해 주어야 합니다.
4. Pending intent mutability
Pending Intent를 사용하였는데 아무런 변경없이 앱을 실행시켜 보면 아래와 같은 화면을 보게 됩니다.
어떤 경우에, FLAG_IMMUTABLE 을 사용하고, 어떤 경우는 사용하지 않아야 하는지 고민이 되는데요.
구글에서 말하는 FLAG_MUTABLE을 사용할 수 있는 경우들은 다음과 같습니다.
- AlarmManager를 통해 alarm을 스케쥴링하는 경우
- 이름대로, EXTRA_ALARM_COUNT 값을 변경할 수 있게 해 주고, 이를 토대로 정확한 숫자로 알람을 반복적으로 실행할 수 있게 해 줍니다.
- requestLocationUpdates() 와 같이 device의 위치정보를 요청하는 경우
- location lifecycle events들을 나타내는 intent extra를 추가해 줍니다.
- notification에서 direct reply actions를 지원하는 경우
물론, 위의 경우들을 기계적으로 적용할 필요는 없을 것 같구요.
앱의 상황에 맞게 해당 Intent가 mutable해야하는지 immutable해야하는지를 기준으로 선택해 주어야 하겠습니다.
FLAG를 바꿀때는 아래와 같이 해 주어야 하는데요.
아래와 같이 API23을 기준으로 해서 if문으로 구분해서 넣어주어야 합니다.
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
일일히 코드를 수정하기는 너무 불편해서 아래와 같은 Util함수를 만들어서 사용하는 것도 방법입니다.
fun getImmutablePendingIntentFlag(flag: Int): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE or flag
} else flag
}
이러한 조치를 하지 않으면 RuntimeException이 나게 되는데요.
어디서 이런 문제가 발생하는지 알기 어렵기 때문에,
PendingIntent를 쓰는 코드를 모두 찾아내서 수정해야 합니다.
PendingIntent관련 코드를 모두 수정했는데도,
문제가 발생한다면 아래 라이브러리를 추가해보면 해결되기도 합니다.
저의 경우도 그러하였구요.
implementation 'androidx.work:work-runtime-ktx:2.7.1'
Android버전이 올라가면서,
if문이 계속 늘어나서 코드 보는 것 자체도 너무 어려워지는 것 같습니다.
너무나 아쉬운 부분입니다.
5. ACCESS_FINE_LOCATION Permission
구글에서는 FINE_LOCATION permisison을 유저로부터 요청할 경우,
COARSE_LOCATION permission도 얻을 수 있도록 하였는데요.
유저가 원치 않으면, 대략적인 위치만으로도 앱을 사용할 수 있게 하라는 의미입니다.
우선 Manifest파일에,
ACCESS_FINE_LOCATION permission을 사용하고 있었다면,
아래와 같이 컴파일 에러를 보게 됩니다.
우선 manifest에서는 아래와 같이 해주면 됩니다.
여기서 끝이 아니구요.
Location관련 permission은 동적permission 요청사항이기 때문에,
동적 Permission요청사항에 대해서도 대응할 수 있도록 해 주어야 합니다.
다만, 동적 Permission에 FINE_LOCATION이 없다면 해당 코드가 동작하거나 화면으로 이동하지 않도록 조건이 들어가 있다면,
앱이 크래쉬가 나지는 않습니다.
실제로도 COARSE_LOCATION으로는 앱이 정상적으로 동작하지 않아서, 의미가 없을경우가 있을 것 입니다.
6. 공식문서 참고링크
위에서는 Android12에서 적용해야 할 주요부분들에 대해서 정리해 보았는데요.
모든 사항에 대해서 디테일하게 보아야 하실분들은,
아래의 공식문서 링크를 참조해 주시면 됩니다.
>> https://developer.android.com/google/play/requirements/target-sdk
>> https://developer.android.com/about/versions/12/behavior-changes-12
targetSDK업데이트는 계속 부채처럼 쌓여서 개인개발자들을 힘들게 하는데요.
거의 부채처럼 인식해서 틈날때 미리미리 이러한 업데이트사항들을 팔로우하고,
업데이트 해 두어야 하겠습니다.
'Android 개발 > Android' 카테고리의 다른 글
Vibrator 로 구현하는 안드로이드 진동 (0) | 2023.05.23 |
---|---|
SharedPreference 로 간단한 데이터 저장하기 # Android (2) | 2023.04.27 |
getLaunchIntentForPackage 로 다른 앱을 실행 하는 방법 # query Android 11 (0) | 2023.04.20 |
함수안에 함수 넣기 # Closure Local functions Kotlin (0) | 2023.04.15 |
RemoteConfig 이용해서 다이나믹하게 앱 업데이트 하기 # Android (1) | 2023.03.23 |
Contentprovider 와 ContentResolver 이용한 CRUD # Mime-type Uri (1) | 2022.11.18 |
Android 리소스 정리시 사용하는 Naming Convention (0) | 2022.11.12 |
Android 에서 동적 권한 얻기 # State registerForActivityResult Runtime Permission (0) | 2022.10.24 |
카카오톡이나 페이스북에서 사용하는 HashKey 얻어오기 #Android (0) | 2021.05.07 |
registerForActivityResult 구현방법 정리 # 예전 onActivityResult (0) | 2021.04.01 |
댓글