비 SDK 인터페이스 제한사항

Android 9(API 수준 28)부터 플랫폼에서는 앱에서 사용할 수 있는 비 SDK 인터페이스가 제한되어 있습니다. 이러한 제한사항은 앱에서 비 SDK 인터페이스를 참조하거나 리플렉션 또는 JNI를 사용해 비 SDK 인터페이스의 핸들을 가져오려고 시도할 때마다 적용됩니다. 이 제한사항은 사용자와 개발자의 환경을 개선하고 사용자가 겪는 비정상 종료의 위험과 개발자가 급하게 새로 출시해야 하는 위험을 줄이기 위해 마련되었습니다. 이러한 결정에 관한 자세한 내용은 비 SDK 인터페이스 사용을 줄여 안정성 향상을 참고하세요.

SDK와 비 SDK 인터페이스의 구분

일반적으로 공개 SDK 인터페이스는 Android 프레임워크 패키지 색인에 문서화되어 있습니다. 비 SDK 인터페이스 처리는 API별 구현 세부정보이므로 이러한 인터페이스는 별도의 공지 없이 변경될 수 있습니다.

비정상 종료나 예기치 않은 동작을 방지하려면 앱에서 SDK의 클래스 중 공식적으로 문서화된 부분만 사용해야 합니다. 또한 리플렉션과 같은 메커니즘을 통해 클래스와 상호작용할 때 SDK에 등록되지 않은 메서드나 필드에 액세스하면 안 됩니다.

비 SDK API 목록

Android가 출시될 때마다 비 SDK 인터페이스가 추가로 제한됩니다. Google에서는 이러한 제한사항이 출시 워크플로에 영향을 줄 수 있음을 알고 있기 때문에 개발자에게 비 SDK 인터페이스 사용을 감지하는 도구, Google에 의견을 보낼 기회, 새로운 정책을 계획하고 조정할 시간을 제공하고자 합니다.

개발 워크플로에 비 SDK 제한사항이 미치는 영향을 최소화하기 위해 비 SDK 인터페이스는 타겟팅되는 API 수준에 따라 사용이 제한되는 정도를 정의하는 목록으로 나뉩니다. 다음 표에서는 이러한 각 목록을 설명합니다.

목록 설명
차단 목록(blacklist) 앱의 타겟 API 수준과 상관없이 사용할 수 없는 비 SDK 인터페이스입니다. 앱에서 이러한 인터페이스 중 하나에 액세스하려고 하면 시스템에 오류가 발생합니다.
조건부로 차단됨(greylist-max-x)

Android 9(API 수준 28)부터 각 API 수준에는 앱에서 해당 API 수준을 타겟팅할 때 제한되는 비 SDK 인터페이스가 포함됩니다.

이러한 목록은 앱이 더 이상 목록에 포함된 비 SDK 인터페이스에 액세스할 수 없게 되기 전에 타겟팅할 수 있는 최대 API 수준(max-target-x)으로 라벨이 지정됩니다. 예를 들어, Android Pie에서 차단되지 않았지만 이제 Android 10에서 차단된 비 SDK 인터페이스는 max-target-p(greylist-max-p) 목록의 일부입니다. 여기서 'p'는 Pie 또는 Android 9(API 수준 28)을 의미합니다.

앱이 타겟 API 수준에서 제한된 인터페이스에 액세스하려고 시도하면 시스템은 API가 차단 목록에 포함된 것처럼 작동합니다.

지원되지 않음(greylist) 현재 제한되지 않았으며 앱에서 사용할 수 있는 비 SDK 인터페이스입니다. 그러나, 이러한 인터페이스는 지원되지 않으며 예고 없이 변경될 수 있습니다. max-target-x 목록에 있는 향후 Android 버전에서 이러한 인터페이스가 조건부로 차단될 수 있습니다.
SDK(whitelist) 자유롭게 사용할 수 있으며 공식 문서화된 Android 프레임워크 패키지 색인의 일부로 지원되는 인터페이스입니다.

현재 앱의 타겟 API 수준에 따라 일부 비 SDK 인터페이스를 사용할 수 있지만, 비 SDK 메서드나 필드를 사용하면 앱이 중단될 위험이 커집니다. 앱에서 비 SDK 인터페이스를 사용하는 경우 SDK 인터페이스나 다른 대안으로 이전을 계획해야 합니다. 앱 기능을 구현하기 위해 비 SDK 인터페이스를 사용하는 것 외에 방법을 찾을 수 없다면 새 공개 API를 요청해야 합니다.

