동작 변경사항: 모든 앱

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

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

핵심 기능

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

앱 메모리 제한

Android 17 引入了基于设备总 RAM 的应用内存限制,旨在为您的应用和 Android 用户打造更稳定、更具确定性的环境。这些限制侧重于在内存泄漏和其他异常值触发系统范围的不稳定性(导致界面卡顿、电池耗电量增加和应用被终止)之前,对其进行限制。虽然我们预计对绝大多数应用会话的影响很小,但我们建议您遵循以下内存最佳实践,包括建立内存基准。

您可以在 ApplicationExitInfo 中调用 getDescription,以确定您的应用会话是否受到影响;如果您的应用受到 影响,退出原因将为 REASON_OTHER,并且 说明将包含字符串 "MemoryLimiter:AnonSwap" 以及 其他信息。您还可以使用基于触发器的分析(使用 TRIGGER_TYPE_ANOMALY)来获取在达到 内存限制时收集的堆转储。

管理应用内存”文档提供了相关信息 可帮助您诊断应用的内存问题并优化其资源 消耗。

在内存限制下测试应用的行为

您可以使用 Android 调试桥 (adb) 调整或停用对任何设备施加的 内存限制。Shell 命令 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 指定进程的内存限制为 30 MB。传递 max 会移除对该进程的所有内存限制。 传递 none 会移除对该进程设置的任何手动限制,从而恢复系统的默认限制(如果有)。

status

报告内存限制器的当前状态。该状态包括对可见和不可见进程施加的内存限制。

개인 정보 보호

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

SMS OTP 보호

Android 17부터 Android는 일회용 비밀번호 (OTP)가 포함된 SMS 메시지에 대한 보호를 확대합니다.

이전 버전의 Android에서는 이 보호가 주로 SMS Retriever 형식에 중점을 두었습니다. SMS Retriever 해시가 포함된 메시지 전송은 대부분의 앱에서 3시간 동안 지연되었습니다. 그러나 특정 앱 (예: 기본 SMS 핸들러)은 지연에서 제외되었으며 해시를 소유한 앱도 제외되었습니다.

Android 17부터는 WebOTP 형식 메시지에도 보호가 적용됩니다. 앱에 SMS 메시지를 읽을 권한이 있지만 도메인 확인에 따라 WebOTP 메시지의 수신자가 아닌 경우 메시지를 받은 후 3시간이 지나야 앱에서 메시지에 액세스할 수 있습니다. 이번 변경사항은 메시지에 언급된 도메인과 연결된 앱만 프로그래매틱 방식으로 인증 코드를 읽을 수 있도록 하여 사용자 보안을 개선하기 위한 것입니다.

이 3시간 지연 동안 SMS_RECEIVED_ACTION 브로드캐스트가 보류되고 SMS 제공업체 데이터베이스 쿼리가 필터링됩니다. 지연 후 이러한 앱에서 SMS 메시지를 사용할 수 있습니다. 이번 변경사항은 대상 API 수준과 관계없이 모든 앱에 적용됩니다.

기본 SMS 어시스턴트 앱, 연결된 기기 도우미 앱 등과 같은 특정 앱은 이 지연에서 제외됩니다. OTP 추출을 위해 SMS 메시지 읽기에 의존하는 모든 앱은 지속적인 기능을 보장하기 위해 SMS Retriever 또는 SMS User Consent API를 사용하도록 전환해야 합니다.

보안

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

usesClearTraffic 지원 중단 계획

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

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

  • usesCleartextTraffic 속성을 true으로 설정
  • 네트워크 구성 파일 사용

앱의 최소 API 수준이 24 이상이면 네트워크 구성 파일을 사용할 수 있으며 usesCleartextTraffic를 설정하지 않아도 됩니다.

암시적 URI 부여 제한

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

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

Kotlin

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

Java

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"

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

Kotlin

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

Java

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

ACTION_IMAGE_CAPTURE 인텐트에 FLAG_GRANT_READ_URI_PERMISSIONFLAG_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);

앱별 키 저장소 한도

应用应避免在 Android 密钥库中创建过多的密钥,因为它是设备上所有应用的共享资源。从 Android 17 开始,系统会强制限制应用可拥有的密钥数量。对于以 Android 17(API 级别 37)或更高版本为目标平台的非系统应用,密钥数量上限为 50,000 个;对于所有其他应用,密钥数量上限为 200,000 个。无论系统应用以哪个 API 级别为目标,其密钥数量上限均为 20 万。

