Abwärtskompatibilität für die SDK-Laufzeit

In diesem Dokument wird eine neue Jetpack-Bibliothek vorgeschlagen, die Entwickler bei der Migration unterstützt zu den SDK-Laufzeit Darin wird erläutert, wie die SDK-Laufzeit für frühere Android-Plattformversionen unterstützt wird (vom Build bis zur Ausführung) und welche Unterschiede oder Einschränkungen Entwickler in der Laufzeitumgebung erwarten können. Mit dieser Bibliothek können Entwickler eine einzige Version ihrer App oder ihres SDKs erstellen, die auf Geräten mit oder ohne SDK-Laufzeitunterstützung ausgeführt werden kann.

Die Abwärtskompatibilität wird durch die folgenden Komponenten erreicht:

  • Mit Android Gradle Plugin (AGP) und Bundletool wird eine App-Variante für Geräte ohne SDK-Laufzeitunterstützung erstellt, indem die SDK-Laufzeit in das APK eingebunden wird.

  • SDK Runtime-Clientbibliothek (androidx.privacysandbox.sdkruntime:sdkruntime-client) lädt das gebündelte SDK aus App-Assets und emuliert die SDK-Laufzeit Geräte ohne SDK Runtime-Unterstützung.

  • Bibliothek des SDK-Laufzeitanbieter (androidx.privacysandbox.sdkruntime:sdkruntime-provider) stellt eine API für SDKs, die das Laden aus der SDK Runtime-Clientbibliothek ermöglichen.

SDK-Übermittlung mit Bundletool

Auf Geräten mit SDK-Laufzeitunterstützung werden SDKs als separate Pakete bereitgestellt und installiert.

Zur Unterstützung von Plattformversionen ohne SDK-Laufzeit Eine oder mehrere Varianten des App-APK-Sets erstellen, die alle SDKs der App enthalten hängt davon ab. Jedes SDK wird als separate APK-Spaltung verpackt. Die werden folgende Transformationen ausgeführt:

  1. Kopieren Sie SDK-Bytecodedateien (DEX) als Assets in die SDK-Spaltung.
  2. Kopieren Sie SDK-Java-Ressourcen in den SDK-Split als Assets.
  3. SDK-Ressourcen neu zuordnen und mit App-Ressourcen zusammenführen.
  4. Konfigurationen für die SDK Runtime-Clientbibliothek generieren

SDKs mit der SDK Runtime-Clientbibliothek laden

Die SDK Runtime-Clientbibliothek stellt APIs bereit, die Plattform-APIs ähneln. unterstützen aber sowohl SDKs in der SDK-Laufzeitumgebung als auch SDKs in der SDK-Laufzeitumgebung App-Variante.

Fügen Sie die Abhängigkeit hinzu, um die SDK Runtime-Clientbibliothek zu verwenden androidx.privacysandbox.sdkruntime:sdkruntime-client und verwenden SdkSandboxManagerCompat statt SdkSandboxManager.

Wenn eine App versucht, ein SDK zu laden, prüft die Bibliothek zuerst, ob das SDK beim Builden mit der App gebündelt wurde. Bei einem Bundle extrahiert die Bibliothek die SDK aus dem SDK-Split und lädt es in den App-Prozess. Wenn das SDK nicht im Lieferumfang der App enthalten war, deligiert die Bibliothek das Laden des SDK an die Plattform-API.

SDK aus Assets extrahieren

Wenn eine App versucht, ein gebündeltes SDK zu laden, prüft die SDK Runtime-Clientbibliothek, ob die DEX-Dateien des SDKs bereits in den Gerätespeicher (code_cache) extrahiert wurden. Andernfalls werden sie aus den Assets extrahiert.

Die Bibliothek extrahiert Dateien normalerweise nur einmal nach einer App-Installation oder aktualisieren.

Wenn der verfügbare Speicherplatz unter dem zulässigen Grenzwert liegt (derzeit 100 MB) und keine DEX-Dateien extrahiert wurden, versucht die Bibliothek, das SDK zu laden. direkt aus Assets auf unterstützten Geräten (API 27 und höher). Dies führt zu einer größeren des Arbeitsspeicher-Fußabdrucks.

Classloader für SDK-Klassen

Um Konflikte zwischen SDKs und App-Klassen zu vermeiden, werden alle SDK-Klassen mit einem separaten Classloader geladen, der völlig unabhängig vom Haupt-Classloader der App ist.

Im aktuellen SDK Runtime-Design ist die gesamte Kommunikation zwischen einer App und SDKs mit Binder IPC-Aufrufen erfolgen. Für gebündelte SDKs werden dieselben SDK-Binder-Objekte verwendet. Durch die Binder-Transaktionsserialisierung können App-Entwickler SDK-Binder-Objekte auf App-Seite in SDK-Binder-Schnittstellen umwandeln.

Für andere interne Interaktionen (z. B. die Initialisierung eines SDKs, die Bereitstellung eines Controller-API auf ein SDK usw.), verwendet die Bibliothek Spiegelung und Dynamische Proxys, die mit verschiedenen Classloadern funktionieren

SDK-Umgebung

