동작 변경사항: 모든 앱

Android 17 플랫폼에는 앱에 영향을 줄 수 있는 동작 변경사항이 있습니다. targetSdkVersion과 관계없이 Android 17에서 실행되는 모든 앱에 적용되는 동작 변경사항은 다음과 같습니다. 이러한 변경사항을 적절히 지원해야 하는 경우 앱을 테스트한 후 필요에 따라 수정해야 합니다.

또한 Android 17을 타겟팅하는 앱에만 영향을 주는 동작 변경사항 목록을 검토해야 합니다.

핵심 기능

Android 17 (API 수준 37)에는 Android 시스템의 다양한 핵심 기능을 수정하거나 확장하는 다음과 같은 변경사항이 포함되어 있습니다.

앱 메모리 제한

Android 17에서는 기기의 총 RAM에 기반한 앱 메모리 제한을 도입하여 앱과 Android 사용자를 위한 더 안정적이고 결정론적인 환경을 만듭니다. 이러한 한도는 메모리 누수 및 기타 이상점이 UI 끊김, 배터리 소모 증가, 앱 종료를 초래하는 시스템 전반의 불안정성을 유발하기 전에 이를 해결하는 데 중점을 둡니다. 대부분의 앱 세션에 미치는 영향은 최소화될 것으로 예상되지만, 메모리 기준 설정 등 다음 메모리 권장사항을 따르는 것이 좋습니다.

ApplicationExitInfo에서 getDescription를 호출하여 앱 세션이 영향을 받았는지 확인할 수 있습니다. 앱이 영향을 받은 경우 종료 이유는 REASON_OTHER이고 설명에는 다른 정보와 함께 문자열 "MemoryLimiter:AnonSwap"가 포함됩니다. TRIGGER_TYPE_ANOMALY와 함께 트리거 기반 프로파일링을 사용하여 메모리 한도에 도달할 때 수집되는 힙 덤프를 가져올 수도 있습니다.

앱 메모리 관리 문서에서는 앱의 메모리 문제를 진단하고 리소스 소비를 최적화하는 데 도움이 되는 정보를 제공합니다.

메모리 제약 조건에서 앱 동작 테스트

Android 디버그 브리지 (adb)를 사용하여 메모리 제한을 적용하는 모든 기기에서 메모리 제한을 조정하거나 사용 중지할 수 있습니다. 셸 명령어 am는 메모리 한도를 조정하는 세 가지 하위 명령어를 제공합니다. 이러한 명령어는 메모리 제한을 적용하지 않는 기기에는 영향을 미치지 않습니다.

  • am memory-limiter ignore <uid>|none|all
  • am memory-limiter manual <pid> <limit>|max|none
  • am memory-limiter status
ignore

메모리 제한기에 일부 또는 모든 프로세스를 무시하도록 지시합니다. UID (Android 사용자 ID)를 전달하면 메모리 제한기가 해당 UID와 연결된 모든 프로세스에 대한 시행을 무시하도록 지시합니다. all (모든 앱 무시) 또는 none(앱을 무시하지 않음)을 전달할 수도 있습니다. none를 전달하면 이전의 am memory-limiter ignore 호출이 재정의됩니다.

메모리 제한기에 UID를 무시하도록 지시하는 경우에도 am memory-limiter manual를 호출하여 앱 내 프로세스에 수동 메모리 한도를 적용할 수 있습니다.

manual

지정된 PID (프로세스 ID)를 사용하여 프로세스에 메모리 제약 조건을 적용하도록 시스템에 지시합니다. 메모리 제약 조건은 정수 MB로 지정됩니다. 예를 들어 30을 전달하면 프로세스가 30MB의 메모리로 제한됩니다. max를 전달하면 해당 프로세스의 모든 메모리 한도가 삭제됩니다. none을 전달하면 프로세스에 설정된 수동 한도가 삭제되고 시스템의 기본 한도 (있는 경우)가 복원됩니다.

status

메모리 제한기의 현재 상태를 보고합니다. 상태에는 표시되는 프로세스와 표시되지 않는 프로세스에 적용되는 메모리 한도가 포함됩니다.

개인 정보 보호

Android 17에는 사용자 개인 정보 보호를 개선하기 위한 다음과 같은 변경사항이 포함되어 있습니다.

SMS OTP 보호

Beginning with Android 17, Android is expanding its protection for SMS messages containing one-time passwords (OTP).

In previous versions of Android, this protection was primarily focused on the SMS Retriever format. Delivery of messages containing an SMS retriever hash was delayed for most apps for three hours. However, certain apps (like the default SMS handler) were exempt from the delay, and the app that owned the hash was also exempted.

Beginning with Android 17, the protection is also applied to WebOTP format messages. If an app has permission to read SMS messages but is not the intended recipient of a WebOTP message (as determined by domain verification), the message is not accessible to the app until three hours after the message's receipt. This change is intended to improve user security by ensuring that only apps associated with the domain mentioned in the message can programmatically read the verification code.

