Android 6.0 변경 사항

Android 6.0 (API 수준 23)에는 새로운 기능 및 기능과 함께 다양한 시스템 변경사항 및 API 동작 변경사항이 포함되어 있습니다. 이 문서에서는 개발자가 이해하고 앱에서 고려해야 하는 몇 가지 주요 변경사항을 중점적으로 설명합니다.

이전에 Android용 앱을 게시한 적이 있다면 이러한 플랫폼 변경사항이 앱에 영향을 미친다는 점에 유의하세요.

런타임 권한

이 출시에서는 새로운 권한 모델을 소개합니다. 여기에서는 이제 사용자가 런타임에 직접 앱 권한을 관리할 수 있습니다. 이 모델은 사용자에게 개선된 가시성과 권한 제어 기능을 제공하는 동시에 앱 개발자를 위해 설치 및 자동 업데이트 프로세스를 간소화합니다. 사용자는 설치된 여러 앱에 대해 개별적으로 권한을 허용하거나 취소할 수 있습니다.

Android 6.0 (API 수준 23) 이상을 타겟팅하는 앱에서는 런타임에 권한을 확인하고 요청해야 합니다. 앱에 권한이 부여되었는지 확인하려면 새 checkSelfPermission() 메서드를 호출합니다. 권한을 요청하려면 새 requestPermissions() 메서드를 호출합니다. 앱이 Android 6.0 (API 수준 23)을 타겟팅하지 않더라도 새 권한 모델에서 앱을 테스트해야 합니다.

앱에서 새 권한 모델을 지원하는 방법에 관한 자세한 내용은 시스템 권한 작업을 참고하세요. 앱에 미치는 영향을 평가하는 방법에 관한 팁은 권한 사용 참고사항을 참고하세요.

잠자기 및 앱 대기

이 릴리스에는 유휴 상태의 기기 및 앱에 대한 새로운 절전 최적화 기능이 새롭게 추가되었습니다. 이러한 기능은 모든 앱에 영향을 미치므로 새로운 모드에서 앱을 테스트해야 합니다.

  • 잠자기: 사용자가 기기의 플러그를 뽑고 화면이 꺼진 상태로 일정 시간 동안 움직이지 않으면 기기는 잠자기 모드로 전환되어 시스템을 절전 모드로 유지하려고 합니다. 이 모드에서 기기는 정기적으로 잠시 동안 정상 작동을 재개하여 앱 동기화가 발생할 수 있고 대기 중인 작업을 시스템이 실행할 수 있도록 합니다.
  • 앱 대기: 앱 대기는 사용자가 활발하게 사용하지 않는 경우 시스템에서 앱이 유휴 상태라고 판단할 수 있게 해줍니다. 시스템은 사용자가 일정 시간 앱을 터치하지 않으면 이 결정을 내립니다. 기기의 플러그가 뽑히면 시스템은 네트워크 액세스를 사용 중지하고 유휴 상태로 간주되는 앱의 동기화와 작업을 정지합니다.

이러한 절전 변경사항에 관한 자세한 내용은 잠자기 및 앱 대기 최적화를 참고하세요.

Apache HTTP 클라이언트 제거

이 Android 6.0 릴리스에서는 Apache HTTP 클라이언트에 대한 지원이 제거되었습니다. 앱에서 이 클라이언트를 사용하고 Android 2.3 (API 수준 9) 이상을 타겟팅한다면 HttpURLConnection 클래스를 대신 사용하세요. 이 API는 투명한 압축 및 응답 캐싱을 통해 네트워크 사용량을 줄이고 전력 소모를 최소화하므로 더 효율적입니다. Apache HTTP API를 계속 사용하려면 먼저 build.gradle 파일에서 다음과 같은 컴파일 시간 종속 항목을 선언해야 합니다.

android {
    useLibrary 'org.apache.http.legacy'
}

BoringSSL

Android는 OpenSSL에서 BoringSSL 라이브러리로 전환됩니다. 앱에서 Android NDK를 사용하는 경우 libcrypto.solibssl.so와 같이 NDK API에 속하지 않는 암호화 라이브러리에 연결하지 마세요. 이러한 라이브러리는 공개 API가 아니며 여러 버전과 기기에서 예고 없이 변경되거나 중단될 수 있습니다. 또한 스스로를 보안 취약점에 노출시킬 수도 있습니다. 대신 네이티브 코드를 수정하여 JNI를 통해 Java 암호화 API를 호출하거나 원하는 암호화 라이브러리에 정적으로 연결하도록 하세요.

