Google은 흑인 공동체를 위한 인종 간 평등을 진전시키기 위해 노력하고 있습니다. Google에서 어떤 노력을 하고 있는지 확인하세요.

동작 변경사항: API 레벨 29 이상을 타겟팅하는 앱

Android 10에는 앱에 영향을 줄 수 있는 업데이트된 시스템 동작 변경사항이 포함되어 있습니다. 이 문서에 나열된 변경사항은 API 29 이상을 타겟팅하는 앱에만 적용됩니다. targetSdkVersion을 '29' 이상으로 설정한 경우 이러한 동작을 올바르게 지원하도록(해당하는 경우) 앱을 수정해야 합니다.

또한 Android 10에서 실행되는 모든 앱에 영향을 미치는 동작 변경사항 목록을 검토해야 합니다.

비 SDK 인터페이스 제한사항 업데이트

앱 안정성과 호환성을 보장하기 위해 플랫폼에서는 Android 9(API 레벨 28)에서 앱이 사용할 수 있는 비 SDK 인터페이스를 제한하기 시작했습니다. Android 10에는 Android 개발자와의 공동작업 및 최신 내부 테스트를 기반으로 제한된 비 SDK 인터페이스의 업데이트된 목록이 포함되어 있습니다. Google의 목표는 비 SDK 인터페이스를 제한하기 전에 공개 대안을 사용할 수 있게 하는 것입니다.

Android 10(API 레벨 29)을 타겟팅하지 않을 경우, 이러한 변경사항 중 일부는 즉시 영향을 미치지 않을 수 있습니다. 그러나 현재 앱의 타겟 API 레벨에 따라 그레이리스트에 속한 비 SDK 인터페이스를 사용할 수는 있지만, 비 SDK 메서드나 필드를 사용하면 앱이 중단될 위험성이 높아집니다.

앱에서 비 SDK 인터페이스를 사용하는지 확실히 알 수 없는 경우 앱을 테스트하여 확인할 수 있습니다. 앱에서 비 SDK 인터페이스를 사용하는 경우 대체 SDK로 이전을 계획해야 합니다. 일부 앱의 경우 비 SDK 인터페이스 사용에 관한 유효한 사용 사례가 있음을 알고 있습니다. 앱 기능을 구현하기 위해 비 SDK 인터페이스 대신 무엇을 사용해야 할지 알 수 없다면 새 공개 API를 요청해야 합니다.

자세한 내용은 Android 10의 비 SDK 인터페이스 제한사항 업데이트비 SDK 인터페이스 제한사항을 참조하세요.

공유 메모리

Ashmem은 /proc/<pid>/maps에서 dalvik 형식을 변경하여 지도 파일을 직접적으로 파싱하는 앱에 영향을 주었습니다. 애플리케이션 개발자는 Android 10 이상을 실행하는 기기에서 /proc/<pid>/maps 형식을 테스트하고 앱이 dalvik 지도 형식에 의존하는 경우 적절히 파싱해야 합니다.

Android 10을 타겟팅하는 앱은 ashmem(/dev/ashmem)을 직접 사용할 수 없으므로 NDK의 ASharedMemory 클래스를 통해 공유 메모리에 액세스해야 합니다. 또한 앱에서 기존 ashmem 파일 설명어에 직접 IOCTL을 실행할 수 없으며 대신에 NDK의 ASharedMemory 클래스 또는 Android 자바 API를 사용하여 공유 메모리 영역을 생성해야 합니다. 이러한 변경으로 공유 메모리로 작업할 때 보안과 견고성이 강화되어 Android의 전반적인 성능과 보안이 향상되었습니다.

앱 홈 디렉터리의 실행 권한이 삭제됨

Android 10을 타겟팅하는 신뢰할 수 없는 앱은 앱의 홈 디렉터리에 있는 파일에서 exec()를 호출할 수 없습니다. 이처럼 쓰기 가능한 앱 홈 디렉터리에서 파일을 실행하는 것은 W^X 위반입니다. 앱에서는 앱의 APK 파일에 삽입된 바이너리 코드만 로드해야 합니다.

또한 Android 10을 타겟팅하는 앱은 dlopen()으로 열린 파일에서 메모리 내 실행 코드를 수정할 수 없습니다. 여기에는 텍스트가 재배치된 모든 공유 개체(.so) 파일이 포함됩니다.

시스템 생성 OAT 파일만 허용하는 Android 런타임

Android 런타임(ART)은 더 이상 애플리케이션 프로세스에서 dex2oat을 호출하지 않습니다. 즉, ART는 시스템에서 생성된 OAT 파일만 허용합니다.

ART의 AOT 정확성 강화