During this three hour delay, the SMS_RECEIVED_ACTION broadcast is withheld and SMS provider database queries are filtered. The SMS message is available to these apps after the delay. This change applies to all apps, regardless of their target API level.

Certain apps such as the default SMS assistant app, connected device companion apps, etc., are exempted from this delay. All apps that rely on reading SMS messages for OTP extraction should transition to using SMS Retriever or SMS User Consent APIs to ensure continued functionality.

보안

Android 17에는 기기 및 앱 보안과 관련된 다음과 같은 개선사항이 포함되어 있습니다.

usesClearTraffic 지원 중단 계획

향후 출시에서 usesCleartextTraffic 요소를 지원 중단할 계획입니다. 암호화되지 않은 (HTTP) 연결을 만들어야 하는 앱은 네트워크 보안 구성 파일을 사용하도록 이전해야 합니다. 이 파일을 사용하면 앱이 일반 텍스트 연결을 만들어야 하는 도메인을 지정할 수 있습니다.

네트워크 보안 구성 파일은 API 수준 24 이상에서만 지원됩니다. 앱의 최소 API 수준이 24 미만인 경우 다음을 모두 실행해야 합니다.

  • usesCleartextTraffic 속성을 true로 설정합니다.
  • 네트워크 구성 파일 사용

앱의 최소 API 수준이 24 이상인 경우 네트워크 구성 파일을 사용할 수 있으며 usesCleartextTraffic를 설정할 필요가 없습니다.

암시적 URI 권한 부여 제한

현재 앱이 ACTION_SEND, ACTION_SEND_MULTIPLE 또는 ACTION_IMAGE_CAPTURE 작업이 있는 URI로 인텐트를 실행하면 시스템은 대상 앱에 읽기 및 쓰기 URI 권한을 자동으로 부여합니다. Android 18부터 시스템은 더 이상 이러한 권한을 자동으로 부여하지 않습니다. 따라서 앱이 시스템에 의존하여 권한을 부여하는 대신 관련 URI 권한을 명시적으로 부여하는 것이 좋습니다.

앱에서 이러한 인텐트의 사용을 감지하려면 StrictMode를 detectImplicitUriPermissionGrant()와 함께 사용하여 위반을 트리거합니다.

Kotlin

val policy = StrictMode.VmPolicy.Builder()
    .detectImplicitUriPermissionGrant()
    .penaltyLog()
    .build()
StrictMode.setVmPolicy(policy)

자바

StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
    .detectImplicitUriPermissionGrant()
    .penaltyLog()
    .build();
StrictMode.setVmPolicy(policy);

또는 시스템이 암시적으로 권한을 설정할 때 표시되는 Please set the grant explicitly in the app 메시지가 포함된 로깅된 예외를 모니터링할 수 있습니다. 다음 adb 명령어를 사용하여 이러한 로그를 모니터링할 수 있습니다.

adb logcat | grep "Please set the grant explicitly in the app"

필요한 권한을 명시적으로 부여하려면 FLAG_GRANT_READ_URI_PERMISSION 플래그를 ACTION_SEND 및 ACTION_SEND_MULTIPLE 인텐트에 추가합니다.

Kotlin

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

자바

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

ACTION_IMAGE_CAPTURE 인텐트의 FLAG_GRANT_READ_URI_PERMISSION 및 FLAG_GRANT_WRITE_URI_PERMISSION 플래그를 모두 포함합니다.

Kotlin

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

자바

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

앱별 키 저장소 제한

Apps should avoid creating excessive numbers of keys in Android Keystore, because it is a shared resource for all apps on the device. Beginning with Android 17, the system enforces a limit on the number of keys an app can own. The limit is 50,000 keys for non-system apps targeting Android 17 (API level 37) or higher, and 200,000 keys for all other apps. System apps have a limit of 200,000 keys, regardless of which API level they target.

If an app attempts to create keys beyond the limit, the creation fails with a KeyStoreException. The exception's message string contains information about the key limit. If the app calls getNumericErrorCode() on the exception, the return value depends on what API level the app targets:

  • Apps targeting Android 17 (API level 37) or higher: getNumericErrorCode() returns the new ERROR_TOO_MANY_KEYS value.
  • All other apps: getNumericErrorCode() returns ERROR_INCORRECT_USAGE.

교차 프로필 루프백 트래픽 차단

Beginning with Android 17, cross-profile loopback traffic is no longer permitted by default. Loopback traffic within the same profile is not affected. This change applies to all apps running on Android 17 or higher, regardless of what API level the app targets.

사용자 환경 및 시스템 UI

Android 17에는 더 일관되고 직관적인 사용자 환경을 만들기 위한 다음 변경사항이 포함되어 있습니다.

회전 후 기본 IME 가시성 복원

Beginning with Android 17, when the device's configuration changes (for example, through rotation), and this is not handled by the app itself, the previous IME visibility is not restored.