인터페이스가 속한 목록 확인

비 SDK 인터페이스의 목록은 플랫폼의 일부로 빌드됩니다. 각 Android 버전에 관한 자세한 내용은 아래 섹션을 참고하세요.

Android 12(개발자 프리뷰)

Android 12의 경우 모든 비 SDK 인터페이스 및 그에 대응하는 목록을 설명하는 다음 파일을 다운로드할 수 있습니다.

파일: hiddenapi-flags.csv

SHA-256 체크섬: 8109174e30a422f495e6239ff2a5d9e650a065f845fb87bbc769b0f26ceb7e44

Android 12에서 조건부로 차단된 API의 대안인 추천 공개 API를 포함한 Android 12의 비 SDK API 목록 변경사항에 관한 자세한 내용은 Android 12의 변경사항 목록을 참고하세요.

Android 11

Android 11(API 수준 30)의 경우 모든 비 SDK 인터페이스 및 그에 대응하는 목록을 설명하는 다음 파일을 다운로드할 수 있습니다.

파일: hiddenapi-flags.csv

SHA-256 체크섬: a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56

Android 11에서 조건부로 차단된 API의 대안인 추천 공개 API를 포함한 Android 11의 비 SDK API 목록 변경사항에 관한 자세한 내용은 Android 11의 변경사항 목록을 참고하세요.

Android 10

Android 10(API 수준 29)의 경우 모든 비 SDK 인터페이스 및 해당하는 목록을 설명하는 다음 파일을 다운로드할 수 있습니다.

파일: hiddenapi-flags.csv

SHA-256 체크섬: f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb

Android 10에서 조건부로 차단된 API의 대안인 추천 공개 API를 포함한 Android 10의 비 SDK API 목록 변경사항에 관한 자세한 내용은 Android 10의 변경사항 목록을 참고하세요.

Android 9

Android 9(API 수준 28)의 경우 텍스트 파일 hiddenapi-light-greylist.txt에 제한되지 않은(그레이리스트) 비 SDK API 목록이 포함되어 있습니다.

차단 목록(blacklist) 및 조건부로 차단된 API 목록(다크그레이리스트)은 빌드 시간에 파생됩니다.

AOSP에서 목록 생성

AOSP로 작업할 때 모든 비 SDK 인터페이스 및 해당하는 목록이 포함된 hiddenapi-flags.csv 파일을 생성할 수 있습니다. 그러려면 AOSP 소스를 다운로드한 후 다음 명령어를 실행합니다.

m out/soong/hiddenapi/hiddenapi-flags.csv

그러면 다음 위치에서 파일을 찾을 수 있습니다.

out/soong/hiddenapi/hiddenapi-flags.csv

제한된 비 SDK 인터페이스에 액세스할 때 예상되는 동작

다음 표는 앱에서 차단 목록에 포함된 비 SDK 인터페이스에 액세스하려고 할 때 예상되는 동작을 설명합니다.

액세스 수단 결과
필드를 참조하는 Dalvik 명령어 NoSuchFieldError 발생
메서드를 참조하는 Dalvik 명령어 NoSuchMethodError 발생
Class.getDeclaredField() 또는 Class.getField()를 통한 리플렉션 NoSuchFieldException 발생
Class.getMethod() Class.getDeclaredMethod()를 통한 리플렉션 NoSuchMethodException 발생
Class.getFields() Class.getDeclaredFields()를 통한 리플렉션 결과에 비 SDK 구성원 없음
Class.getDeclaredMethods(), Class.getMethods()를 통한 리플렉션 결과에 비 SDK 구성원 없음
env->GetFieldID()를 통한 JNI NULL 반환, NoSuchFieldError 발생
env->GetMethodID()를 통한 JNI NULL 반환, NoSuchMethodError 발생

앱의 비 SDK 인터페이스 테스트

앱의 비 SDK 인터페이스 테스트에 사용할 수 있는 방법에는 여러 가지가 있습니다.

디버그 가능한 앱을 사용하여 테스트