하드웨어 식별자 액세스

사용자에게 향상된 데이터 보호 기능을 제공하기 위해 이 버전부터 Android에서는 Wi-Fi 및 블루투스 API를 사용하는 앱의 기기 로컬 하드웨어 식별자에 대한 프로그래매틱 방식의 액세스를 삭제합니다. WifiInfo.getMacAddress()BluetoothAdapter.getAddress() 메서드는 이제 02:00:00:00:00:00의 상수 값을 반환합니다.

블루투스 및 Wi-Fi 검색을 통해 근처 외부 기기의 하드웨어 식별자에 액세스하려면 이제 앱에 ACCESS_FINE_LOCATION 또는 ACCESS_COARSE_LOCATION 권한이 있어야 합니다.

참고: Android 6.0 (API 수준 23)을 실행하는 기기가 백그라운드 Wi-Fi 또는 블루투스 검색을 시작하면 이 작업이 외부 기기에 무작위 MAC 주소에서 발생하는 것으로 표시됩니다.

알림

이 출시에서는 Notification.setLatestEventInfo() 메서드가 삭제되었습니다. 대신 Notification.Builder 클래스를 사용하여 알림을 구성합니다. 알림을 반복적으로 업데이트하려면 Notification.Builder 인스턴스를 재사용합니다. build() 메서드를 호출하여 업데이트된 Notification 인스턴스를 가져옵니다.

adb shell dumpsys notification 명령어가 더 이상 알림 텍스트를 출력하지 않습니다. 대신 adb shell dumpsys notification --noredact 명령어를 사용하여 알림 객체의 텍스트를 출력합니다.

AudioManager 변경 사항

볼륨을 직접 설정하거나 AudioManager 클래스를 통해 특정 스트림을 음소거하는 기능은 더 이상 지원되지 않습니다. setStreamSolo() 메서드는 지원 중단되었으므로 requestAudioFocus() 메서드를 대신 호출해야 합니다. 마찬가지로 setStreamMute() 메서드도 지원 중단되었습니다. 대신 adjustStreamVolume() 메서드를 호출하고 방향 값 ADJUST_MUTE 또는 ADJUST_UNMUTE를 전달하세요.

텍스트 선택

플로팅 툴바 내의 새로운 텍스트 선택 기능을 보여주는 화면

사용자가 앱에서 텍스트를 선택하면 이제 플로팅 툴바잘라내기, 복사, 붙여넣기와 같은 텍스트 선택 작업을 표시할 수 있습니다. 사용자 상호작용 구현은 개별 뷰에 상황별 작업 모드 사용 설정에 설명된 대로 상황별 작업 모음의 구현과 유사합니다.

텍스트 선택을 위해 플로팅 툴바를 구현하려면 기존 앱에서 다음과 같이 변경합니다.

  1. View 또는 Activity 객체에서 ActionMode 호출을 startActionMode(Callback)에서 startActionMode(Callback, ActionMode.TYPE_FLOATING)로 변경합니다.
  2. 기존 ActionMode.Callback 구현을 가져와서 대신 ActionMode.Callback2를 확장하도록 합니다.
  3. onGetContentRect() 메서드를 재정의하여 뷰에서 콘텐츠 Rect 객체(예: 텍스트 선택 직사각형)의 좌표를 제공합니다.
  4. 직사각형 위치 지정이 더 이상 유효하지 않고 무효화할 요소가 이것뿐인 경우 invalidateContentRect() 메서드를 호출합니다.

Android 지원 라이브러리 버전 22.2를 사용하는 경우 플로팅 툴바는 이전 버전과 호환되지 않으며 appcompat이 기본적으로 ActionMode 객체를 제어합니다. 이 경우, 부동 툴바가 표시되지 않도록 차단됩니다. AppCompatActivity에서 ActionMode 지원을 사용 설정하려면 getDelegate()를 호출한 다음 반환된 AppCompatDelegate 객체에서 setHandleNativeActionModesEnabled()을 호출하고 입력 매개변수를 false로 설정합니다. 이 호출은 ActionMode 객체의 제어권을 프레임워크에 반환합니다. Android 6.0 (API 수준 23)을 실행하는 기기에서는 프레임워크가 ActionBar 또는 플로팅 툴바 모드를 지원할 수 있는 반면, Android 5.1 (API 수준 22) 이하를 실행하는 기기에서는 ActionBar 모드만 지원됩니다.

