Compatibilità con le versioni precedenti dell'SDK Runtime

Questo documento propone una nuova libreria Jetpack per aiutare gli sviluppatori nella migrazione a SDK Runtime. Spiega come SDK Runtime sarà supportato per le versioni precedenti della piattaforma Android (dalla build all'esecuzione) e quali differenze o limitazioni nell'ambiente di runtime possono aspettarsi gli sviluppatori. Questa libreria consente agli sviluppatori di creare una singola versione dell'app o dell'SDK che include la possibilità di eseguirla su dispositivi con o senza supporto SDK Runtime.

La compatibilità con le versioni precedenti si ottiene tramite i seguenti componenti:

  • Android Gradle Plugin (AGP) + Bundletool crea una variante dell'app per i dispositivi che non supportano SDK Runtime raggruppando SDK Runtime nell'APK.

  • La libreria client di SDK Runtime (androidx.privacysandbox.sdkruntime:sdkruntime-client) carica l'SDK in bundle dagli asset dell'app ed emula l'SDK Runtime sui dispositivi che non supportano SDK Runtime.

  • La libreria del provider SDK Runtime (androidx.privacysandbox.sdkruntime:sdkruntime-provider) fornisce un'API per gli SDK per consentire il caricamento dalla libreria client di SDK Runtime.

Pubblicazione dell'SDK con Bundletool

Sui dispositivi che supportano SDK Runtime, gli SDK verranno pubblicati e installati come pacchetti separati.

Per supportare le versioni della piattaforma prive del supporto di SDK Runtime, Bundletool creerà una o più varianti del set di APK dell'app che includono tutti gli SDK da cui dipende l'app. Ogni SDK viene pacchettizzato come una suddivisione separata dell'APK. Inoltre, vengono eseguite le seguenti trasformazioni:

  1. Copia i file bytecode (DEX) dell'SDK nella suddivisione dell'SDK come asset.
  2. Copia le risorse Java dell'SDK nella suddivisione dell'SDK come asset.
  3. Rimappa le risorse SDK e uniscile alle risorse dell'app.
  4. Genera configurazioni per la libreria client di SDK Runtime.

Carica gli SDK con la libreria client di SDK Runtime

La libreria client di SDK Runtime fornisce API simili alle API della piattaforma, ma supporta sia gli SDK nell'ambiente SDK Runtime sia gli SDK in bundle con l'app variante.

Per utilizzare la libreria client di SDK Runtime, aggiungi la dipendenza androidx.privacysandbox.sdkruntime:sdkruntime-client e usa SdkSandboxManagerCompat invece di SdkSandboxManager.

Quando un'app tenta di caricare un SDK, la libreria controlla prima se l'SDK è stato integrato con l'app durante la build. Se è stato integrato, la libreria estrae l'SDK dalla suddivisione dell'SDK e lo carica nel processo dell'app. Se l'SDK non è stato associato all'app, la libreria delega l'API della piattaforma a caricare l'SDK.

Estrarre un SDK dagli asset

Quando un'app tenta di caricare un SDK in bundle, la libreria client di SDK Runtime controlla se i file DEX dell'SDK sono già stati estratti nello spazio di archiviazione del dispositivo (code_cache) e, in caso contrario, li estrae dagli asset.

Di solito la libreria estrae i file solo una volta dopo l'installazione o l'aggiornamento dell'app.

Se lo spazio di archiviazione disponibile è inferiore alla soglia consentita (attualmente 100 MB) e non vengono estratti file DEX, la libreria tenta di caricare l'SDK direttamente dagli asset sui dispositivi supportati (API 27 e versioni successive), con un conseguente utilizzo di memoria maggiore.

Caricatore di classi per le classi di SDK

Per evitare conflitti tra SDK e classi di app, tutte le classi di SDK vengono caricate utilizzando un classloader separato e completamente indipendente dal classloader principale dell'app.

Nell'attuale progettazione di SDK Runtime, tutte le comunicazioni tra un'app e gli SDK avvengono tramite chiamate IPC di Binder. Gli stessi oggetti SDK Binder vengono utilizzati per gli SDK in bundle e la serializzazione delle transazioni di Binder consente agli sviluppatori di app di trasmettere oggetti SDK Binder alle interfacce di SDK Binder sul lato app.

Per altre interazioni interne (come l'inizializzazione di un SDK, la fornitura di un'API controller a un SDK e così via), la libreria utilizza Reflection e Proxy dinamici per funzionare su diversi caricatori di classi.

Ambiente SDK

La libreria SDKRuntime Provider fornisce API agli sviluppatori di SDK. Queste API sono simili alle API della piattaforma, ma consentono il caricamento degli SDK sia dall'ambiente SDK Runtime sia dalla libreria client SDKRuntime.

Per poter utilizzare l'SDK della libreria, devi aggiungere la dipendenza androidx.privacysandbox.sdkruntime:sdkruntime-provider ed estendere SandboxedSdkProviderCompat anziché SandboxedSdkProvider.

Devi inoltre utilizzare SandboxedSdkProviderAdapter come provider di SDK, per consentire il caricamento del provider compatibile nell'ambiente SDK Runtime.

SdkSandboxControllerCompat delega all'API della piattaforma quando l'SDK viene caricato in SDK Runtime oppure delega alla libreria client SDKRuntime quando l'SDK viene caricato come SDK in bundle.

Per gli SDK in bundle, la libreria modifica l'ambiente SDK in modo da emulare un comportamento simile all'ambiente SDK Runtime.

Le sezioni successive descrivono i comportamenti previsti quando l'SDK viene caricato dalla libreria client SDKRuntime.

Risorse SDK

Le risorse SDK (res/) sono supportate quando l'SDK viene caricato nel processo dell'app. Bundletool unisce tutte le risorse degli SDK con le risorse dell'app.

Per evitare conflitti, le risorse SDK vengono rimappate modificando il prefisso packageId in tutti gli ID risorsa.

Quando l'SDK viene caricato dalla libreria client SDKRuntime, packageId viene aggiornato in runtime per consentire l'indirizzamento delle risorse rimappate utilizzando la classe R.

Risorse Java

Le risorse Java sono supportate quando l'SDK viene caricato nel processo dell'app. Bundletool copia tutte le risorse Java dell'SDK in una directory speciale negli asset per app. La libreria client SDKRuntime utilizza un classloader intermedio per reindirizzare tutte le chiamate relative alle risorse Java alla nuova directory root.

Asset SDK

Gli asset dell'SDK vengono uniti agli asset per app senza rimappare.

Spazio di archiviazione SDK

Per supportare SDK Storage, la libreria client di SDK Runtime crea una directory radice dedicata per ogni SDK in bundle nello spazio di archiviazione dell'app e fornisce un contesto speciale che utilizza questa directory come radice di archiviazione.

Questo contesto può essere recuperato da SandboxedSdkProviderCompat#getContext.

Metodi supportati per lo spazio di archiviazione:

  • getDataDir
  • getCacheDir
  • getCodeCacheDir
  • getNoBackupFilesDir
  • getDir
  • getFilesDir
  • openFileInput
  • openFileOutput
  • deleteFile
  • getFileStreamPath
  • fileList
  • getDatabasePath
  • openOrCreateDatabase
  • moveDatabaseFrom: solo tra contesti SDK
  • deleteDatabase
  • databaseList
  • getSharedPreferences
  • moveSharedPreferencesFrom: solo tra contesti SDK
  • deleteSharedPreferences

È possibile creare un contesto di archiviazione protetto del dispositivo chiamando createDeviceProtectedStorageContext() in quel contesto.

SdkSandboxControllerCompat

La libreria client SDKRuntime fornisce l'implementazione SdkSandboxControllerCompat per gli SDK in bundle caricati nel processo dell'app.

Se le API non sono supportate dalla libreria client (ad esempio con un SDK creato con una versione della libreria più recente rispetto alla versione dell'app), verrà utilizzato il fallback più adatto (nessun servizio o un'eccezione).

Controllo delle versioni

Quando la libreria client SDKRuntime carica un SDK in bundle, esegue un handshake con la libreria SDKRuntime Provider all'interno dell'SDK. Durante l'handshake, le librerie scambiano le proprie versioni e modificano il comportamento per sostituire le API non disponibili con le API di riserva più adatte (nessuna operazione o eccezione).

L'utilizzo della versione più recente della libreria è vivamente consigliato sia per gli sviluppatori di app sia per gli sviluppatori di SDK, altrimenti le funzionalità che richiedono supporto in entrambe le parti potrebbero non essere disponibili.

Qualsiasi versione della libreria client SDKRuntime può caricare un SDK con qualsiasi versione della libreria del provider SDKRuntime e viceversa.

In futuro, verrà applicata la versione minima della libreria client necessaria per caricare l'SDK con una determinata versione della libreria del provider.

Questo ridurrà al minimo la frammentazione e contribuirà a garantire che la maggior parte delle API sia supportata se l'SDK in bundle viene caricato correttamente.