如果应用尝试创建超出限制的密钥,则创建会失败并显示 KeyStoreException。异常的消息字符串包含有关密钥限制的信息。如果应用针对异常调用 getNumericErrorCode(),则返回值取决于应用的目标 API 级别:

  • 如果应用以 Android 17(API 级别 37)或更高版本为目标平台,getNumericErrorCode() 会返回新的 ERROR_TOO_MANY_KEYS 值。
  • 所有其他应用:getNumericErrorCode() 返回 ERROR_INCORRECT_USAGE

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

Android 17부터는 교차 프로필 루프백 트래픽이 기본적으로 더 이상 허용되지 않습니다. 동일한 프로필 내의 루프백 트래픽은 영향을 받지 않습니다. 이 변경사항은 앱이 타겟팅하는 API 수준과 관계없이 Android 17 이상에서 실행되는 모든 앱에 적용됩니다.

사용자 환경 및 시스템 UI

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

회전 후 기본 IME 공개 상태 복원

从 Android 17 开始,当设备的配置发生变化(例如,通过旋转)且应用本身未处理此变化时,系统不会恢复之前的 IME 可见性。

如果应用经历了它无法处理的配置更改,并且应用需要在更改后显示键盘,您必须明确请求此行为。您可以通过以下方式之一提出此要求:

  • android:windowSoftInputMode 属性设置为 stateAlwaysVisible
  • 在 activity 的 onCreate() 方法中以编程方式请求显示软键盘,或添加 onConfigurationChanged() 方法。

수동 입력

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

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

从 Android 17 开始,如果应用使用 View.requestPointerCapture() 请求捕获指针,并且用户使用触控板,系统会识别用户触摸操作产生的指针移动和滚动手势,并以与捕获的鼠标产生的指针和滚轮移动相同的方式将这些信息报告给应用。在大多数情况下,这使得支持捕获鼠标的应用无需为触控板添加特殊的处理逻辑。如需了解详情,请参阅 View.POINTER_CAPTURE_MODE_RELATIVE 的文档。

之前,系统不会尝试识别触控板的手势,而是以类似于触摸屏触摸的格式将原始的绝对手指位置传递给应用。如果应用仍需要此绝对数据,则应改为使用 View.POINTER_CAPTURE_MODE_ABSOLUTE 调用新的 View.requestPointerCapture(int) 方法。

미디어

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

백그라운드 오디오 강화

从 Android 17 开始,音频框架会对后台音频互动(包括音频播放、音频焦点请求和音量更改 API)强制执行限制,以确保这些更改是由用户有意发起的。

如果应用尝试在应用未处于有效生命周期时调用音频 API,则音频播放和音量更改 API 会以静默方式失败,而不会抛出异常或提供失败消息。音频焦点 API 会失败,并返回结果代码 AUDIOFOCUS_REQUEST_FAILED

如需了解详情(包括缓解措施),请参阅后台音频安全加固

연결

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

블루투스 페어링 손실 시 자동 재페어링

Android 17 引入了自主重新配对功能,这是一项系统级增强功能,旨在自动解决蓝牙配对信息丢失问题。

以前,如果配对信息丢失,用户必须手动前往“设置”取消配对,然后重新配对外围设备。此功能以 Android 16 的安全改进为基础,允许系统在后台重新建立配对信息,而无需用户手动前往“设置”取消配对并重新配对外围设备。

虽然大多数应用不需要更改代码,但开发者应注意蓝牙堆栈中的以下行为变更:

  • 新的配对上下文ACTION_PAIRING_REQUEST 现在包含 EXTRA_PAIRING_CONTEXT extra,允许应用区分 标准配对请求和自主系统发起的重新配对尝试。
  • 有条件的密钥更新:只有在重新配对成功且新连接达到或超过之前配对信息的安全级别时,才会替换现有安全密钥。
  • 修改后的 intent 时间:现在,只有在自主重新配对尝试失败时,才会广播 ACTION_KEY_MISSING intent。如果系统在后台成功恢复配对信息,则可以减少应用中不必要的错误处理。
  • 用户通知:系统通过新的界面通知和对话框管理重新配对。系统会提示用户确认重新配对尝试,以确保用户了解重新连接。

外围设备制造商和配套应用开发者应验证硬件和应用是否能妥善处理配对信息转换。如需测试此行为,请使用以下任一方法模拟远程配对信息丢失:

  • 从外围设备中手动移除配对信息
  • 在“设置”>“已连接的设备”中手动取消配对设备