브라우저 책갈피 변경 사항

이 릴리스에서는 전역 책갈피 지원이 제거되었습니다. 이제 android.provider.Browser.getAllBookmarks()android.provider.Browser.saveBookmark() 메서드가 삭제되었습니다. 마찬가지로 READ_HISTORY_BOOKMARKSWRITE_HISTORY_BOOKMARKS 권한도 삭제됩니다. 앱이 Android 6.0 (API 수준 23) 이상을 타겟팅한다면 전역 제공자에서 북마크에 액세스하거나 북마크 권한을 사용하지 마세요. 대신 앱은 내부적으로 북마크 데이터를 저장해야 합니다.

Android Keystore 변경 사항

이 출시에서는 Android 키 저장소 제공업체가 더 이상 DSA를 지원하지 않습니다. ECDSA는 여전히 지원됩니다.

저장 데이터 암호화가 필요하지 않은 키는 보안 잠금 화면이 사용 중지되거나 재설정될 때 (예: 사용자 또는 기기 관리자에 의해) 더 이상 삭제되지 않습니다. 저장 데이터 암호화가 필요한 키는 이러한 이벤트 중에 삭제됩니다.

Wi-Fi 및 네트워킹 변경 사항

이 릴리스에서는 Wi-Fi와 네트워킹 API에 다음과 같은 동작 변경 사항이 추가되었습니다.

  • 이제 앱에서 WifiConfiguration 객체를 만든 경우에만 이 객체의 상태를 변경할 수 있습니다. 사용자 또는 다른 앱에서 만든 WifiConfiguration 객체는 수정하거나 삭제할 권한이 없습니다.
  • 이전에는 앱이 disableAllOthers=true 설정으로 enableNetwork()를 사용하여 기기를 특정 Wi-Fi 네트워크에 연결하도록 강제하면 기기가 모바일 데이터와 같은 다른 네트워크에서 연결 해제되었습니다. 이 릴리스에서는 기기가 그러한 다른 네트워크에서 더 이상 연결을 해제하지 않습니다. 앱의 targetSdkVersion“20” 이하인 경우 선택한 Wi-Fi 네트워크에 고정됩니다. 앱의 targetSdkVersion“21” 이상이면 멀티네트워크 API (예: openConnection(), bindSocket(), 새 bindProcessToNetwork() 메서드)를 사용하여 네트워크 트래픽이 선택한 네트워크에서 전송되도록 합니다.

카메라 서비스 변경 사항

이 버전에서는 카메라 서비스의 공유 리소스에 액세스하는 모델이 이전의 '선착순' 액세스 모델에서 우선순위가 높은 프로세스가 선호되는 액세스 모델로 변경되었습니다. 서비스 동작에 대한 변경 사항은 다음과 같습니다.

  • 카메라 기기 열기 및 구성을 포함한 카메라 하위 시스템 리소스에 대한 액세스는 클라이언트 애플리케이션 프로세스의 '우선순위'를 기반으로 부여됩니다. 사용자에게 표시되는 활동 또는 포그라운드 활동이 있는 애플리케이션 프로세스에는 일반적으로 더 높은 우선순위가 부여되므로 카메라 리소스 획득 및 사용에 더 신뢰할 수 있습니다.
  • 우선순위가 낮은 앱의 활성 카메라 클라이언트는 우선순위가 더 높은 애플리케이션이 카메라를 사용하려고 하면 '제거'될 수 있습니다. 지원 중단된 Camera API에서는 이로 인해 제거된 클라이언트를 위해 onError()가 호출됩니다. Camera2 API에서는 제거된 클라이언트에 대해 onDisconnected()가 호출됩니다.
  • 적절한 카메라 하드웨어가 있는 기기에서는 별도의 애플리케이션 프로세스가 독립적으로 열고 별도의 카메라 기기를 동시에 사용할 수 있습니다. 그러나 동시 액세스가 열려 있는 카메라 기기의 성능이나 기능이 크게 저하되는 다중 프로세스 사용 사례를 이제 카메라 서비스에서 감지하여 허용하지 않습니다. 이 변경으로 인해, 다른 앱이 동일한 카메라 기기에 직접 액세스하려고 시도하지 않더라도 우선순위가 낮은 클라이언트의 '제거'가 발생할 수 있습니다.
  • 현재 사용자를 변경하면 이전 사용자 계정이 소유한 앱의 활성 카메라 클라이언트가 제거됩니다. 카메라에 대한 액세스는 현재 기기 사용자가 소유한 사용자 프로필로만 제한됩니다. 실제로 이는 예를 들어 사용자가 다른 계정으로 전환한 경우 '게스트' 계정이 카메라 하위 시스템을 사용하는 실행 중인 프로세스에서 나갈 수 없음을 의미합니다.