Android 9(API 수준 28) 이상을 실행하는 기기나 에뮬레이터에서 디버그 가능한 앱을 빌드하고 실행하여 비 SDK 인터페이스를 테스트할 수 있습니다. 사용 중인 기기나 에뮬레이터가 앱의 타겟 API 수준과 일치하는지 확인하세요.

앱에서 테스트를 실행하는 동안 앱에서 특정 비 SDK 인터페이스에 액세스하는 경우 시스템에서 로그 메시지를 출력합니다. 앱의 로그 메시지에서 다음 세부정보를 찾을 수 있습니다.

  • 선언하는 클래스, 이름, 유형(Android 런타임에서 사용하는 형식)
  • 액세스 수단: 연결, 리플렉션 또는 JNI를 통해
  • 비 SDK 인터페이스가 속한 목록

adb logcat을 사용해 이 로그 메시지에 액세스할 수 있습니다. 이 메시지는 실행 중인 앱의 PID 아래에 표시됩니다. 예를 들어 로그의 항목은 다음과 같습니다.

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)

StrictMode API를 사용하여 테스트

StrictMode API를 사용하여 비 SDK 인터페이스를 테스트할 수도 있습니다. detectNonSdkApiUsage 메서드를 사용하여 이 API를 사용 설정합니다. StrictMode API를 사용 설정한 후에는 맞춤 처리를 구현할 수 있는 penaltyListener를 사용하여 비 SDK 인터페이스의 각 사용에 관한 콜백을 수신할 수 있습니다. 콜백에 제공된 Violation 객체는 Throwable에서 파생되며 포함된 스택 트레이스에서 사용 컨텍스트를 제공합니다.

veridex 도구를 사용하여 테스트

APK에서 정적 분석 도구인 veridex를 실행할 수도 있습니다. veridex 도구는 타사 라이브러리를 비롯한 APK의 전체 코드베이스를 검사한 후 발견되는 모든 비 SDK 인터페이스 사용을 보고합니다.

veridex 도구의 한계는 다음과 같습니다.

  • JNI를 통한 호출은 감지할 수 없습니다.
  • 리플렉션을 통한 호출의 경우 일부만 감지할 수 있습니다.
  • 비활성 코드 경로 분석이 API 수준 검사로 제한됩니다.
  • SSE4.2 및 POPCNT 명령어를 지원하는 머신에서만 실행할 수 있습니다.

Windows

네이티브 Windows 바이너리는 제공되지 않지만 Linux용 Windows 하위 시스템(WSL)을 사용하여 Linux 바이너리를 실행함으로써 Windows에서 veridex 도구를 실행할 수 있습니다. 이 섹션의 단계를 따르기 전에 WSL을 설치하고 Linux 배포판으로 Ubuntu를 선택합니다.

Ubuntu가 설치되면 Ubuntu 터미널을 실행한 후 다음 단계를 따르세요.

  1. Android 런타임 사전 빌드 저장소에서 veridex 도구를 다운로드합니다.
  2. appcompat.tar.gz 파일의 콘텐츠를 추출합니다.
  3. 추출된 폴더에서 veridex-linux.zip 파일을 찾아 압축을 풉니다.
  4. 압축이 풀린 폴더로 이동한 후 다음 명령어를 실행합니다. 여기서 your-app.apk는 테스트하려는 APK입니다.

    ./appcompat.sh --dex-file=your-app.apk
    

macOS

macOS에서 veridex 도구를 실행하려면 다음 단계를 따르세요.

  1. Android 런타임 사전 빌드 저장소에서 veridex 도구를 다운로드합니다.
  2. appcompat.tar.gz 파일의 콘텐츠를 추출합니다.
  3. 추출된 폴더에서 veridex-mac.zip 파일을 찾아 압축을 풉니다.
  4. 압축이 풀린 폴더로 이동한 후 다음 명령어를 실행합니다. 여기서 /path-from-root/your-app.apk는 테스트하려는 APK의 경로(시스템의 루트 디렉터리부터 시작됨)입니다.

    ./appcompat.sh --dex-file=/path-from-root/your-app.apk
    

Linux

Linux에서 veridex 도구를 실행하려면 다음 단계를 따르세요.

  1. Android 런타임 사전 빌드 저장소에서 veridex 도구를 다운로드합니다.
  2. appcompat.tar.gz 파일의 콘텐츠를 추출합니다.
  3. 추출된 폴더에서 veridex-linux.zip 파일을 찾아 압축을 풉니다.
  4. 압축이 풀린 폴더로 이동한 후 다음 명령어를 실행합니다. 여기서 your-app.apk는 테스트하려는 APK입니다.

    ./appcompat.sh --dex-file=your-app.apk
    

