Rétrocompatibilité pour le SDK Runtime

Ce document propose une nouvelle bibliothèque Jetpack pour aider les développeurs à effectuer la migration vers le SDK Runtime. Il explique comment le SDK Runtime sera compatible avec les versions précédentes de la plate-forme Android (de la compilation à l'exécution) et les différences ou limites dans l'environnement d'exécution auxquelles les développeurs peuvent s'attendre. Cette bibliothèque permet aux développeurs de créer une seule version de leur application ou de leur SDK qui comprend la possibilité de l'exécuter sur des appareils compatibles ou non avec SDK Runtime.

La rétrocompatibilité est obtenue grâce aux composants suivants :

  • Le plug-in Android Gradle (AGP) + Bundletool crée une variante d'application pour les appareils non compatibles avec le SDK Runtime en regroupant le SDK Runtime dans l'APK.

  • La bibliothèque cliente du SDK Runtime (androidx.privacysandbox.sdkruntime:sdkruntime-client) charge le SDK groupé à partir des composants d'application et émule le SDK Runtime sur les appareils qui ne le prennent pas en charge.

  • La bibliothèque du fournisseur du SDK Runtime (androidx.privacysandbox.sdkruntime:sdkruntime-provider) fournit une API pour que les SDK permettent le chargement à partir de la bibliothèque cliente du SDK Runtime.

Diffusion du SDK avec Bundletool

Sur les appareils compatibles avec le SDK Runtime, les SDK seront fournis et installés en tant que packages distincts.

Pour prendre en charge les versions de plate-forme qui ne sont pas compatibles avec le SDK Runtime, Bundletool créera une ou plusieurs variantes de l'ensemble d'APK d'application, qui incluent tous les SDK dont dépend l'application. Chaque SDK est empaqueté sous la forme d'une division d'APK distincte. De plus, les transformations suivantes sont effectuées :

  1. Copiez les fichiers bytecode (DEX) du SDK en tant qu'éléments vers la division du SDK.
  2. Copiez les ressources Java du SDK en tant qu'éléments vers la division du SDK.
  3. Remappez les ressources du SDK et fusionnez-les avec les ressources de l'application.
  4. Générez des configurations pour la bibliothèque cliente du SDK Runtime.

Charger des SDK avec la bibliothèque cliente du SDK Runtime

La bibliothèque cliente du SDK Runtime fournit des API semblables aux API de plate-forme, mais qui sont compatibles avec les SDK de l'environnement SDK Runtime et les SDK groupés avec l'application de variante.

Pour utiliser la bibliothèque cliente du SDK Runtime, ajoutez la dépendance androidx.privacysandbox.sdkruntime:sdkruntime-client et utilisez SdkSandboxManagerCompat au lieu de SdkSandboxManager.

Lorsqu'une application tente de charger un SDK, la bibliothèque vérifie d'abord si le SDK a été groupé à l'application lors de la compilation. S'il a été groupé, la bibliothèque extrait le SDK de la division du SDK et le charge dans le processus de l'application. Si le SDK n'a pas été groupé à l'application, la bibliothèque délègue l'API de la plate-forme pour charger le SDK.

Extraire un SDK à partir d'éléments

Lorsqu'une application tente de charger un SDK groupé, la bibliothèque cliente du SDK Runtime vérifie si les fichiers DEX du SDK ont déjà été extraits vers l'espace de stockage de l'appareil (code_cache) et, si ce n'est pas le cas, les extrait des éléments.

La bibliothèque n'extrait normalement les fichiers qu'une seule fois après l'installation ou la mise à jour d'une application.

Si l'espace de stockage disponible est inférieur au seuil autorisé (actuellement 100 Mo) et qu'aucun fichier DEX n'est extrait, la bibliothèque tente de charger le SDK directement à partir des éléments présents sur les appareils compatibles (API 27 et versions ultérieures). Cela se traduit par une augmentation de l'espace mémoire utilisé.

ClassLoader pour les classes du SDK

Pour éviter les conflits entre les SDK et les classes d'application, toutes les classes du SDK sont chargées à l'aide d'un ClassLoader distinct, qui est complètement indépendant du ClassLoader principal de l'application.

Dans la conception actuelle du SDK Runtime, toutes les communications entre une application et les SDK s'effectuent à l'aide d'appels de liaison (IPC). Les mêmes objets SDK Binder sont utilisés pour les SDK groupés, et la sérialisation des transactions Binder permet aux développeurs d'applications de caster des objets SDK Binder en interfaces de SDK Binder du côté de l'application.

Pour les autres interactions internes (telles que l'initialisation d'un SDK, la fourniture d'une API de contrôleur à un SDK, etc.), la bibliothèque utilise la réflexion et les proxys dynamiques pour fonctionner sur différents ClassLoaders.

Environnement du SDK

La bibliothèque du fournisseur SDK Runtime fournit des API aux développeurs de SDK. Ces API sont semblables aux API de plate-forme, mais elles permettent de charger les SDK à la fois par l'environnement SDK Runtime et par la bibliothèque cliente SDK Runtime.

Pour être en mesure d'utiliser le SDK de la bibliothèque, vous devez ajouter la dépendance androidx.privacysandbox.sdkruntime:sdkruntime-provider et étendre SandboxedSdkProviderCompat au lieu de SandboxedSdkProvider.

Vous devez également utiliser SandboxedSdkProviderAdapter comme fournisseur de SDK pour permettre le chargement du fournisseur de compatibilité dans l'environnement SDK Runtime.

SdkSandboxControllerCompat délègue à l'API de la plate-forme lorsque le SDK est chargé dans SDK Runtime ou délègue à la bibliothèque cliente du SDK Runtime lorsque le SDK est chargé en tant que SDK groupé.

Pour les SDK groupés, la bibliothèque modifie l'environnement du SDK de manière à émuler un comportement semblable à celui de l'environnement SDK Runtime.

Les sections suivantes décrivent les comportements attendus lorsque le SDK est chargé par la bibliothèque cliente du SDK Runtime.

Ressources du SDK

Les ressources du SDK (res/) sont prises en charge lorsque le SDK est chargé dans le processus de l'application. Bundletool fusionne les ressources de tous les SDK avec les ressources de l'application.

Pour éviter les conflits, les ressources du SDK sont remappées en modifiant le préfixe packageId dans tous les ID de ressource.

Lorsque le SDK est chargé par la bibliothèque cliente du SDK Runtime, packageId est mis à jour dans l'environnement d'exécution pour permettre l'adressage des ressources remappées à l'aide de la classe R.

Ressources Java

Les ressources Java sont prises en charge lorsque le SDK est chargé dans le processus de l'application. Bundletool copie toutes les ressources Java du SDK dans un répertoire spécial des composants Application. La bibliothèque cliente du SDK Runtime utilise un ClassLoader intermédiaire pour rediriger tous les appels liés aux ressources Java vers le nouveau répertoire racine.

Éléments du SDK

Les éléments du SDK sont fusionnés avec les composants Application sans remappage.

Stockage du SDK

Pour prendre en charge le stockage du SDK, la bibliothèque cliente du SDK Runtime crée un répertoire racine dédié pour chaque SDK groupé dans le stockage d'application et fournit un contexte spécial qui utilise ce répertoire comme racine de stockage.

Ce contexte peut être récupéré à partir de SandboxedSdkProviderCompat#getContext.

Méthodes de stockage compatibles :

  • getDataDir
  • getCacheDir
  • getCodeCacheDir
  • getNoBackupFilesDir
  • getDir
  • getFilesDir
  • openFileInput
  • openFileOutput
  • deleteFile
  • getFileStreamPath
  • fileList
  • getDatabasePath
  • openOrCreateDatabase
  • moveDatabaseFrom : uniquement entre les contextes de SDK
  • deleteDatabase
  • databaseList
  • getSharedPreferences
  • moveSharedPreferencesFrom : uniquement entre les contextes de SDK
  • deleteSharedPreferences

Vous pouvez créer un contexte de stockage protégé par l'appareil en appelant createDeviceProtectedStorageContext() au niveau de ce contexte.

.

SdkSandboxControllerCompat

La bibliothèque cliente du SDK Runtime fournit l'implémentation SdkSandboxControllerCompat aux SDK groupés et chargés dans le processus de l'application.

Si les API ne sont pas compatibles avec la bibliothèque cliente (par exemple, avec un SDK créé avec une version de la bibliothèque plus récente que la version de l'application), la solution de remplacement la plus appropriée sera utilisée (aucune opération ou exception).

Gestion des versions

Lorsque la bibliothèque cliente du SDK Runtime charge un SDK groupé, elle effectue un handshake avec la bibliothèque du fournisseur du SDK Runtime dans le SDK. Lors du handshake, les bibliothèques échangent leurs versions et ajustent leur comportement pour remplacer les API indisponibles par la solution de remplacement la plus appropriée (aucune opération ou exception).

L'utilisation de la version la plus récente de la bibliothèque est vivement recommandée pour les développeurs d'applications et de SDK. Sinon, les fonctionnalités qui nécessitent une prise en charge dans les deux parties risquent de ne pas être disponibles.

N'importe quelle version de la bibliothèque cliente du SDK Runtime peut charger un SDK avec n'importe quelle version de la bibliothèque du fournisseur du SDK Runtime et inversement.

À l'avenir, ces versions seront remplacées par la version minimale de la bibliothèque cliente requise pour charger le SDK avec une version particulière de la bibliothèque du fournisseur.

Cela minimise la fragmentation et garantit que la plupart des API seront compatibles si le SDK groupé a bien été chargé.