이전에서 Android 런타임(ART)에서 수행되는 AOT(Ahead-of-Time) 컴파일로 인해 컴파일 시간과 런타임의 클래스 경로 환경이 동일하지 않을 경우 런타임 충돌이 발생할 수 있습니다. Android 10 이상에서는 이러한 환경이 항상 동일해야 하며, 그 결과 동작이 다음과 같이 변경됩니다.

  • 맞춤형 클래스 로더(dalvik.system 패키지의 클래스 로더와 달리 앱에 의해 작성된 클래스 로더)는 AOT로 컴파일되지 않습니다. 이는 ART가 런타임에 맞춤 클래스 조회 구현에 대해 알 수 없기 때문입니다.
  • 보조 dex 파일(기본 APK에 없는 앱에 의해 수동으로 로드되는 dex 파일)은 이제 백그라운드에서 AOT로 컴파일됩니다. 이는 컴파일을 처음 사용하는 비용이 너무 비싸서 실행 전에 원치 않는 지연 시간이 발생할 수 있기 때문입니다. 앱의 경우 분할을 채택하고 보조 dex 파일에서 벗어나는 것이 좋습니다.
  • Android의 공유 라이브러리(Android manifest의 <library> 및 <uses-library> 항목)는 이전 버전의 플랫폼에서 사용된 것과 다른 클래스 로더 계층 구조를 사용하여 구현됩니다.

전체 화면 인텐트에 대한 권한 변경

Android 10 이상을 타겟팅하고 전체 화면 인텐트의 알림을 사용하는 앱은 앱의 manifest 파일에서 USE_FULL_SCREEN_INTENT 권한을 요청해야 합니다. 이는 정상적인 권한이므로 시스템은 요청 앱에 자동으로 권한을 부여합니다.

Android 10 이상을 타겟팅하는 앱이 필요한 권한을 요청하지 않고 전체 화면 인텐트의 알림을 만들려고 시도하면 시스템은 전체 화면 인텐트를 무시하고 다음 로그 메시지를 출력합니다.

    Package your-package-name: Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission
    

폴더블 지원

Android 10은 폴더블 및 큰 화면 기기를 지원하도록 변경되었습니다.

앱이 Android 10에서 실행될 때 onResume()onPause() 메서드는 다른 방식으로 작동합니다. 멀티 윈도우 또는 다중 디스플레이 모드에서 여러 앱이 동시에 표시되는 경우 공개 스택의 모든 포커스 가능 주요 활동이 재개된 상태이지만 이 중에서 실제로 포커스가 있는 것은 '최상위 재개' 활동 하나뿐입니다. Android 10 이전 버전에서 실행하면 시스템에서 한 번에 하나의 활동만 다시 시작할 수 있고 다른 모든 공개 활동은 일시중지됩니다.

'포커스'를 '최상위 재개' 활동과 혼동하지 마세요. 시스템에서는 z-order에 근거하여 활동에 우선순위를 지정함으로써 사용자가 마지막으로 상호작용한 활동에 더 높은 우선순위를 부여합니다. 활동은 상위 재개될 수 있지만 포커스가 없습니다(예: 알림 창이 확장된 경우).

Android 10(API 레벨 29) 이상에서는 onTopResumedActivityChanged() 콜백을 구독하여 활동이 최상위 재개 지위를 획득하거나 잃을 때 알림을 받을 수 있습니다. 최상위 재개 지위는 Android 10 이전의 재개된 상태와 동일하며 앱이 다른 앱과 공유해야 할 독점 또는 싱글턴 리소스를 사용하는 경우 유용한 힌트가 될 수 있습니다.

resizeableActivity 매니페스트 속성의 동작도 변경되었습니다. 앱이 Android 10(API 레벨 29) 이상에서 resizeableActivity=false를 설정하면 사용 가능한 화면 크기가 변경되거나 앱이 한 화면에서 다른 화면으로 이동하는 경우 호환 모드로 전환될 수 있습니다.

앱은 Android 10에 도입되어 앱이 지원하는 화면 비율을 표시하는 android:minAspectRatio 속성을 사용할 수 있습니다.

버전 3.5부터 Android 스튜디오의 에뮬레이터 도구에는 더 큰 화면에서 코드를 테스트하기 위한 7.3" 및 8" 가상 기기가 포함됩니다.

자세한 내용은 폴더블용 앱 빌드를 참조하십시오.

java.io.FileChannel.map() 변경사항

Android 10부터 truncate()를 사용하여 크기를 변경할 수 없는 /dev/zero와 같은 비표준 파일에서는 FileChannel.map()이 지원되지 않습니다. Android의 이전 버전은 truncate()에 의해 반환된 오류를 표시하지 않았지만 Android 10은 IOException을 표시합니다. 이전 동작이 필요하면 네이티브 코드를 사용해야 합니다.