If your app undergoes a configuration change that it does not handle, and the app needs the keyboard to be visible after the change, you must explicitly request this. You can make this request in one of the following ways:

  • Set the android:windowSoftInputMode attribute to stateAlwaysVisible.
  • Programmatically request the soft keyboard in your activity's onCreate() method, or add the onConfigurationChanged() method.

수동 입력

Android 17에는 앱이 키보드 및 터치패드와 같은 인간 입력 장치와 상호작용하는 방식에 영향을 미치는 다음과 같은 변경사항이 포함되어 있습니다.

터치패드는 포인터 캡처 중에 기본적으로 상대 이벤트를 전송함

Android 17부터 앱이 View.requestPointerCapture()를 사용하여 포인터 캡처를 요청하고 사용자가 터치패드를 사용하는 경우 시스템은 사용자의 터치에서 포인터 움직임과 스크롤 동작을 인식하고 캡처된 마우스의 포인터 및 스크롤 휠 움직임과 동일한 방식으로 앱에 보고합니다. 대부분의 경우 이렇게 하면 캡처된 마우스를 지원하는 앱이 터치패드에 관한 특수 처리 로직을 추가할 필요가 없습니다. 자세한 내용은 View.POINTER_CAPTURE_MODE_RELATIVE 문서를 참조하세요.

이전에는 시스템이 터치패드의 동작을 인식하려고 시도하지 않았으며, 대신 터치스크린 터치와 유사한 형식으로 원시 절대 손가락 위치를 앱에 전달했습니다. 앱에 이 절대 데이터가 여전히 필요한 경우 대신 View.POINTER_CAPTURE_MODE_ABSOLUTE를 사용하여 새 View.requestPointerCapture(int) 메서드를 호출해야 합니다.

미디어

Android 17에는 미디어 동작과 관련해 다음과 같은 변경사항이 포함되어 있습니다.

백그라운드 오디오 강화

Beginning with Android 17, the audio framework enforces restrictions on background audio interactions including audio playback, audio focus requests, and volume change APIs to ensure that these changes are started intentionally by the user.

If the app tries to call audio APIs while the app is not in a valid lifecycle, the audio playback and volume change APIs fail silently without throwing an exception or providing a failure message. The audio focus API fails with the result code AUDIOFOCUS_REQUEST_FAILED.

For more information, including mitigation strategies, see Background audio hardening.

연결

Android 17에는 기기 연결을 개선하기 위한 다음과 같은 변경사항이 포함되어 있습니다.

블루투스 연결 끊김 시 자동 다시 페어링

Android 17에는 블루투스 결합 손실을 자동으로 해결하도록 설계된 시스템 수준 개선사항인 자율 재페어링이 도입되었습니다.

이전에는 결합이 끊어지면 사용자가 수동으로 설정으로 이동하여 주변기기를 페어링 해제한 후 다시 페어링해야 했습니다. 이 기능은 Android 16의 보안 개선사항을 기반으로 하며, 사용자가 수동으로 설정으로 이동하여 주변기기를 페어링 해제하고 다시 페어링하지 않아도 시스템이 백그라운드에서 결합을 다시 설정할 수 있도록 합니다.

대부분의 앱은 코드 변경이 필요하지 않지만 개발자는 블루투스 스택의 다음과 같은 동작 변경사항을 알고 있어야 합니다.

  • 새 페어링 컨텍스트: 이제 ACTION_PAIRING_REQUEST에 EXTRA_PAIRING_CONTEXT 추가 항목이 포함되어 앱이 표준 페어링 요청과 자율 시스템에서 시작한 재페어링 시도를 구분할 수 있습니다.
  • 조건부 키 업데이트: 기존 보안 키는 다시 페어링이 성공하고 새 연결이 이전 결합의 보안 수준을 충족하거나 초과하는 경우에만 교체됩니다.
  • 수정된 인텐트 타이밍: 이제 ACTION_KEY_MISSING 인텐트는 자율 재페어링 시도가 실패한 경우에만 브로드캐스트됩니다. 이렇게 하면 시스템이 백그라운드에서 결합을 성공적으로 복구하는 경우 앱에서 불필요한 오류 처리가 줄어듭니다.
  • 사용자 알림: 시스템은 새로운 UI 알림 및 대화상자를 통해 다시 페어링을 관리합니다. 사용자에게 다시 페어링 시도를 확인하라는 메시지가 표시되어 재연결을 인지할 수 있습니다.

주변기기 제조업체와 호환 앱 개발자는 하드웨어와 앱이 결합 전환을 원활하게 처리하는지 확인해야 합니다. 이 동작을 테스트하려면 다음 방법 중 하나를 사용하여 원격 결합 손실을 시뮬레이션합니다.

  • 주변기기에서 결합 정보를 수동으로 삭제합니다.
  • 설정 > 연결된 기기에서 기기의 페어링을 수동으로 해제합니다.