Key concepts | Set up your development environment | Build an RE SDK | Consume the RE SDK | Testing, and building for distribution |
Crea un SDK abilitato per il runtime
Per creare un SDK abilitato per il runtime, devi completare i seguenti passaggi:
- Configurare la struttura del progetto
- Prepara le dipendenze del progetto e dei moduli
- Aggiungi la logica di business dell'SDK
- Definire le API SDK
- Specificare un punto di ingresso per il tuo SDK
Configura la struttura del progetto
Ti consigliamo di organizzare il progetto nei seguenti moduli:
- Modulo App: l'app di test che stai utilizzando per testare e sviluppare la tua che rappresenta ciò che avrebbero avuto i tuoi clienti di app reali. La tua app deve avere una dipendenza dal modulo della libreria di annunci esistente (SDK consapevole del runtime).
- Modulo esistente della libreria di annunci (SDK che supporta il runtime): un modulo della libreria Android
che contiene i valori "non abilitati per il runtime" della logica SDK, in modo statico
SDK collegato.
- Per iniziare, le funzionalità possono essere suddivise. Ad esempio, una parte di codice gestite dall'SDK esistente e alcune possono essere indirizzate all'account abilitato per il runtime l'SDK.
- Modulo della libreria di annunci abilitata per il runtime: contiene la logica di business dell'SDK abilitato per il runtime. Può essere creato in Android Studio come libreria Android. in maggior dettaglio più avanti in questo modulo.
- Modulo ASB abilitato per il runtime: definisce i dati del pacchetto per raggruppare il codice SDK abilitato per il runtime in un ASB.
- Deve essere creato manualmente utilizzando il tipo com.android.privacy-sandbox-sdk. Puoi farlo creando un nella nuova directory.
- Questo modulo non deve contenere codice e solo un file build.gradle vuoto con dipendenze del modulo della libreria di annunci abilitato per il runtime. I contenuti di questo file sono definiti in Preparare l'SDK.
- Ricordati di includere questo modulo nel file settings.gradle e nel modulo della libreria pubblicitaria esistente.
La struttura del progetto in questa guida è un suggerimento. Puoi scegliere una struttura diversa per il tuo SDK e applicare gli stessi principi tecnici. Puoi sempre creare altri moduli aggiuntivi per modularizzare il codice nei moduli dell'app e della libreria.
Prepara l'SDK
Per preparare il progetto per lo sviluppo di un SDK abilitato per il runtime, devi devi prima definire alcuni strumenti e dipendenze delle librerie:
- Librerie di compatibilità con le versioni precedenti del runtime dell'SDK, che forniscono supporto per i dispositivi che non dispongono di Privacy Sandbox (Android 13 e versioni precedenti)
(
androidx.privacysandbox.sdkruntime:
) - Librerie UI per supportare la presentazione degli annunci (
androidx.privacysandbox.ui:
) - Strumenti per sviluppatori SDK per supportare la dichiarazione dell'API SDK e la generazione di shim (
androidx.privacysandbox.tools:
)
Aggiungi questo flag al file gradle.properties del progetto per abilitare la possibilità di creare SDK abilitati per il runtime.
# This enables the Privacy Sandbox for your project on Android Studio. android.experimental.privacysandboxsdk.enable=true android.experimental.privacysandboxsdk.requireServices=false
Modifica il file build.gradle del progetto in modo da includere le librerie di assistenza Jetpack e altre dipendenze:
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.kotlin_version = '1.9.10' ext.ksp_version = "$kotlin_version-1.0.13" ext.privacy_sandbox_activity_version = "1.0.0-alpha01" ext.privacy_sandbox_sdk_runtime_version = "1.0.0-alpha13" ext.privacy_sandbox_tools_version = "1.0.0-alpha09" ext.privacy_sandbox_ui_version = "1.0.0-alpha09" repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } plugins { id 'com.android.application' version '8.4.0-alpha13' apply false id 'com.android.library' version '8.4.0-alpha13' apply false // These two plugins do annotation processing and code generation for the sdk-implementation. id 'androidx.privacysandbox.library' version '1.0.0-alpha02' apply false id 'com.google.devtools.ksp' version "$ksp_version" apply false id 'org.jetbrains.kotlin.jvm' version '1.9.10' apply false } task clean(type: Delete) { delete rootProject.buildDir }
Aggiorna il file build.gradle nel modulo Libreria di annunci abilitata per il runtime (SDK RE) per includere queste dipendenze.
dependencies { // This allows Android Studio to parse and validate your SDK APIs. ksp "androidx.privacysandbox.tools:tools-apicompiler:$privacy_sandbox_tools_version" // This contains the annotation classes to decorate your SDK APIs. implementation "androidx.privacysandbox.tools:tools:$privacy_sandbox_tools_version" // This is runtime dependency required by the generated server shim code for // backward compatibility. implementation "androidx.privacysandbox.sdkruntime:sdkruntime-provider:$privacy_sandbox_sdk_runtime_version" // These are runtime dependencies required by the generated server shim code as // they use Kotlin. implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1' // This is the core part of the UI library to help with UI notifications. implementation "androidx.privacysandbox.ui:ui-core:$privacy_sandbox_ui_version" // This helps the SDK open sessions for the ad. implementation "androidx.privacysandbox.ui:ui-provider:$privacy_sandbox_ui_version" // This is needed if your SDK implements mediation use cases implementation "androidx.privacysandbox.ui:ui-client:$privacy_sandbox_ui_version" }
Sostituisci il file build.gradle nel modulo ASB abilitato per il runtime con quanto segue:
plugins { id 'com.android.privacy-sandbox-sdk' } android { compileSdk 34 minSdk 21 bundle { // This is the package name of the SDK that you want to publish. // This is used as the public identifier of your SDK. // You use this later on to load the runtime-enabled SDK packageName = '<package name of your runtime-enabled SDK>' // This is the version of the SDK that you want to publish. // This is used as the public identifier of your SDK version. setVersion(1, 0, 0) // SDK provider defined in the SDK Runtime library. // This is an important part of the future backwards compatibility // support, most SDKs won't need to change it. sdkProviderClassName = "androidx.privacysandbox.sdkruntime.provider.SandboxedSdkProviderAdapter" // This is the class path of your implementation of the SandboxedSdkProviderCompat class. // It's the implementation of your runtime-enabled SDK's entry-point. // If you miss this step, your runtime-enabled SDK will fail to load at runtime: compatSdkProviderClassName = "<your-sandboxed-sdk-provider-compat-fully-qualified-class-name>" } } dependencies { // This declares the dependency on your runtime-enabled ad library module. include project(':<your-runtime-enabled-ad-library-here>') }
Aggiorna il file build.gradle nel modulo della libreria annunci esistente (SDK RA) in modo da includere le seguenti dipendenze:
dependencies { // This declares the client's dependency on the runtime-enabled ASB module. // ⚠️ Important: We depend on the ASB module, not the runtime-enabled module. implementation project(':<your-runtime-enabled-asb-module-here>') // Required for backwards compatibility on devices where SDK Runtime is unavailable. implementation "androidx.privacysandbox.sdkruntime:sdkruntime-client:$privacy_sandbox_sdk_runtime_version" // This is required to display banner ads using the SandboxedUiAdapter interface. implementation "androidx.privacysandbox.ui:ui-core:$privacy_sandbox_ui_version" implementation "androidx.privacysandbox.ui:ui-client:$privacy_sandbox_ui_version" // This is required to use SDK ActivityLaunchers. implementation "androidx.privacysandbox.activity:activity-core:$privacy_sandbox_activity_version" implementation "androidx.privacysandbox.activity:activity-client:$privacy_sandbox_activity_version" }
Aggiungi la logica di business dell'SDK
Implementa la logica di business dell'SDK come faresti regolarmente nella modulo della libreria di annunci abilitato per il runtime.
Se stai eseguendo la migrazione di un SDK esistente, in questa fase sposta tutte le funzioni della logica di business, dell'interfaccia e del sistema che vuoi, ma tieni conto di una migrazione completa in futuro.
Se hai bisogno di accedere allo spazio di archiviazione, all'ID pubblicità di Google Play o all'ID set di app, leggi le seguenti sezioni:
Utilizzare le API di archiviazione nell'SDK
Gli SDK in SDK Runtime non possono più accedere, leggere o scrivere nella memoria interna di un'app e viceversa.
All'ambiente di runtime dell'SDK viene allocata una propria area di archiviazione interna, separata dall'app.
Gli SDK sono in grado di accedere a questo spazio di archiviazione interno separato utilizzando le API di archiviazione dei file nell'oggetto Context
restituito da SandboxedSdkProvider#getContext()
.
Gli SDK possono usare solo la memoria interna; di conseguenza, solo le API di archiviazione interna, come Context.getFilesDir()
o
Context.getCacheDir()
lavoro. Vedi altri esempi in
Accesso dalla memoria interna.
L'accesso allo spazio di archiviazione esterno da SDK Runtime non è supportato. La chiamata delle API per accedere allo spazio di archiviazione esterno genera un'eccezione o restituisce null. Il seguente elenco include alcuni esempi:
- L'accesso ai file utilizzando Storage Access Framework genera un'eccezione SecurityException.
getExternalFilsDir()
restituisce sempre null.
Devi utilizzare Context
restituito da SandboxedSdkProvider.getContext()
per l'archiviazione. L'utilizzo dell'API di archiviazione file su qualsiasi altra istanza di oggetto Context
, ad esempio il contesto dell'applicazione, non è garantito che funzioni come previsto in tutte le situazioni.
Il seguente snippet di codice mostra come utilizzare lo spazio di archiviazione in SDK Runtime:
class SdkServiceImpl(private val context: Context) : SdkService { override suspend fun getMessage(): String = "Hello from Privacy Sandbox!" override suspend fun createFile(sizeInMb: Int): String { val path = Paths.get( context.dataDir.path, "file.txt" ) withContext(Dispatchers.IO) { Files.deleteIfExists(path) Files.createFile(path) val buffer = ByteArray(sizeInMb * 1024 * 1024) Files.write(path, buffer) } val file = File(path.toString()) val actualFileSize: Long = file.length() / (1024 * 1024) return "Created $actualFileSize MB file successfully" } }
All'interno dello spazio di archiviazione interno separato per ogni runtime dell'SDK, ogni SDK ha la propria directory di archiviazione. Lo spazio di archiviazione per SDK è una separazione logica dello spazio di archiviazione interno di SDK Runtime che consente di tenere conto della quantità di spazio di archiviazione utilizzata da ciascun SDK.
Tutte le API di archiviazione interna nell'oggetto Context
restituiscono un percorso di archiviazione per ogni SDK.
Accedere all'ID pubblicità fornito da Google Play Services
Se il tuo SDK deve accedere all'ID pubblicità fornito da Google Play Services, utilizza AdIdManager#getAdId()
per recuperare il valore in modo asincrono.
Accedere all'ID set di app fornito da Google Play Services
Se il tuo SDK richiede l'accesso all'ID set di app fornito da Google Play Services, usa
AppSetIdManager#getAppSetId()
per recuperare il valore in modo asincrono.
Dichiara le API SDK
Affinché l'SDK abilitato per il runtime sia accessibile al di fuori del runtime, devi per definire le API utilizzabili dai client (SDK RA o app client).
Utilizza le annotazioni per dichiarare queste interfacce.
Annotazioni
Le API SDK devono essere dichiarate in Kotlin come interfacce e classi di dati utilizzando le seguenti annotazioni:
Annotazioni | |
---|---|
@PrivacySandboxService |
|
@PrivacySandboxInterface |
|
@PrivacySandboxValue |
|
@PrivacySandboxCallback |
|
Devi definire queste interfacce e classi in qualsiasi punto del modulo della libreria di annunci abilitata in fase di runtime.
Vedi l'utilizzo di queste annotazioni nelle sezioni seguenti.
@PrivacySandboxService
@PrivacySandboxService interface SdkService { suspend fun getMessage(): String suspend fun createFile(sizeInMb: Int): String suspend fun getBanner(request: SdkBannerRequest, requestMediatedAd: Boolean): SdkSandboxedUiAdapter? suspend fun getFullscreenAd(): FullscreenAd }
@PrivacySandboxInterface
@PrivacySandboxInterface interface SdkSandboxedUiAdapter : SandboxedUiAdapter
@PrivacySandboxValue
@PrivacySandboxValue data class SdkBannerRequest( /** The package name of the app. */ val appPackageName: String, /** * An [SdkActivityLauncher] used to launch an activity when the banner is clicked. */ val activityLauncher: SdkActivityLauncher, /** * Denotes if a WebView banner ad needs to be loaded. */ val isWebViewBannerAd: Boolean )
@PrivacySandboxCallback
@PrivacySandboxCallback interface InAppMediateeSdkInterface { suspend fun show() }
Tipi supportati
Le API SDK abilitate per il runtime supportano i seguenti tipi:
- Tutti i tipi primitivi nel linguaggio di programmazione Java (come int, long, char, booleano e così via)
- Stringa
- Interfacce Kotlin annotate con
@PrivacySandboxInterface
o@PrivacySandboxCallback
- Classi di dati Kotlin annotate con
@PrivacySandboxValue
- java.lang.List: tutti gli elementi nell'elenco devono essere uno dei dati supportati Tipi
Esistono alcuni altri aspetti da tenere presente:
- Le classi di dati annotate con
@PrivacySandboxValue
non possono contenere campi di tipo@PrivacySandboxCallback
- I tipi restituiti non possono contenere tipi annotati con
@PrivacySandboxCallback
- L'elenco non può contenere elementi di tipi annotati con
@PrivacySandboxInterface
o@PrivacySandboxCallback
API asincrone
Poiché le API SDK effettuano sempre una chiamata a un processo separato, assicurati che queste chiamate non blocchino il thread delle chiamate del client.
A questo scopo, tutti i metodi nelle interfacce sono annotati con
@PrivacySandboxService
, @PrivacySandboxInterface
e @PrivacySandboxCallback
devono essere dichiarate esplicitamente
come API asincrone.
Le API asincrone possono essere implementate in Kotlin in due modi:
- Utilizza le funzioni di sospensione.
- Accetta i callback che ricevono una notifica al termine dell'operazione o di altri eventi durante l'avanzamento dell'operazione. Il tipo restituito della funzione deve essere una Unit.
Eccezioni
Le API SDK non supportano nessun tipo di eccezioni selezionate.
Il codice shim generato rileva eventuali eccezioni di runtime generate dall'SDK e
la invia come PrivacySandboxException
al cliente con informazioni
la causa.
libreria UI
Se disponi di interfacce che rappresentano annunci, ad esempio un banner, devi implementare anche l'interfaccia di SandboxedUiAdapter
per abilitare le sessioni di apertura per l'annuncio caricato.
Queste sessioni formano un canale laterale tra il client e l'SDK e soddisfano due scopi principali:
- Ricevi notifiche ogni volta che si verifica un cambiamento dell'interfaccia utente.
- Avvisa il cliente di eventuali modifiche alla presentazione dell'interfaccia utente.
Poiché il client può utilizzare l'interfaccia annotata con @PrivacySandboxService
per
comunicare con il tuo SDK, le API per il caricamento degli annunci possono essere aggiunte a questo
a riga di comando.
Quando il client richiede di caricare un annuncio, carica l'annuncio e restituisci un'istanza dell'interfaccia che implementa SandboxedUiAdapter
. In questo modo, il client può richiedere sessioni di apertura per quell'annuncio.
Quando il client richiede di aprire una sessione, l'SDK abilitato al runtime può creare una visualizzazione dell'annuncio utilizzando la risposta all'annuncio e il contesto fornito.
A questo scopo, crea una classe che implementi l'interfaccia SandboxedUiAdapter.Session
e, quando viene chiamato SandboxedUiAdapter.openSession()
, assicurati di chiamare client.onSessionOpened()
, passando un'istanza della classe Session
come parametro.
class SdkSandboxedUiAdapterImpl(
private val sdkContext: Context,
private val request: SdkBannerRequest,
) : SdkSandboxedUiAdapter {
override fun openSession(
context: Context,
windowInputToken: IBinder,
initialWidth: Int,
initialHeight: Int,
isZOrderOnTop: Boolean,
clientExecutor: Executor,
client: SandboxedUiAdapter.SessionClient
) {
val session = SdkUiSession(clientExecutor, sdkContext, request)
clientExecutor.execute {
client.onSessionOpened(session)
}
}
}
Inoltre, questo corso riceve notifiche ogni volta che si verifica un cambiamento dell'interfaccia utente. Puoi utilizzare questa classe per ridimensionare l'annuncio o sapere, ad esempio, quando la configurazione è stata modificata.
Scopri di più sulle API di presentazione dell'interfaccia utente nel runtime.
Assistenza per l'attività
Per avviare le attività di proprietà dell'SDK da Privacy Sandbox, devi modificare l'API SDK per ricevere un oggetto SdkActivityLauncher
, fornito anch'esso dalla libreria UI.
Ad esempio, la seguente API SDK dovrebbe avviare delle attività, quindi è previsto il parametro SdkActivityLauncher
:
@PrivacySandboxInterface
interface FullscreenAd {
suspend fun show(activityLauncher: SdkActivityLauncher)
}
Entry-point SDK
La classe astratta SandboxedSdkProvider
incapsula l'API che SDK Runtime utilizza per interagire con gli SDK caricati al suo interno.
Un SDK abilitato per il runtime deve implementare questa classe astratta per generare un punto di ingresso affinché il runtime dell'SDK sia in grado di comunicare con quest'ultima.
Per il supporto della compatibilità con le versioni precedenti, abbiamo introdotto i seguenti tipi di classe:
SandboxedSdkProviderAdapter
, che estendeSandboxedSdkProvider
e gestisce le richieste di caricamento dell'SDK indipendentemente dalla disponibilità di SDK Runtime. Viene utilizzato internamente e dichiarato nel modulo ASB.SandboxedSdkProviderCompat
, una classe astratta che imita l'interfaccia dell'SandboxedSdkProvider
.
Scopri di più sulla compatibilità con le versioni precedenti di SDK Runtime.
Gli strumenti di generazione di shim aggiungono un altro livello di astrazione: generano una classe astratta denominata AbstractSandboxedSdkProvider
utilizzando l'interfaccia annotata con @PrivacySandboxService
.
Questa classe estende SandboxedSdkProviderCompat
e si trova all'interno dello stesso pacchetto dell'interfaccia annotata.
// Auto-generated code.
abstract class AbstractSandboxedSdkProvider : SandboxedSdkProviderCompat {
abstract fun createMySdk(context: Context): MySdk
}
Questa classe generata espone un singolo metodo di fabbrica astratto che accetta una
Context
e prevede che venga restituito l'interfaccia annotata del tuo punto di ingresso.
Questo metodo prende il nome dall'interfaccia @PrivacySandboxService
, con create
premesso al nome. Ad esempio, se l'interfaccia si chiama MySdk
, gli strumenti genereranno createMySdk
.
Per connettere completamente il tuo punto di ingresso, devi fornire un'implementazione dell'interfaccia annotata @PrivacySandboxService
nell'SDK abilitato per il runtime all'elemento AbstractSandboxedSdkProvider
generato.
class MySdkSandboxedSdkProvider : AbstractSandboxedSdkProvider() {
override fun createMySdk(context: Context): MySdk = MySdkImpl(context)
}
Modifiche al modulo ASB
Devi dichiarare il nome completo della classe dell'implementazione di SandboxedSdkProviderCompat
nel campo compatSdkProviderClassName
di build.gradle del modulo ASB.
Questa è la classe che hai implementato nel passaggio precedente. Devi modificare build.gradle sul modulo ASB nel seguente modo:
bundle {
packageName = '<package name of your runtime-enabled SDK>'
setVersion(1, 0, 0)
// SDK provider defined in the SDK Runtime library.
sdkProviderClassName = "androidx.privacysandbox.sdkruntime.provider.SandboxedSdkProviderAdapter"
// This is the class that extends AbstractSandboxedSdkProvider,
// MySdkSandboxProvider as per the example provided.
compatSdkProviderClassName = "com.example.mysdk.MySdkSandboxProvider"
}
Passaggio 2: configura l'ambiente di sviluppoPassaggio 4: utilizza l'SDK abilitato per il runtime