안드로이드 targetSDK & compileSDK 를 33 → 34 마이그레이션 정리
(번역)알림: 정확한 알람 일정은 기본적으로 거부됩니다.
[본문]
With the launch of Android 14, apps targeting Android 13 (API level 33) or
higher have new restrictions on using SCHEDULE_EXACT_ALARM.
If you had already upgraded your app to API level 33 before Android 14
then please go back to the Android 12L / API level 32 → Android 13 / API level 33 sequence and find this new upgrade step.
If you have already completed that migration step as part of the upgrade to API
level 33 then there is nothing extra to do as part of the upgrade to API level 34.
For more information, see Schedule exact alarms are denied by default.
공식문서: https://developer.android.com/about/versions/14/changes/schedule-exact-alarms?hl=ko
(번역) 포그라운드 서비스 유형은 필수 항목입니다.
[본문]
If your app targets Android 14, it must specify at least one foreground service type for each foreground service within your app.
You should choose a foreground service type that represents your app's use case.
The system expects foreground services that have a particular type to satisfy a particular use case.
Note: Android 14 introduces foreground service types for health and remote messaging use cases.
The system also reserves new types for short services, special use cases, and system exemptions.
If a use case in your app isn't associated with any of these types,
it's strongly recommended that you migrate your logic to use WorkManager
or user-initiated data transfer jobs.
Android 14 대상 앱의 요구사항
새로운 포그라운드 서비스 유형
사용 사례가 관련 유형과 맞지 않는 경우
Android 14의 주요 업데이트 중 하나로 최신 OpenJDK LTS 릴리스와의 기능 정렬을 위한 Android 핵심 라이브러리가 지속적으로 갱신되고 있습니다.
이번 라이브러리 업데이트는 앱 및 플랫폼 개발자를 위한 Java 17 언어 지원이며, 호환성에 영향을 미칠 수 있는 변경사항입니다.
Matcher 클래스에서 IllegalArgumentException이 발생할 수 있는 새로운 경우를 볼 수 있습니다. 따라서 정규 표현식을 사용하는 앱 영역에 대해 테스트를 수행해야 합니다.
일부 경우에는 java.lang.ClassValue 클래스를 추가하면 ProGuard를 사용하여 앱을 축소화, 난독화 및 최적화하려고 할 때 문제가 발생할 수 있습니다.
(번역): 암시적 및 보류 중인 인텐트에 대한 제한사항
<activity
android:name=".AppActivity"
android:exported="false">
<intent-filter>
<action android:name="com.example.action.APP_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
만약 앱이 위의 인텐트 필터로 선언된 액티비티를 암시적 인텐트로 실행하려고 한다면, 다음과 같이 예외가 발생할 것입니다
// Android 14를 타겟으로 할 때 예외가 발생합니다.
context.startActivity(Intent("com.example.action.APP_ACTION"))
다음은 export 되지 않은 액티비티를 만드는 예제입니다.
// This makes the intent explicit.
val explicitIntent = Intent("com.example.action.APP_ACTION")
explicitIntent.apply {
package = context.packageName
}
context.startActivity(explicitIntent)
(번역): 런타임 등록 브로드캐스트 수신기는 내보내기 동작을 지정해야 합니다.
안드로이드 14를 타겟으로 하고 context-registered 리시버를 사용하는 앱과 서비스는 리시버가 기기의 다른 모든 앱에 내보내져야 하는지 여부를 나타내는 플래그를 지정해야 합니다
시스템 브로드캐스트만 받는 리시버에 대한 예외
(번역): 더욱 안전한 동적 코드 로딩
안드로이드 14를 타겟으로 하고 동적 코드 로딩(Dynamic Code Loading, DCL)을 사용하는 경우, 모든 동적으로 로드된 파일은 읽기 전용으로 설정되어야 합니다. 그렇지 않으면 시스템에서 예외가 발생합니다.
가능하다면 동적 코드 로딩을 피하는 것이 좋습니다. 이는 코드 주입이나 코드 변조에 의해 앱이 손상될 위험을 크게 증가시키기 때문입니다.
동적 코드를 로드해야 하는 경우, 파일이 열리자마자 파일을 읽기 전용으로 설정하고, 콘텐츠가 기록되기 전에 다음 접근 방식을 사용하세요
val jar = File("DYNAMICALLY_LOADED_FILE.jar")
val os = FileOutputStream(jar)
os.use {
// 경합 조건을 방지하기 위해 먼저 파일을 읽기 전용으로 설정
jar.setReadOnly()
// 그런 다음 실제 파일 내용을 작성
}
val cl = PathClassLoader(jar, parentClassLoader)
이미 존재하는 동적으로 로드된 파일 처리
기존의 동적으로 로드된 파일에 대해 예외가 발생하는 것을 방지하려면, 해당 파일을 다시 로드하기 전에 삭제하고 새로 생성하는 것을 권장합니다. 파일을 새로 생성할 때, 파일을 쓰기 시점에 읽기 전용으로 설정하는 위의 지침을 따르세요.
또는 기존 파일을 읽기 전용으로 다시 라벨링할 수도 있지만, 이 경우 파일의 무결성을 먼저 확인하는 것이 좋습니다(예: 신뢰할 수 있는 값에 대한 파일 서명을 확인). 이는 악의적인 행위로부터 앱을 보호하는 데 도움이 됩니다.
(번역): 백그라운드에서 활동 시작에 대한 추가 제한 사항
PendingIntent 사용 시 제한
val pendingIntent = PendingIntent.getActivity(context, requestCode, intent, flags)
val options = ActivityOptions.makeBasic()
options.setPendingIntentBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
pendingIntent.send(null, 0, null, null, null, null, options.toBundle())
bindService 사용 시 제한
val intent = Intent(context, MyService::class.java)
val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
// 서비스 연결 시 작업
}
override fun onServiceDisconnected(name: ComponentName) {
// 서비스 연결 해제 시 작업
}
}
context.bindService(intent, serviceConnection, Context.BIND_ALLOW_ACTIVITY_STARTS)
Android 14에서 사용자는 앱이 시각적 미디어 권한(READ_MEDIA_IMAGES 또는 READ_MEDIA_VIDEO)을 요청할 때 시각적 미디어 라이브러리(사진/비디오)에 대한 부분 접근 권한을 부여할 수 있습니다. 이 변경 사항을 지원하기 위해 아래의 세부 사항을 확인하세요.
새 권한 부여 옵션
시스템 동작
새 권한
앱이 변경하지 않는 경우의 동작
READ_MEDIA_VISUAL_USER_SELECTED 권한을 선언하지 않으면 다음 동작이 발생합니다:
READ_MEDIA_IMAGES 및 READ_MEDIA_VIDEO 권한은 앱 세션 동안 부여되며, 임시 접근 권한을 제공합니다.
앱이 백그라운드로 이동하거나 사용자가 앱을 종료하면 시스템은 권한을 거부합니다.
추가 사진 및 비디오 접근이 필요한 경우, READ_MEDIA_IMAGES 또는 READ_MEDIA_VIDEO 권한을 다시 요청해야 하며, 시스템은 사용자에게 사진 및 비디오를 선택하도록 다시 요청합니다.
앱이 권한 모범 사례를 따르면 이 변경 사항은 앱에 문제를 일으키지 않습니다. 예를 들어, URI 접근이 유지된다고 가정하지 않거나, 시스템 권한 상태를 저장하거나, 권한 변경 후 표시되는 이미지를 새로고침하는 경우.
앱에서 동작을 제어하려면
READ_MEDIA_VISUAL_USER_SELECTED 권한을 선언하고 사용자가 시스템 권한 대화 상자에서 "사진 및 비디오 선택"을 선택한 경우 다음 동작이 발생합니다:
READ_MEDIA_IMAGES 및 READ_MEDIA_VIDEO 권한은 모두 거부됩니다.
READ_MEDIA_VISUAL_USER_SELECTED 권한이 부여되어 사용자의 사진 및 비디오에 대한 부분적이고 임시 접근 권한을 제공합니다.
추가 사진 및 비디오 접근이 필요한 경우 READ_MEDIA_IMAGES 또는 READ_MEDIA_VIDEO 권한(또는 둘 다)을 다시 요청해야 합니다.
val jar = File("DYNAMICALLY_LOADED_FILE.jar")
val os = FileOutputStream(jar)
os.use {
// 경합 조건을 방지하기 위해 먼저 파일을 읽기 전용으로 설정
jar.setReadOnly()
// 그런 다음 실제 파일 내용을 작성
}
val cl = PathClassLoader(jar, parentClassLoader)
중요: 사용자가 시스템 대화 상자를 다시 보게 되지 않도록, READ_MEDIA_IMAGES 또는 READ_MEDIA_VIDEO 권한을 다시 요청하기 전에 앱에 UI 요소를 추가하세요.
권장 사항: 여러 시스템 런타임 대화 상자를 방지하기 위해 READ_MEDIA_VISUAL_USER_SELECTED, ACCESS_MEDIA_LOCATION 및 "read media" 권한(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO 또는 둘 다)을 한 번에 요청하세요.
추가 정보
부분 접근 권한 부여에 대한 자세한 내용은 Grant partial access to photos and videos 문서를 참조하세요.
공식 문서: https://developer.android.com/about/versions/14/changes/partial-photo-video-access?hl=ko