런타임

이제 ART 런타임이 newInstance() 메서드의 액세스 규칙을 올바르게 구현합니다. 이 변경사항은 이전 버전에서 Dalvik이 액세스 규칙을 잘못 확인하는 문제를 해결합니다. 앱에서 newInstance() 메서드를 사용하고 액세스 확인을 재정의하려면 입력 매개변수를 true로 설정하여 setAccessible() 메서드를 호출합니다. 앱에서 v7 appcompat 라이브러리 또는 v7 recyclerview 라이브러리를 사용하는 경우 이러한 라이브러리의 최신 버전을 사용하도록 앱을 업데이트해야 합니다. 그렇지 않은 경우 XML에서 참조되는 모든 맞춤 클래스가 클래스 생성자에 액세스할 수 있도록 업데이트되어야 합니다.

이 릴리스에서는 동적 링커의 동작을 업데이트합니다. 동적 링커는 이제 라이브러리의 soname과 라이브러리 경로( 공개 버그 6670) 간의 차이점을 이해하고 soname별 검색이 구현됩니다. 이전에 작동했지만 DT_NEEDED 항목(일반적으로 빌드 머신의 파일 시스템에 있는 절대 경로)이 있는 앱은 로드될 때 실패할 수 있습니다.

이제 dlopen(3) RTLD_LOCAL 플래그가 올바르게 구현되었습니다. RTLD_LOCAL가 기본값이므로 앱에서 명시적으로 RTLD_GLOBAL를 사용하지 않는 한 RTLD_LOCAL를 명시적으로 사용하지 않은 dlopen(3) 호출은 영향을 받습니다. RTLD_LOCAL를 사용하면 나중에 dlopen(3) 호출로 로드된 라이브러리에서 기호를 사용할 수 없습니다(DT_NEEDED 항목에 의해 참조되는 것과는 다름).

이전 버전의 Android에서는 앱이 시스템에 텍스트 재배치가 포함된 공유 라이브러리를 로드하도록 요청한 경우 시스템에서 경고를 표시했지만 라이브러리 로드는 허용했습니다. 이 버전부터는 앱의 타겟 SDK 버전이 23 이상이면 시스템에서 이 라이브러리를 거부합니다. 라이브러리 로드에 실패했는지 감지할 수 있도록 앱은 dlopen(3) 실패를 기록하고 dlerror(3) 호출이 반환하는 문제 설명 텍스트를 포함해야 합니다. 텍스트 재배치 처리에 관한 자세한 내용은 이 가이드를 참고하세요.

APK 유효성 검사

이제 플랫폼이 APK에 대해 좀 더 엄격한 유효성 검사를 수행합니다. APK는 파일이 매니페스트에서 선언되었지만 APK 자체에는 없는 경우 손상된 것으로 간주됩니다. 콘텐츠가 삭제되면 APK를 다시 서명해야 합니다.

USB 연결

이제 USB 포트를 통한 기기 연결은 기본적으로 충전 전용 모드로 설정됩니다. USB 연결을 통해 기기와 콘텐츠에 액세스하려면 사용자는 이러한 상호작용에 관한 권한을 명시적으로 부여해야 합니다. 앱이 USB 포트를 통한 기기와의 상호작용을 지원하는 경우 상호작용이 명시적으로 사용 설정되어야 한다는 점을 고려하세요.

Android for Work 변경 사항

