SDK 런타임의 이전 버전과의 호환성

이 문서에서는 개발자가 SDK 런타임으로 이전하는 데 도움이 되는 새로운 Jetpack 라이브러리를 제안합니다. 이전 Android 플랫폼 버전에서 SDK 런타임이 어떻게 지원(빌드에서 실행까지)되는지, 런타임 환경 개발자가 예상할 수 있는 차이점이나 제한사항을 설명합니다. 이 라이브러리를 사용하면 개발자가 SDK 런타임 지원 여부와 관계없이 기기에서 실행할 수 있는 기능이 포함된 단일 버전의 앱 또는 SDK를 만들 수 있습니다.

이전 버전과의 호환성은 다음 구성요소를 통해 달성할 수 있습니다.

  • Android Gradle 플러그인(AGP) + Bundletool: SDK 런타임을 APK에 번들로 묶어 SDK 런타임이 지원되지 않는 기기의 앱 변형을 빌드합니다.

  • SDK 런타임 클라이언트 라이브러리(androidx.privacysandbox.sdkruntime:sdkruntime-client): 앱 애셋에서 번들 SDK를 로드하고 SDK 런타임이 지원되지 않는 기기에서 SDK 런타임을 에뮬레이션합니다.

  • SDK 런타임 제공업체 라이브러리(androidx.privacysandbox.sdkruntime:sdkruntime-provider): SDK 런타임 클라이언트 라이브러리에서 로드할 수 있도록 SDK용 API를 제공합니다.

Bundletool을 사용한 SDK 전송

SDK 런타임이 지원되는 기기에서 SDK는 별도의 패키지로 제공되고 설치됩니다.

SDK 런타임 지원이 없는 플랫폼 버전을 지원하기 위해 Bundletool은 앱이 종속되는 모든 SDK를 포함하는 앱 APK 세트의 변형을 하나 이상 빌드합니다. 각 SDK는 별도의 APK 분할로 패키징됩니다. 또한 다음 변환이 실행됩니다.

  1. SDK 바이트 코드(DEX) 파일을 SDK 분할에 애셋으로 복사합니다.
  2. SDK Java 리소스를 SDK 분할에 애셋으로 복사합니다.
  3. SDK 리소스를 재매핑하여 앱 리소스와 병합합니다.
  4. SDK 런타임 클라이언트 라이브러리의 구성을 생성합니다.

SDK 런타임 클라이언트 라이브러리로 SDK 로드

SDK 런타임 클라이언트 라이브러리는 플랫폼 API와 유사한 API를 제공하지만 SDK 런타임 환경의 SDK와 변형 앱과 번들로 묶인 SDK를 모두 지원합니다.

SDK 런타임 클라이언트 라이브러리를 사용하려면 종속 항목 androidx.privacysandbox.sdkruntime:sdkruntime-client를 추가하고 SdkSandboxManager 대신 SdkSandboxManagerCompat를 사용하세요.

앱이 SDK를 로드하려고 하면 라이브러리는 먼저 SDK가 빌드 중에 앱과 번들로 묶였는지 확인합니다. 번들로 묶인 경우 라이브러리는 SDK 분할에서 SDK를 추출하여 앱 프로세스에 로드합니다. SDK가 앱과 번들로 묶이지 않은 경우 라이브러리는 SDK를 로드하도록 플랫폼 API를 위임합니다.

애셋에서 SDK 추출

앱이 번들 SDK를 로드하려고 하면 SDK 런타임 클라이언트 라이브러리는 SDK의 DEX 파일이 이미 기기 저장소(code_cache)에 추출되었는지 확인하고 추출되지 않은 경우 애셋에서 추출합니다.

라이브러리는 일반적으로 앱 설치 또는 업데이트 후에 한 번만 파일을 추출합니다.

사용 가능한 저장공간이 허용된 기준점(현재 100MB)보다 적고 DEX 파일이 추출되지 않은 경우 라이브러리는 지원되는 기기(API 27 이상)의 애셋에서 SDK를 직접 로드하려고 시도합니다. 따라서 메모리 사용량이 더 커집니다.

SDK 클래스용 클래스 로더

SDK와 앱 클래스 간의 충돌을 방지하기 위해 모든 SDK 클래스는 기본 앱 클래스 로더와 완전히 독립적인 별도의 클래스 로더를 사용하여 로드됩니다.

현재 SDK 런타임 설계에서는 앱과 SDK 간의 모든 통신이 바인더 IPC 호출을 사용하여 이루어집니다. 동일한 SDK 바인더 객체가 번들 SDK에 사용되며, 바인더 트랜잭션 직렬화를 사용하면 앱 개발자가 앱 측에서 SDK 바인더 객체를 SDK 바인더 인터페이스로 전송할 수 있습니다.

다른 내부 상호작용(예: SDK 초기화, SDK에 컨트롤러 API 제공 등)의 경우 라이브러리는 리플렉션 및 동적 프록시를 사용하여 여러 클래스 로더에서 작동합니다.

SDK 환경

