Zgodność wsteczna środowiska wykonawczego SDK

Ten dokument przedstawia nową bibliotekę Jetpack, która ma pomóc deweloperom w migracji do środowiska wykonawczego SDK. Wyjaśniono w nim, jak środowisko wykonawcze SDK będzie obsługiwane w przypadku poprzednich wersji platformy Androida (od kompilacji do wykonania) oraz jakich różnic lub ograniczeń w środowisku wykonawczym mogą się spodziewać deweloperzy. Ta biblioteka umożliwia deweloperom tworzenie jednej wersji aplikacji lub pakietu SDK, która umożliwia działanie na urządzeniach z obsługą środowiska wykonawczego SDK lub bez.

Zgodność wsteczną jest możliwa dzięki tym komponentom:

  • Wtyczka Android Gradle (AGP) + Bundletool tworzy wariant aplikacji dla urządzeń nieobsługujących środowiska wykonawczego SDK przez połączenie środowiska wykonawczego SDK z plikiem APK.

  • Biblioteka klienta środowiska wykonawczego SDK (androidx.privacysandbox.sdkruntime:sdkruntime-client) wczytuje pakiet SDK z zasobów aplikacji i emuluje środowisko wykonawcze SDK na urządzeniach, które nie obsługują tego środowiska.

  • Biblioteka dostawcy środowiska wykonawczego SDK (androidx.privacysandbox.sdkruntime:sdkruntime-provider) udostępnia interfejs API dla pakietów SDK, który umożliwia wczytywanie z biblioteki klienta środowiska wykonawczego SDK.

Dostarczanie pakietów SDK za pomocą narzędzia Bundletool

Na urządzeniach obsługujących środowisko wykonawcze SDK pakiety SDK są dostarczane i instalowane jako osobne pakiety.

Aby umożliwić obsługę wersji platformy, które nie obsługują środowiska wykonawczego SDK, Bundletool utworzy co najmniej 1 wariant zestawu APK aplikacji obejmujący wszystkie pakiety SDK, od których zależy aplikacja. Każdy pakiet SDK jest sprzedawany jako osobny podział APK. Dodatkowo wykonywane są te przekształcenia:

  1. Skopiuj pliki z kodem bajtowym (DEX) pakietu SDK do podziału pakietu SDK jako zasoby.
  2. Skopiuj zasoby pakietu SDK w języku Java do podziału SDK jako zasobów.
  3. Zmapuj zasoby pakietu SDK i scal je z zasobami aplikacji.
  4. Wygeneruj konfiguracje biblioteki klienta środowiska wykonawczego SDK.

Wczytywanie pakietów SDK za pomocą biblioteki klienta środowiska wykonawczego SDK

Biblioteka klienta środowiska wykonawczego SDK udostępnia interfejsy API podobne do interfejsów API platformy, ale obsługuje zarówno pakiety SDK w środowisku wykonawczym SDK, jak i pakiety SDK dołączone do aplikacji wariantu.

Aby użyć biblioteki klienta środowiska wykonawczego SDK, dodaj zależność androidx.privacysandbox.sdkruntime:sdkruntime-client i użyj parametru SdkSandboxManagerCompat zamiast SdkSandboxManager.

Gdy aplikacja próbuje wczytać pakiet SDK, biblioteka sprawdza najpierw, czy podczas kompilacji został on do niej dołączony. Jeśli był on w pakiecie, biblioteka wyodrębnia go z podziału SDK i wczytuje go w procesie aplikacji. Jeśli pakiet SDK nie był dołączony do aplikacji, biblioteka deleguje interfejs API platformy do wczytywania tego pakietu.

Wyodrębnianie SDK z zasobów

Gdy aplikacja próbuje wczytać pakiet SDK, biblioteka klienta środowiska wykonawczego SDK sprawdza, czy pliki DEX pakietu SDK zostały już wyodrębnione z pamięci urządzenia (code_cache), a jeśli nie, wyodrębnia je z zasobów.

Po zainstalowaniu lub aktualizacji aplikacji biblioteka wyodrębnia pliki tylko raz.

Jeśli dostępne miejsce na dane jest mniejsze niż dozwolony próg (obecnie 100 MB) i nie są wyodrębniane żadne pliki DEX, biblioteka próbuje wczytać pakiet SDK bezpośrednio z zasobów na obsługiwanych urządzeniach (interfejs API w wersji 27 lub nowszej). Powoduje to większą ilość pamięci.

Moduł ładowania klas pakietów SDK

Aby uniknąć konfliktów między pakietami SDK a klasami aplikacji, wszystkie klasy pakietów SDK są wczytywane za pomocą osobnego modułu ładowania klas całkowicie niezależnego od głównego modułu do ładowania klasy aplikacji.

W obecnym projekcie środowiska wykonawczego SDK cała komunikacja między aplikacją a pakietami SDK odbywa się za pomocą wywołań Binder IPC. W pakietach SDK używane są te same obiekty Binder, a serializacja transakcji Binder umożliwia deweloperom aplikacji przesyłanie obiektów SDK Binder do interfejsów SDK Binder po stronie aplikacji.

W przypadku innych interakcji wewnętrznych (np. inicjowania pakietu SDK, przekazywania do niego interfejsu API kontrolera itd.) biblioteka korzysta z funkcji Reflection i dynamicznych serwerów proxy do pracy z różnymi modułami ładowania klas.