Die SDKRuntime Provider-Bibliothek stellt SDK-Entwicklern APIs zur Verfügung. Diese APIs sind ähnlich wie Plattform-APIs, können aber SDKs sowohl über die SDK-Laufzeit laden und die SDKRuntime-Clientbibliothek.

Damit Sie das Bibliothek-SDK verwenden können, müssen Sie die Abhängigkeit androidx.privacysandbox.sdkruntime:sdkruntime-provider hinzufügen und SandboxedSdkProviderCompat anstelle von SandboxedSdkProvider erweitern.

Außerdem musst du SandboxedSdkProviderAdapter als SDK-Anbieter verwenden, das Laden des Compat-Anbieters in die SDK-Laufzeitumgebung zulassen.

SdkSandboxControllerCompat delegiert an die Plattform-API, wenn das SDK in der SDK-Laufzeit geladen wird, oder an die SDKRuntime-Clientbibliothek, wenn das SDK als gebundeltes SDK geladen wird.

Bei gebündelten SDKs ändert die Bibliothek die SDK-Umgebung so, dass das Verhalten der SDK-Laufzeitumgebung nachempfunden wird.

In den folgenden Abschnitten wird das erwartete Verhalten beschrieben, wenn das SDK von der SDKRuntime-Clientbibliothek geladen wird.

SDK-Ressourcen

SDK-Ressourcen (res/) werden unterstützt, wenn das SDK in den App-Prozess geladen wird. Bundletool führt alle SDKs zusammen, durch Anwendungsressourcen.

Um Konflikte zu vermeiden, werden SDK-Ressourcen neu zugeordnet, indem das Präfix packageId in allen Ressourcen-IDs geändert wird.

Wenn das SDK von der SDKRuntime-Clientbibliothek geladen wird, wird packageId in der Laufzeit aktualisiert, damit neu zugeordnete Ressourcen mithilfe der R-Klasse adressiert werden können.

Java-Ressourcen

Java-Ressourcen werden unterstützt, wenn das SDK in den App-Prozess geladen wird. Bundletool kopiert alle Java-Ressourcen des SDK in ein spezielles Verzeichnis in den App-Assets. Die SDKRuntime-Clientbibliothek verwendet einen Zwischen-Klassenloader, um alle Java-Ressourcen-bezogenen Aufrufe an das neue Stammverzeichnis weiterzuleiten.

SDK-Assets

SDK-Assets werden ohne Neuzuordnung mit App-Assets zusammengeführt.

SDK-Speicher

Zur Unterstützung des SDK-Speichers erstellt die SDK Runtime Client-Bibliothek ein eigenes Stammverzeichnis für jedes gebundelte SDK im App-Speicher und stellt einen speziellen Kontext bereit, in dem dieses Verzeichnis als Speicherstamm verwendet wird.

Dieser Kontext kann über SandboxedSdkProviderCompat#getContext abgerufen werden.

Unterstützte speicherbezogene Methoden:

  • getDataDir
  • getCacheDir
  • getCodeCacheDir
  • getNoBackupFilesDir
  • getDir
  • getFilesDir
  • openFileInput
  • openFileOutput
  • deleteFile
  • getFileStreamPath
  • fileList
  • getDatabasePath
  • openOrCreateDatabase
  • moveDatabaseFrom – nur zwischen SDK-Kontexten
  • deleteDatabase
  • databaseList
  • getSharedPreferences
  • moveSharedPreferencesFrom – nur zwischen SDK-Kontexten
  • deleteSharedPreferences

Ein gerätegeschützter Speicherkontext kann durch Aufrufen von createDeviceProtectedStorageContext() auf diesen Kontext erstellt werden.

SdkSandboxControllerCompat

Die SDKRuntime-Clientbibliothek stellt die SdkSandboxControllerCompat bereit. auf gebündelte SDKs, die im App-Prozess geladen werden.

Wenn APIs nicht von der Clientbibliothek unterstützt werden (z. B. bei einem SDK, das mit einer Version der Bibliothek erstellt wurde, die neuer ist als die App-Version), wird der am besten geeignete Fallback verwendet (No-Op oder Ausnahme).

Versionsverwaltung

Wenn die SDKRuntime-Clientbibliothek ein gebündeltes SDK lädt, führt sie einen Handshake mit der SDKRuntime-Anbieterbibliothek im SDK aus. Während des Handshakes Bibliotheken ihre Versionen austauschen und das Verhalten anpassen, um die Verfügbarkeit APIs mit dem am besten geeigneten Fallback (No-Op oder Ausnahme).

Die Verwendung der neuesten Version der Bibliothek wird für beide Apps dringend empfohlen. und SDK-Entwickler, andernfalls Funktionen, die Unterstützung in beiden Teilen erfordern. sind möglicherweise nicht verfügbar.

Jede Version der SDKRuntime-Clientbibliothek kann ein SDK mit beliebigen Version der SDKRuntime Provider-Bibliothek und umgekehrt.

Künftig wird dies in die minimale Clientbibliotheksversion geändert, die zum Laden des SDKs mit einer bestimmten Version der Anbieterbibliothek erforderlich ist.

Dies minimiert die Fragmentierung und stellt sicher, dass die meisten APIs wird unterstützt, wenn das gebündelte SDK geladen wurde.