Android 스튜디오 린트 도구를 사용하여 테스트

Android 스튜디오에서 앱을 빌드하면 린트 도구가 잠재적인 문제가 있는지 코드를 검사합니다. 앱에서 비 SDK 인터페이스를 사용하는 경우 인터페이스가 속한 목록에 따라 빌드 오류 또는 경고가 표시될 수 있습니다.

명령줄에서 린트 도구를 실행하거나 특정 프로젝트, 폴더, 파일에서 직접 검사를 실행할 수도 있습니다.

Play Console을 이용하여 테스트

앱을 Play Console의 테스트 트랙에 업로드하면 잠재적인 문제가 있는지 자동으로 테스트가 실행되며 사전 출시 보고서가 생성됩니다. 앱에서 비 SDK 인터페이스를 사용하는 경우 인터페이스가 속한 목록에 따라 사전 출시 보고서에 오류 또는 경고가 표시됩니다.

자세한 내용은 사전 출시 보고서를 통해 문제 확인하기에서 Android 호환성 섹션을 참조하세요.

새 공개 API 요청

앱 기능을 구현하기 위해 비 SDK 인터페이스를 사용하는 것 외에 방법을 찾을 수 없는 경우에는 Issue Tracker에서 기능 요청을 생성하여 새 공개 API를 요청할 수 있습니다.

기능을 요청할 때는 다음 정보를 제공하세요.

  • 현재 사용 중인 그레이리스트 API(Accessing hidden ... logcat 메시지에 표시되는 전체 설명어 포함)
  • 이 API를 사용해야 하는 이유(낮은 수준의 세부정보뿐 아니라 API가 필요한 높은 수준의 기능에 관한 세부정보 포함)
  • 관련된 모든 공개 SDK API가 용도에 충분하지 않은 이유
  • 시도한 모든 대안과 대안이 효과가 없었던 이유

기능 요청에 이러한 세부정보를 제공하면 새 공개 API가 지원될 가능성이 높아집니다.

기타 문의

이 섹션에서는 개발자가 자주 묻는 기타 질문에 대한 일부 답변을 확인할 수 있습니다.

일반적인 질문

Google에서는 어떻게 Issue Tracker를 통해 모든 앱의 요구사항이 파악된다고 확신할 수 있나요?

Google에서는 다음 방법으로 보완된 앱의 정적 분석을 통해 Android 9(API 수준 28)의 초기 목록을 만들었습니다.

  • 상위 Play 및 Play 이외의 앱을 수동으로 테스트
  • 내부 보고서
  • 내부 사용자로부터 자동으로 데이터 수집
  • 개발자 미리보기 보고서
  • 거짓양성을 더 포함하도록 보수적으로 설계된 추가 정적 분석

새로 출시되는 각 목록을 평가할 때는 문제 트래커를 통해 API 사용뿐 아니라 개발자 의견도 고려합니다.

비 SDK 인터페이스에 액세스할 수 있도록 설정하려면 어떻게 해야 하나요?

다음 adb 명령어를 사용해 API 시행 정책을 변경하여 개발 기기에서 비 SDK 인터페이스에 액세스하도록 설정할 수 있습니다. 사용하는 명령어는 API 수준에 따라 다릅니다. 이러한 명령어를 사용하는 데는 루팅된 기기가 필요하지 않습니다.

Android 10(API 수준 29) 이상

액세스를 사용 설정하려면 다음 adb 명령어를 사용합니다.

adb shell settings put global hidden_api_policy  1

API 시행 정책을 기본 설정으로 재설정하려면 다음 명령을 사용합니다.

adb shell settings delete global hidden_api_policy
Android 9(API 수준 28)

액세스를 사용 설정하려면 다음 adb 명령어를 사용합니다.

adb shell settings put global hidden_api_policy_pre_p_apps  1
adb shell settings put global hidden_api_policy_p_apps 1

API 시행 정책을 기본 설정으로 재설정하려면 다음 명령어를 사용합니다.

adb shell settings delete global hidden_api_policy_pre_p_apps
adb shell settings delete global hidden_api_policy_p_apps