이 릴리스에는 Android for Work에 대해 다음과 같은 동작 변경 사항이 포함되어 있습니다.

  • 개인적 컨텍스트에서의 직장 연락처. 이제 사용자가 이전 통화를 볼 때 Google 다이얼러 통화 기록에 직장 연락처가 표시됩니다. setCrossProfileCallerIdDisabled()true로 설정하면 Google 다이얼러 통화 기록에서 직장 프로필 연락처가 숨겨집니다. setBluetoothContactSharingDisabled()false로 설정한 경우에만 블루투스를 통해 기기에 직장 연락처를 개인 연락처와 함께 표시할 수 있습니다. 기본적으로 true로 설정되어 있습니다.
  • Wi-Fi 구성 삭제: 이제 프로필 소유자가 추가한 Wi-Fi 구성(예: addNetwork() 메서드 호출)은 직장 프로필이 삭제되면 삭제됩니다.
  • Wi-Fi 구성 잠금: WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN이 0이 아닌 경우 활성 기기 소유자가 만든 Wi-Fi 구성을 더 이상 사용자가 수정하거나 삭제할 수 없습니다. 사용자는 여전히 본인의 Wi-Fi 구성을 생성하고 수정할 수 있습니다. 활성 기기 소유자는 직접 생성하지 않은 Wi-Fi 구성을 포함하여 모든 Wi-Fi 구성을 수정하거나 삭제할 수 있는 권한이 있습니다.
  • Google 계정 추가를 통해 기기 정책 컨트롤러 다운로드: 이제 기기 정책 컨트롤러 (DPC) 앱을 통해 관리해야 하는 Google 계정이 관리 컨텍스트 외부의 기기에 추가되면 계정 추가 흐름에서 사용자에게 적절한 WPC를 설치하라는 메시지를 표시합니다. 이 동작은 초기 기기 설정 마법사에서 설정 > 계정을 통해 추가된 계정에도 적용됩니다.
  • 특정 DevicePolicyManager API 동작 변경사항:
    • setCameraDisabled() 메서드를 호출하면 호출하는 사용자의 카메라에만 영향을 미칩니다. 관리 프로필에서 호출하면 기본 사용자에서 실행 중인 카메라 앱에는 영향을 미치지 않습니다.
    • 또한 이제 setKeyguardDisabledFeatures() 메서드를 기기 소유자뿐만 아니라 프로필 소유자도 사용할 수 있습니다.
    • 프로필 소유자는 다음과 같은 키가드 제한사항을 설정할 수 있습니다.
    • DevicePolicyManager.createAndInitializeUser()DevicePolicyManager.createUser() 메서드가 지원 중단되었습니다.
    • 이제 setScreenCaptureDisabled() 메서드도 지정된 사용자의 앱이 포그라운드에 있으면 지원 구조를 차단합니다.
    • EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM의 기본값은 이제 SHA-256입니다. SHA-1은 이전 버전과의 호환성을 위해 계속 지원되지만 향후 삭제될 예정입니다. EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM는 이제 SHA-256만 허용합니다.
    • 이제 Android 6.0(API 레벨 23)에 있던 기기 이니셜라이저 API가 제거되었습니다.
    • EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS가 삭제되었으므로 NFC 범프 프로비저닝은 초기화 보호 기기를 프로그래매틱 방식으로 잠금 해제할 수 없습니다.
    • 이제 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE 추가 항목을 사용하여 관리 기기의 NFC 프로비저닝 중에 기기 소유자 앱에 데이터를 전달할 수 있습니다.
    • Android for Work API는 직장 프로필, 지원 레이어 등을 포함한 M 런타임 권한에 최적화되어 있습니다. 새로운 DevicePolicyManager 권한 API는 M 이전 앱에 영향을 미치지 않습니다.
    • 사용자가 ACTION_PROVISION_MANAGED_PROFILE 또는 ACTION_PROVISION_MANAGED_DEVICE 인텐트를 통해 시작된 설정 흐름의 동기식 부분에서 나가면 이제 시스템이 RESULT_CANCELED 결과 코드를 반환합니다.
  • 다른 API 변경사항:
    • 데이터 사용량: android.app.usage.NetworkUsageStats 클래스의 이름이 NetworkStats로 변경되었습니다.
  • 전체 설정 변경사항: