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를 사용하는 경우, NDK API의 일부분이 아닌 암호화 라이브러리에 대해 링크를 연결하지 마세요(예: libcrypto.solibssl.so). 이러한 라이브러리는 공개 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 객체는 개발자가 수정하거나 삭제할 권한이 없습니다.
  • 이전에는 앱이 기기에 강제로 특정 Wi-Fi 네트워크에 연결하도록 하는 경우, 즉 enableNetwork()disableAllOthers=true 설정으로 사용하면 기기가 셀룰러 데이터와 같은 다른 네트워크에서는 연결을 해제했습니다. 이 릴리스에서는 기기가 그러한 다른 네트워크에서 더 이상 연결을 해제하지 않습니다. 앱의 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_LOCAL을 명시적으로 사용하지 않는 dlopen(3) 호출은 영향을 받습니다(단, 앱이 RTLD_GLOBAL을 명시적으로 사용한 경우는 예외). 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 구성을 수정하거나 삭제할 수 있는 권한이 있습니다.
  • 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는 Work 프로필, 지원 레이어 등을 포함한 M 런타임 권한에 최적화되어 있습니다. 새로운 DevicePolicyManager 권한 API는 M 이전 앱에 영향을 미치지 않습니다.
    • 사용자가 ACTION_PROVISION_MANAGED_PROFILE 또는 ACTION_PROVISION_MANAGED_DEVICE 인텐트를 통해 시작된 설정 흐름의 동기화 부분에서 나가면 이제 시스템이 RESULT_CANCELED 결과 코드를 반환합니다.
  • 기타 API 변경사항:
    • 데이터 사용량: android.app.usage.NetworkUsageStats 클래스의 이름이 NetworkStats로 변경되었습니다.
  • 전체 설정 변경사항: