| Key concepts | Set up your development environment | Build an RE SDK | Consume the RE SDK | Testing, and building for distribution |
Compila un SDK habilitado para el entorno de ejecución
Para compilar un SDK habilitado para el entorno de ejecución, debes completar los siguientes pasos:
- Configura la estructura de tu proyecto
- Prepara las dependencias de tu proyecto y módulo
- Agrega la lógica empresarial de tu SDK
- Define las APIs del SDK
- Especifica un punto de entrada para tu SDK
Configura la estructura de tu proyecto
Te recomendamos que organices tu proyecto en los siguientes módulos:
- Módulo de la app: Es la app de prueba que usas para probar y desarrollar tu SDK, que representa lo que tendrían tus clientes reales de la app. Tu app debe tener una dependencia en el módulo de biblioteca de anuncios existente (SDK consciente del entorno de ejecución).
- Módulo de biblioteca de anuncios existente (SDK consciente del entorno de ejecución): Es un módulo de biblioteca de Android que contiene tu lógica de SDK existente "no habilitada para el entorno de ejecución", un SDK vinculado de forma estática.
- Para empezar, las capacidades se pueden dividir. Por ejemplo, parte del código puede ser mediante tu SDK existente, y algunos se pueden enrutar al entorno habilitado de Google Cloud.
- Módulo de biblioteca de anuncios habilitado para el entorno de ejecución: Contiene tu SDK habilitado para el entorno de ejecución en la lógica empresarial. Esto se puede crear en Android Studio como un módulo de biblioteca de Android.
- Módulo ASB habilitado para el entorno de ejecución: Define los datos del paquete para empaquetar
código del SDK habilitado para el entorno de ejecución en un ASB.
- Se debe crear manualmente con el com.android.privacy-sandbox-sdk. Puedes hacerlo creando una directorio nuevo.
- Este módulo no debe contener ningún código, solo un archivo build.gradle vacío con dependencias en tu módulo de biblioteca de anuncios habilitado para el entorno de ejecución. El contenido de este archivo se define en Prepara tu SDK.
- Recuerda incluir este módulo en el archivo settings.gradle y en el módulo de biblioteca de anuncios existente.
La estructura del proyecto en esta guía es una sugerencia. Puedes elegir una estructura diferente para tu SDK y aplicar los mismos principios técnicos. Siempre puedes crear otros módulos adicionales para modularizar el código en la app y los módulos de biblioteca.
Prepara el SDK
Si quieres preparar tu proyecto para el desarrollo del SDK habilitado para el entorno de ejecución, debes hacer lo siguiente: primero define algunas dependencias de bibliotecas y herramientas:
- con las bibliotecas de retrocompatibilidad del entorno de ejecución de SDK, que admiten
dispositivos que no cuentan con Privacy Sandbox (Android 13 y versiones anteriores)
(
androidx.privacysandbox.sdkruntime:) - Bibliotecas de IU que admiten la presentación de anuncios (
androidx.privacysandbox.ui:) - Herramientas para desarrolladores del SDK que admiten la declaración de API del SDK y la generación de corrección de compatibilidad (
androidx.privacysandbox.tools:)
Agrega esta marca al archivo gradle.properties de tu proyecto para habilitar la capacidad de crear SDK habilitados para el entorno de ejecución.
# This enables the Privacy Sandbox for your project on Android Studio. android.experimental.privacysandboxsdk.enable=true android.experimental.privacysandboxsdk.requireServices=falseModifica el build.gradle de tu proyecto para incluir las bibliotecas auxiliares de Jetpack y otras dependencias:
// 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 }Actualiza el archivo build.gradle en el módulo de la biblioteca de anuncios habilitada para el entorno de ejecución (SDK habilitado para el entorno de ejecución) para incluir estas dependencias.
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" }Reemplaza el archivo build.gradle en tu módulo ASB habilitado para el entorno de ejecución con lo siguiente:
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>') }Actualiza el archivo build.gradle en el módulo de la biblioteca de anuncios existente (SDK de RA) para incluir las siguientes dependencias:
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" }
Agrega la lógica empresarial del SDK
Implementa la lógica empresarial de tu SDK como lo harías normalmente dentro del módulo de biblioteca de anuncios habilitado para el entorno de ejecución.
Si ya tienes un SDK que estás migrando, mueve la mayor parte de la lógica empresarial, la interfaz y las funciones orientadas al sistema que desees en esta etapa, pero ten en cuenta una migración completa en el futuro.
Si necesitas acceso al almacenamiento, al ID de publicidad de Google Play o al ID del conjunto de apps, consulta las siguientes secciones:
Usa las APIs de Storage en tu SDK
Los SDKs en el entorno de ejecución de SDK ya no pueden acceder al almacenamiento interno de una app, ni leerlo ni escribirlo. y viceversa.
Al entorno de ejecución de SDK se le asigna su propia área de almacenamiento interno, separada de la app.
Los SDKs pueden acceder a este almacenamiento interno independiente a través de las APIs de almacenamiento de archivos en el objeto Context que muestra SandboxedSdkProvider#getContext().
Los SDKs solo pueden usar el almacenamiento interno, por lo que solo las APIs de almacenamiento interno, como Context.getFilesDir() o
Context.getCacheDir() trabajo. Consulta más ejemplos en
Acceso desde el almacenamiento interno.
No se admite el acceso al almacenamiento externo desde el entorno de ejecución del SDK. Llamar a las APIs para acceder al almacenamiento externo arrojará una excepción o mostrará un valor nulo. En la siguiente lista, se incluyen algunos ejemplos:
- El acceso a los archivos con el framework de acceso al almacenamiento arroja una SecurityException.
getExternalFilsDir()siempre muestra un valor nulo.
Debes usar el Context que muestra SandboxedSdkProvider.getContext() para el almacenamiento. No se garantiza que el uso de la API de almacenamiento de archivos en cualquier otra instancia de objeto Context, como el contexto de la aplicación, funcione como se espera en todas las situaciones.
En el siguiente fragmento de código, se muestra cómo usar el almacenamiento en el entorno de ejecución del SDK:
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" } }
Dentro del almacenamiento interno independiente para cada entorno de ejecución de SDK, cada SDK tiene su propio directorio de almacenamiento. El almacenamiento por SDK es una separación lógica del almacenamiento interno del entorno de ejecución de SDK que ayuda a conocer la cantidad de almacenamiento que usa cada uno.
Todas las APIs de almacenamiento interno del objeto Context muestran una ruta de almacenamiento para cada SDK.
Accede al ID de publicidad que brindan los Servicios de Google Play
Si tu SDK necesita acceder al ID de publicidad que brindan los Servicios de Google Play, usa AdIdManager#getAdId() para recuperar el valor de forma asíncrona.
Accede al ID del conjunto de apps que brindan los Servicios de Google Play
Si tu SDK necesita acceder al ID del conjunto de apps que brindan los Servicios de Google Play, usa
AppSetIdManager#getAppSetId() para recuperar el valor de forma asíncrona.
Declara las APIs del SDK
Para que se pueda acceder al SDK habilitado para el entorno de ejecución fuera de este, para definir las APIs que los clientes (el SDK de RA o la aplicación cliente) pueden consumir.
Usa anotaciones para declarar estas interfaces.
Anotaciones
Las APIs del SDK deben declararse en Kotlin como interfaces y clases de datos con el siguientes anotaciones:
| Anotaciones | |
|---|---|
@PrivacySandboxService |
|
@PrivacySandboxInterface |
|
@PrivacySandboxValue |
|
@PrivacySandboxCallback |
|
Debes definir estas interfaces y clases en cualquier lugar del módulo de la biblioteca de anuncios habilitado para el entorno de ejecución.
Consulta el uso de estas anotaciones en las siguientes secciones.
@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() }
Tipos admitidos
Las APIs del SDK habilitado para el entorno de ejecución admiten los siguientes tipos:
- Todos los tipos primitivos del lenguaje de programación Java (como int, long, char, boolean, etc.)
- String
- Interfaces de Kotlin con anotaciones
@PrivacySandboxInterfaceo@PrivacySandboxCallback - Clases de datos de Kotlin con anotaciones
@PrivacySandboxValue - java.lang.List: Todos los elementos de la lista deben ser uno de los datos admitidos. tipos
Ten en cuenta las siguientes advertencias adicionales:
- Las clases de datos con anotaciones
@PrivacySandboxValueno pueden contener campos de tipo@PrivacySandboxCallback. - Los tipos de datos que se muestran no pueden contener tipos anotados con
@PrivacySandboxCallback - La lista no puede contener elementos de tipos con anotaciones
@PrivacySandboxInterfaceo@PrivacySandboxCallback
APIs asíncronas
Como las APIs del SDK siempre realizan una llamada a un proceso independiente, debemos asegúrate de que estas llamadas no bloqueen el subproceso de llamada del cliente.
Para lograrlo, todos los métodos de las interfaces anotadas con
@PrivacySandboxService, @PrivacySandboxInterface y @PrivacySandboxCallback
deben declararse explícitamente como APIs asíncronas.
Las APIs asíncronas se pueden implementar en Kotlin de dos maneras:
- Usa funciones de suspensión.
- Aceptar devoluciones de llamada que reciban notificaciones cuando se complete la operación otros eventos durante el progreso de la operación. El tipo de datos que se muestra de la función debe ser una unidad.
Excepciones
Las APIs del SDK no admiten ninguna forma de excepciones verificadas.
El código de corrección de compatibilidad generado captura todas las excepciones de tiempo de ejecución que arroja el SDK y
los muestra como un PrivacySandboxException al cliente con información sobre
la causa que envuelve a él.
Biblioteca de IU
Si tienes interfaces que representan anuncios, como un banner, también debes implementar la interfaz SandboxedUiAdapter para habilitar las sesiones de apertura del anuncio cargado.
Estas sesiones forman un canal lateral entre el cliente y el SDK, cumplir con dos objetivos principales:
- Recibe notificaciones cada vez que se produzca un cambio en la IU.
- Notifica al cliente sobre cualquier cambio en la presentación de la IU.
Dado que el cliente puede usar la interfaz anotada con @PrivacySandboxService para
comunicarse con el SDK, se pueden agregar APIs para cargar anuncios
interfaz de usuario.
Cuando el cliente solicita cargar un anuncio, carga el anuncio y muestra una instancia de
la interfaz que implementa SandboxedUiAdapter Esto permite que el cliente solicite la apertura de sesiones para ese anuncio.
Cuando el cliente solicita abrir una sesión, el SDK habilitado para el entorno de ejecución puede crear una vista de anuncio usando la respuesta del anuncio y el contexto proporcionado.
Para lograrlo, crea una clase que implemente la interfaz SandboxedUiAdapter.Session y, cuando se llame a SandboxedUiAdapter.openSession(), asegúrate de llamar a client.onSessionOpened() pasando una instancia de la clase Session como parámetro.
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)
}
}
}
Esta clase también recibe notificaciones cada vez que se produce un cambio de IU. Puedes usar esta clase para cambiar el tamaño del anuncio o saber cuándo cambió la configuración, por ejemplo.
Obtén más información sobre las APIs de presentación de la IU en el entorno de ejecución.
Compatibilidad con actividades
Para iniciar actividades que pertenecen al SDK desde Privacy Sandbox, debes modificar la API del SDK para recibir un objeto SdkActivityLauncher, que también proporciona la biblioteca de la IU.
Por ejemplo, la siguiente API del SDK debería iniciar actividades, por lo que espera el parámetro SdkActivityLauncher:
@PrivacySandboxInterface
interface FullscreenAd {
suspend fun show(activityLauncher: SdkActivityLauncher)
}
Punto de entrada del SDK
La clase abstracta SandboxedSdkProvider
encapsula la API que usa el entorno de ejecución de SDK para interactuar con los SDKs cargados en él.
Un SDK habilitado para el entorno de ejecución debe implementar esta clase abstracta para generar un punto de entrada para que el entorno de ejecución del SDK pueda comunicarse con él.
Para ofrecer compatibilidad con versiones anteriores, incorporamos las siguientes clases:
SandboxedSdkProviderAdapter, que extiendeSandboxedSdkProvidery controla las solicitudes de carga de SDKs independientemente de la disponibilidad del entorno de ejecución de SDK. Se usa internamente, declarado en el módulo de ASB.SandboxedSdkProviderCompat, una clase abstracta que imita la interfaz deSandboxedSdkProvider
Obtén más información sobre la retrocompatibilidad con el entorno de ejecución de SDK.
Las herramientas de generación de shims agregan otra capa de abstracción: generan una clase abstracta llamada AbstractSandboxedSdkProvider con la interfaz que anotaste con @PrivacySandboxService.
Esta clase extiende SandboxedSdkProviderCompat y se encuentra en el mismo paquete que tu interfaz con anotaciones.
// Auto-generated code.
abstract class AbstractSandboxedSdkProvider : SandboxedSdkProviderCompat {
abstract fun createMySdk(context: Context): MySdk
}
Esta clase generada expone un único método de fábrica abstracto que toma un
Context y espera que se muestre tu interfaz con anotaciones de punto de entrada.
Este método se nombra según tu interfaz @PrivacySandboxService y se antepone create al nombre. Por ejemplo, si tu interfaz se llama MySdk, las herramientas
genera createMySdk.
Para conectar completamente tu punto de entrada, debes proporcionar una implementación de tu interfaz con anotaciones @PrivacySandboxService en el SDK habilitado para el entorno de ejecución al AbstractSandboxedSdkProvider generado.
class MySdkSandboxedSdkProvider : AbstractSandboxedSdkProvider() {
override fun createMySdk(context: Context): MySdk = MySdkImpl(context)
}
Cambios en el módulo de ASB
Debes declarar el nombre de clase completamente calificado de tu implementación de SandboxedSdkProviderCompat en el campo compatSdkProviderClassName del build.gradle de tu módulo ASB.
Esta es la clase que implementaste en el paso anterior, y deberías modificar build.gradle en tu módulo ASB de la siguiente manera:
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"
}
Paso 2: Configura tu entorno de desarrollo Paso 4: Usa el SDK habilitado para el entorno de ejecución