SDKRuntime 제공업체 라이브러리는 SDK 개발자에게 API를 제공합니다. 이러한 API는 플랫폼 API와 비슷하지만 SDK 런타임 환경과 SDKRuntime 클라이언트 라이브러리에서 모두 SDK를 로드할 수 있습니다.

라이브러리 SDK를 사용하려면 androidx.privacysandbox.sdkruntime:sdkruntime-provider 종속 항목을 추가하고 SandboxedSdkProvider 대신 SandboxedSdkProviderCompat를 확장해야 합니다.

또한 compat 제공자가 SDK 런타임 환경에 로드될 수 있도록 하려면 SandboxedSdkProviderAdapter를 SDK 제공업체로 사용해야 합니다.

SdkSandboxControllerCompat는 SDK가 SDK 런타임에 로드될 때 플랫폼 API에 위임하거나 SDK가 번들 SDK로 로드될 때 SDKRuntime 클라이언트 라이브러리에 위임합니다.

번들 SDK의 경우 라이브러리는 SDK 런타임 환경과 유사한 동작을 에뮬레이션하는 방식으로 SDK 환경을 수정합니다.

다음 섹션에서는 SDKRuntime 클라이언트 라이브러리에서 SDK를 로드할 때 예상되는 동작을 설명합니다.

SDK 리소스

SDK 리소스(res/)는 SDK가 앱 프로세스에 로드될 때 지원됩니다. Bundletool은 모든 SDK 리소스를 앱 리소스와 병합합니다.

충돌을 방지하기 위해 모든 리소스 ID에서 packageId 접두사를 변경하여 SDK 리소스를 다시 매핑합니다.

SDK가 SDKRuntime 클라이언트 라이브러리에 의해 로드되면 재매핑된 리소스를 R 클래스를 사용하여 처리할 수 있도록 런타임에 packageId가 업데이트됩니다.

Java 리소스

Java 리소스는 SDK가 앱 프로세스에 로드될 때 지원됩니다. Bundletool은 모든 SDK Java 리소스를 앱 애셋의 특수 디렉터리에 복사합니다. SDKRuntime 클라이언트 라이브러리는 중간 클래스 로더를 사용하여 모든 Java 리소스 관련 호출을 새 루트 디렉터리로 리디렉션합니다.

SDK 애셋

SDK 애셋은 재매핑 없이 앱 애셋과 병합됩니다.

SDK 저장소

SDK 저장소를 지원하기 위해 SDK 런타임 클라이언트 라이브러리는 각 번들 SDK의 전용 루트 디렉터리를 앱 저장소에 만들고 이 디렉터리를 저장소 루트로 사용하는 특수 컨텍스트를 제공합니다.

이 컨텍스트는 SandboxedSdkProviderCompat#getContext에서 가져올 수 있습니다.

지원되는 저장소 관련 메서드는 다음과 같습니다.

  • getDataDir
  • getCacheDir
  • getCodeCacheDir
  • getNoBackupFilesDir
  • getDir
  • getFilesDir
  • openFileInput
  • openFileOutput
  • deleteFile
  • getFileStreamPath
  • fileList
  • getDatabasePath
  • openOrCreateDatabase
  • moveDatabaseFrom - SDK 컨텍스트 간에만
  • deleteDatabase
  • databaseList
  • getSharedPreferences
  • moveSharedPreferencesFrom - SDK 컨텍스트 간에만
  • deleteSharedPreferences

기기 보호 저장소 컨텍스트는 해당 컨텍스트에서 createDeviceProtectedStorageContext()를 호출하여 만들 수 있습니다.

SdkSandboxControllerCompat

SDKRuntime 클라이언트 라이브러리는 앱 프로세스에 로드된 번들 SDK에 SdkSandboxControllerCompat 구현을 제공합니다.

클라이언트 라이브러리에서 API를 지원하지 않는 경우(예: 앱 버전보다 최신 버전의 라이브러리로 빌드된 SDK) 가장 적합한 대체가 사용됩니다(노옵스(no-ops) 또는 예외).

버전 관리

SDKRuntime 클라이언트 라이브러리가 번들 SDK를 로드할 때 SDK 내의 SDKRuntime 제공업체 라이브러리와 핸드셰이크를 실행합니다. 핸드셰이크 중에 라이브러리는 버전을 교환하고 동작을 조정하여 사용할 수 없는 API를 가장 적합한 대체(노옵스(no-ops) 또는 예외)로 대체합니다.

앱과 SDK 개발자 모두 최신 버전의 라이브러리를 사용하는 것이 좋습니다. 그러지 않으면 두 부분 모두에서 지원이 필요한 기능을 사용하지 못할 수 있습니다.

모든 버전의 SDKRuntime 클라이언트 라이브러리는 모든 버전의 SDKRuntime 제공업체 라이브러리와 함께 SDK를 로드할 수 있으며 그 반대의 경우도 가능합니다.

향후 이는 특정 버전의 제공업체 라이브러리로 SDK를 로드하는 데 필요한 최소 클라이언트 라이브러리 버전으로 변경될 예정입니다.

이렇게 하면 단편화를 최소화하고 번들 SDK가 성공적으로 로드된 경우 대부분의 API가 지원됩니다.