API 시행 정책의 정수는 다음 값 중 하나로 설정할 수 있습니다.

  • 0: 비 SDK 인터페이스의 모든 감지를 사용 중지합니다. 이 설정을 사용하면 비 SDK 인터페이스 사용에 관한 모든 로그 메시지가 사용 중지되고 StrictMode API를 사용하여 앱을 테스트할 수 없습니다. 이 설정은 사용하지 않는 것이 좋습니다.
  • 1: 모든 비 SDK 인터페이스에 액세스할 수 있지만 비 SDK 인터페이스를 사용하면 경고와 함께 로그 메시지가 인쇄됩니다. 이 설정을 사용하면 StrictMode API를 사용하여 앱을 테스트할 수 있습니다.
  • 2: 차단 목록에 속하거나 타겟 API 수준에서 조건부로 차단된 비 SDK 인터페이스의 사용이 금지됩니다.

비 SDK 인터페이스 목록에 관한 질문

비 SDK API 목록은 시스템 이미지의 어디에서 찾을 수 있나요?

비 SDK API 목록은 플랫폼 dex 파일의 필드 및 메서드 액세스 플래그 비트에 인코딩되어 있습니다. 시스템 이미지에 이러한 목록이 포함된 별도의 파일은 없습니다.

같은 Android 버전을 사용하는 다른 OEM 기기에서 비 SDK API 목록이 동일한가요?

OEM은 차단 목록(블랙리스트)에 자체 인터페이스를 추가할 수 있지만, AOSP 비 SDK API 목록에서 인터페이스를 삭제할 수는 없습니다. CDD는 이러한 변경을 금지하며 CTS 테스트는 Android 런타임이 목록을 적용하고 있는지 확인합니다.

네이티브 코드에 비 NDK 인터페이스 관련 제한사항이 있나요?

Android SDK에는 자바 인터페이스가 포함되어 있습니다. 플랫폼에서는 Android 7(API 수준 26)에서 네이티브 C/C++ 코드의 비 NDK 인터페이스에 대한 액세스를 제한하기 시작했습니다. 자세한 내용은 Android N에서 비공개 C/C++ 기호 제한사항으로 안정성 향상을 참조하세요.

dex2oat 또는 DEX 파일 조작을 제한할 계획이 있나요?

dex2oat 바이너리에 대한 액세스를 제한할 적극적인 계획은 없지만, DEX 파일 형식을 안정화하거나 Dalvik 실행 가능 형식에 공개적으로 지정된 부분을 넘어서는 공개 인터페이스로 만들지도 않을 것입니다. Google은 언제든 dex2oat 및 DEX 형식의 지정되지 않은 부분을 수정하거나 제거할 권리를 보유합니다. 또한 ODEX(OAT라고도 함), VDEX, CDEX 등 dex2oat에서 생성된 파생 파일은 모두 지정되지 않은 형식입니다.

중요한 타사 SDK(예: Obfuscator)에서 비 SDK 인터페이스 사용을 피할 수 없지만 향후 Android 버전과의 호환성 유지를 약속하는 경우 어떻게 하나요? 이 경우 Android에서 호환성 요구사항을 포기할 수 있나요?

Google에서는 SDK별로 호환성 요구사항을 포기할 계획이 없습니다. 현재 SDK 개발자가 지원되지 않는 목록(이전의 그레이리스트)의 인터페이스에 종속되는 방법으로만 호환성을 유지할 수 있다면 SDK 인터페이스 또는 다른 대안으로 이전할 계획을 수립해야 하며 비 SDK 인터페이스 사용의 대안을 찾을 수 없을 때마다 새 공개 API를 요청해야 합니다.

비 SDK 인터페이스 제한사항은 타사 앱뿐 아니라 시스템 및 자사 앱을 포함한 모든 앱에 적용되나요?

예, 하지만 플랫폼 키로 서명된 앱과 일부 시스템 이미지 앱은 제외됩니다. 이러한 예외는 시스템 이미지에 속한 앱(또는 업데이트된 시스템 이미지 앱)에만 적용됩니다. 이 목록은 LOCAL_PRIVATE_PLATFORM_APIS := true인 SDK API가 아닌 비공개 플랫폼 API를 대상으로 빌드된 앱에만 사용됩니다.