Środowisko SDK

Biblioteka dostawcy SDKRuntime zawiera interfejsy API przeznaczone dla deweloperów pakietów SDK. Te interfejsy API są podobne do interfejsów API platformy, ale pozwalają na ładowanie pakietów SDK zarówno przez środowisko wykonawcze SDK, jak i bibliotekę klienta SDKRuntime.

Aby móc korzystać z pakietu SDK biblioteki, musisz dodać zależność androidx.privacysandbox.sdkruntime:sdkruntime-provider i rozszerzyć zakres SandboxedSdkProviderCompat zamiast SandboxedSdkProvider.

Aby umożliwić wczytywanie dostawcy compat w środowisku wykonawczym SDK, musisz też użyć SandboxedSdkProviderAdapter jako dostawcy pakietu SDK.

SdkSandboxControllerCompat przekazuje dostęp do interfejsu API platformy, gdy pakiet SDK jest wczytywany w środowisku wykonawczym SDK lub przekazuje do biblioteki klienta SDKRuntime, gdy pakiet SDK jest wczytywany jako pakiet SDK.

W przypadku pakietów SDK biblioteka modyfikuje środowisko SDK w sposób emulujący działanie środowiska podobnego do środowiska wykonawczego SDK.

W kolejnych sekcjach opisano oczekiwane zachowanie przy wczytywaniu pakietu SDK przez bibliotekę klienta SDKRuntime.

Zasoby SDK

Zasoby SDK (res/) są obsługiwane, gdy pakiet SDK jest wczytywany w procesie aplikacji. Bundletool łączy wszystkie zasoby pakietów SDK z zasobami aplikacji.

Aby uniknąć konfliktów, zasoby pakietu SDK są mapowane przez zmianę prefiksu packageId we wszystkich identyfikatorach zasobów.

Podczas wczytywania pakietu SDK przez bibliotekę klienta SDKRuntime usługa packageId jest aktualizowana w środowisku wykonawczym, aby umożliwić adresowanie zmapowanych zasobów za pomocą klasy R.

Zasoby Java

Zasoby Java są obsługiwane podczas wczytywania pakietu SDK w procesie aplikacji. Narzędzie Bundletool kopiuje wszystkie zasoby SDK w języku Java do specjalnego katalogu w zasobach aplikacji. Biblioteka klienta SDKRuntime używa pośredniego modułu ładowania klas do przekierowania wszystkich wywołań związanych z zasobami w języku Java do nowego katalogu głównego.

Zasoby SDK

Komponenty pakietu SDK są scalane z komponentami z linkami do aplikacji bez ponownego mapowania.

Pamięć SDK

Aby zapewnić obsługę pakietu SDK Storage, biblioteka klienta środowiska wykonawczego SDK tworzy dedykowany katalog główny dla każdego pakietu SDK w pamięci aplikacji i udostępnia specjalny kontekst, który używa tego katalogu jako katalogu głównego.

Ten kontekst można pobrać z SandboxedSdkProviderCompat#getContext.

Obsługiwane metody związane z miejscem na dane:

  • getDataDir
  • getCacheDir
  • getCodeCacheDir
  • getNoBackupFilesDir
  • getDir
  • getFilesDir
  • openFileInput
  • openFileOutput
  • deleteFile
  • getFileStreamPath
  • fileList
  • getDatabasePath
  • openOrCreateDatabase
  • moveDatabaseFrom – tylko między kontekstami pakietu SDK
  • deleteDatabase
  • databaseList
  • getSharedPreferences
  • moveSharedPreferencesFrom – tylko między kontekstami pakietu SDK
  • deleteSharedPreferences

Kontekst chronionej pamięci urządzenia można utworzyć, wywołując createDeviceProtectedStorageContext() w tym kontekście.

SdkSandboxControllerCompat

Biblioteka klienta SDKRuntime udostępnia implementację SdkSandboxControllerCompat w połączonych pakietach SDK wczytywanych w procesie aplikacji.

Jeśli biblioteka klienta nie obsługuje interfejsów API (np. za pomocą pakietu SDK z biblioteką w wersji nowszej niż wersja aplikacji), zostanie użyta najodpowiedniejsza opcja zastępcza (brak operacji lub wyjątek).

Obsługa wersji

Gdy biblioteka klienta SDKRuntime wczytuje pakiet SDK, przeprowadza uzgadnianie połączenia z biblioteką dostawcy SDKRuntime w pakiecie SDK. Podczas uzgadniania połączenia biblioteki wymieniają swoje wersje i dostosowują swoje działanie, aby zastąpić niedostępne interfejsy API najbardziej odpowiednią opcją zastępczą (brak operacji lub wyjątek).

Zdecydowanie zalecamy korzystanie z najnowszej wersji biblioteki zarówno deweloperom aplikacji, jak i pakietom SDK. W przeciwnym razie funkcje, które wymagają obsługi przez obie części, mogą być niedostępne.

Dowolna wersja biblioteki klienta SDKRuntime może wczytywać pakiet SDK z dowolną wersją biblioteki dostawcy SDKRuntime i odwrotnie.

W przyszłości zmienimy ją na minimalną wersję biblioteki klienta niezbędną do wczytywania SDK określonej wersji biblioteki dostawcy.

Pozwoli to zminimalizować fragmentację danych i zapewnić obsługę większości interfejsów API po załadowaniu pakietu SDK.