Guía para desarrolladores del entorno de ejecución de SDK

A medida que leas la documentación de Privacy Sandbox en Android, usa el botón Versión preliminar para desarrolladores o Beta para seleccionar la versión del programa con la que estás trabajando, ya que las instrucciones pueden variar.


Enviar comentarios

El entorno de ejecución de SDK permite que los SDKs se ejecuten en una zona de pruebas dedicada independiente de la app que realiza la llamada. El entorno de ejecución de SDK proporciona mejores protecciones y garantías en cuanto a la recopilación de datos del usuario. Esto se hace a través de un entorno de ejecución modificado que limita los derechos de acceso a los datos y el conjunto de permisos que pueden otorgarse. Obtén más información sobre el entorno de ejecución del SDK en la propuesta de diseño.

Los pasos que se indican en esta página te guiarán a través del proceso de creación de un SDK habilitado para el entorno de ejecución que define una vista basada en la Web que se puede renderizar, de forma remota, en una app que realiza la llamada.

Limitaciones conocidas

Si quieres ver una lista de las funciones en curso para el entorno de ejecución de SDK, consulta las notas de la versión.

Se espera que las siguientes limitaciones se corrijan en la próxima actualización importante de la plataforma de Android.

  • Renderización de anuncios dentro de una vista que admite desplazamiento (por ejemplo, RecyclerView no funciona correctamente)
    • Es posible que experimentes bloqueos al cambiar el tamaño.
    • Los eventos de desplazamiento táctil del usuario no se pasan correctamente al entorno de ejecución.
  • API de Storage.

El siguiente problema se corregirá en 2023:

  • Las APIs de getAdId y getAppSetId aún no funcionan correctamente, ya que todavía se está trabajando en la compatibilidad.

Antes de comenzar

Antes de comenzar, completa los siguientes pasos:

  1. Configura tu entorno de desarrollo para Privacy Sandbox en Android. Las herramientas para admitir el entorno de ejecución de SDK están en desarrollo activo, por lo que en esta guía deberás usar la versión Canary de Android Studio más reciente. Puedes ejecutar esta versión de Android Studio en paralelo a otras versiones que uses; te pedimos que nos cuentes si este requisito no funciona en tu caso.

  2. Instala una imagen del sistema en un dispositivo compatible o configura un emulador que incluya compatibilidad con Privacy Sandbox en Android.

Configura tu proyecto en Android Studio

Para probar el entorno de ejecución de SDK, usa un modelo similar al modelo cliente-servidor. La principal diferencia es que las apps (el cliente) y los SDKs (el "servidor") se ejecutan en el mismo dispositivo.

  1. Agrega un módulo de app a tu proyecto. Este módulo funciona como el cliente que controla el SDK.
  2. En el módulo de tu app, habilita el entorno de ejecución de SDK, declara los permisos necesarios y configura los servicios de anuncios específicos de la API.
  3. Agrega un módulo de biblioteca a tu proyecto. Este módulo contiene tu código del SDK.
  4. En el módulo del SDK, declara los permisos necesarios. No necesitas configurar servicios de anuncios específicos de APIs en este módulo.
  5. Quita las dependencies del archivo build.gradle del módulo de la biblioteca que no usa el SDK. En la mayoría de los casos, puedes quitar todas las dependencias. Puedes hacerlo creando un directorio nuevo cuyo nombre corresponda a tu SDK.
  6. Crea manualmente un módulo nuevo con el tipo com.android.privacy-sandbox-sdk. Este se incluye con el código del SDK para crear un APK que se pueda implementar en tu dispositivo. Puedes hacerlo creando un directorio nuevo cuyo nombre corresponda a tu SDK. Agrega un archivo build.gradle vacío. El contenido de este archivo se completará más adelante en esta guía.

  7. Agrega el siguiente fragmento a tu archivo gradle.properties:

    android.experimental.privacysandboxsdk.enable=true
    

  8. Descarga la imagen del emulador Tiramisu (nivel de extensión 4) y crea un emulador con esta imagen que incluya Play Store.

En función de si eres un desarrollador de SDKs o de apps, es posible que tengas una configuración final diferente a la que se describe en el párrafo anterior.

Instala el SDK en un dispositivo de prueba, de manera similar a como instalarías una app, con Android Studio o Android Debug Bridge (ADB). Para ayudarte a comenzar, creamos apps de ejemplo en los lenguajes de programación Kotlin y Java, que puedes encontrar en este repositorio de GitHub. Los archivos de manifiesto y readme contienen comentarios que describen qué se debe cambiar para ejecutar las apps de ejemplo en versiones estables de Android Studio.

Prepara el SDK

  1. Crea un directorio de nivel de módulo de forma manual. Esto sirve como wrapper del código de implementación para compilar el APK del SDK. Agrega un archivo build.gradle en el directorio nuevo e incluye en él el siguiente fragmento. Usa un nombre único para el SDK habilitado para el entorno de ejecución y proporciona una versión. Incluye el módulo de biblioteca en la sección dependencies.

    plugins {
        id 'com.android.privacy-sandbox-sdk'
    }
    
    android {
        compileSdk 33
        compileSdkExtension 4
        minSdk 33
        targetSdk 33
        namespace = "com.example.example-sdk"
    
        bundle {
            packageName = "com.example.privacysandbox.provider"
            sdkProviderClassName = "com.example.sdk_implementation.SdkProviderImpl"
            setVersion(1, 0, 0)
        }
    }
    
    dependencies {
        include project(':<your-library-here>')
    }
    
  2. Crea una clase en la biblioteca de implementación de modo que funcione como punto de entrada para el SDK. Se le debe asignar el valor de sdkProviderClassName al nombre y extender SandboxedSdkProvider.

El punto de entrada de tu SDK extiende SandboxedSdkProvider. SandboxedSdkProvider contiene un objeto Context para tu SDK, al que puedes acceder si llamas a getContext(). Solo se debe acceder a este contexto una vez que se invocó onLoadSdk().

Para que se compile tu app del SDK, debes anular métodos para controlar el ciclo de vida del SDK:

onLoadSdk()

Carga el SDK en la zona de pruebas y notifica a la app que realiza la llamada cuando este esté listo para controlar las solicitudes pasando su interfaz como un objeto IBinder que está unido a un nuevo objeto SandboxedSdk. En la guía de servicios vinculados, se detallan diferentes formas de proporcionar IBinder. Puedes elegir la que prefieras, pero debe haber coherencia entre el SDK y la app que realiza la llamada.

Con AIDL como ejemplo, debes definir un archivo AIDL para presentar tu IBinder, que la app compartirá y usará:

// ISdkInterface.aidl
interface ISdkInterface {
    // the public functions to share with the App.
    int doSomething();
}
getView()

Crea y configura la vista de tu anuncio, inicializa la vista de la misma manera que cualquier otra vista de Android y muestra la vista de modo que se renderice de forma remota en una ventana de un ancho y una altura determinados en píxeles.

En el siguiente fragmento de código, se muestra cómo anular estos métodos:

Kotlin

class SdkProviderImpl : SandboxedSdkProvider() {
    override fun onLoadSdk(params: Bundle?): SandboxedSdk {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return SandboxedSdk(SdkInterfaceProxy())
    }

    override fun getView(windowContext: Context, bundle: Bundle, width: Int,
            height: Int): View {
        val webView = WebView(windowContext)
        val layoutParams = LinearLayout.LayoutParams(width, height)
        webView.setLayoutParams(layoutParams)
        webView.loadUrl("https://developer.android.com/privacy-sandbox")
        return webView
    }

    private class SdkInterfaceProxy : ISdkInterface.Stub() {
        fun doSomething() {
            // Implementation of the API.
        }
    }
}

Java

public class SdkProviderImpl extends SandboxedSdkProvider {
    @Override
    public SandboxedSdk onLoadSdk(Bundle params) {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return new SandboxedSdk(new SdkInterfaceProxy());
    }

    @Override
    public View getView(Context windowContext, Bundle bundle, int width,
            int height) {
        WebView webView = new WebView(windowContext);
        LinearLayout.LayoutParams layoutParams =
                new LinearLayout.LayoutParams(width, height);
        webView.setLayoutParams(layoutParams);
        webView.loadUrl("https://developer.android.com/privacy-sandbox");
        return webView;
    }

    private static class SdkInterfaceProxy extends ISdkInterface.Stub {
        @Override
        public void doSomething() {
            // Implementation of the API.
        }
    }
}

Cómo probar reproductores de video en el entorno de ejecución de SDK

Además de admitir anuncios de banner, Privacy Sandbox se compromete a admitir los reproductores de video que se ejecutan dentro del entorno de ejecución de SDK.

El flujo para probar reproductores de video es similar al de probar anuncios de banner. Cambia el método getView() del punto de entrada de tu SDK para incluir un reproductor de video en el objeto View que se muestra. Prueba todos los flujos del reproductor de video que esperas que sean compatibles con Privacy Sandbox. Ten en cuenta que la comunicación entre el SDK y la app cliente sobre el ciclo de vida del video está fuera del alcance, por lo que aún no se requieren comentarios para esta funcionalidad.

Tus pruebas y comentarios garantizarán que el entorno de ejecución de SDK sea compatible con todos los casos de uso de tu reproductor de video preferido.

En el siguiente fragmento de código, se demuestra cómo mostrar una vista de video simple que se carga desde una URL.

Kotlin

    class SdkProviderImpl : SandboxedSdkProvider() {

        override fun getView(windowContext: Context, bundle: Bundle, width: Int,
                height: Int): View {
            val videoView = VideoView(windowContext)
            val layoutParams = LinearLayout.LayoutParams(width, height)
            videoView.setLayoutParams(layoutParams)
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"))
            videoView.setOnPreparedListener { mp -> mp.start() }
            return videoView
        }
    }

Java

    public class SdkProviderImpl extends SandboxedSdkProvider {

        @Override
        public View getView(Context windowContext, Bundle bundle, int width,
                int height) {
            VideoView videoView = new VideoView(windowContext);
            LinearLayout.LayoutParams layoutParams =
                    new LinearLayout.LayoutParams(width, height);
            videoView.setLayoutParams(layoutParams);
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"));
            videoView.setOnPreparedListener(mp -> {
                mp.start();
            });
            return videoView;
        }
    }

Uso de las APIs de Storage en tu SDK

Los SDKs en el entorno de ejecución del SDK ya no pueden acceder al almacenamiento interno de una app, ni viceversa, ni leer o escribir en él. Al entorno de ejecución de SDK se le asignará su propia área de almacenamiento interno, que será independiente de la app.

Los SDKs podrán acceder a este almacenamiento interno independiente con 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 funcionarán las APIs de almacenamiento interno, como Context.getFilesDir() o Context.getCacheDir(). Puedes ver 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 que accedan al almacenamiento externo arrojará una excepción o mostrará null. Varios ejemplos:

En Android 13, todos los SDKs en el entorno de ejecución de SDK compartirán el almacenamiento interno asignado para ese entorno. El almacenamiento se conservará hasta que se desinstale la app cliente o cuando se borren los datos de ella.

Debes usar el Context que muestra SandboxedSdkProvider.getContext() para el almacenamiento. El uso de la API de almacenamiento de archivos en cualquier otra instancia de objeto Context, como el contexto de la aplicación, no se garantiza que funcione como se espera en todas las situaciones o en el futuro.

En el siguiente fragmento de código, se muestra el modo de uso del almacenamiento en el entorno de ejecución del SDK:

Kotlin

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    override fun doSomething() {
        val filename = "myfile"
        val fileContents = "content"
        try {
            getContext().openFileOutput(filename, Context.MODE_PRIVATE).use {
                it.write(fileContents.toByteArray())
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }
}

    

Java

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    @Override
    public void doSomething() {
        final filename = "myFile";
        final String fileContents = "content";
        try (FileOutputStream fos = getContext().openFileOutput(filename, Context.MODE_PRIVATE)) {
            fos.write(fileContents.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

    

Almacenamiento por SDK

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.

En Android 13, solo una API muestra una ruta de acceso al almacenamiento por SDK: Context#getDataDir().

En Android 14, todas las APIs de almacenamiento interno del objeto Context muestran una ruta de almacenamiento para cada SDK. Es posible que debas habilitar esta función ejecutando el siguiente comando adb:

adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true

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, haz lo siguiente:

  • Declara el permiso android.permission.ACCESS_ADSERVICES_AD_ID en el manifiesto del SDK.
  • 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, haz lo siguiente:

  • Usa AppSetIdManager#getAppSetId() para recuperar el valor de forma asíncrona.

Actualiza las apps cliente

Para llamar a un SDK que se ejecuta en el entorno de ejecución de SDK, realiza los siguientes cambios en la app cliente que realiza la llamada:

  1. Agrega los permisos INTERNET y ACCESS_NETWORK_STATE al manifiesto de tu app:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
  2. En la actividad de la app que incluye un anuncio, declara una referencia a SdkSandboxManager, un valor booleano para saber si se cargó el SDK, y a un objeto SurfaceView para la renderización remota:

    Kotlin

        private lateinit var mSdkSandboxManager: SdkSandboxManager
        private lateinit var mClientView: SurfaceView
        private var mSdkLoaded = false
    
        companion object {
            private const val SDK_NAME = "com.example.privacysandbox.provider"
        }
    

    Java

        private static final String SDK_NAME = "com.example.privacysandbox.provider";
    
        private SdkSandboxManager mSdkSandboxManager;
        private SurfaceView mClientView;
        private boolean mSdkLoaded = false;
    
  3. Comprueba si el proceso del entorno de ejecución del SDK está disponible en el dispositivo.

    1. Verifica la constante SdkSandboxState (getSdkSandboxState()). SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION significa que el entorno de ejecución del SDK está disponible.

    2. Comprueba que la llamada a loadSdk() se haya realizado correctamente. Es exitosa si no se producen excepciones y el receptor es la instancia del SandboxedSdk.

      • Llama a loadSdk() desde el primer plano. Si se llama en segundo plano, se arroja una SecurityException.

      • Verifica el OutcomeReceiver para ver una instancia de SandboxedSdk y comprobar si se arrojó una LoadSdkException. Una excepción indica que el entorno de ejecución del SDK puede no estar disponible.

    Si la llamada a loadSdk o el SdkSandboxState fallan, el entorno de ejecución del SDK no está disponible y la llamada debería recurrir al SDK existente.

  4. Para definir una clase de devolución de llamada, implementa OutcomeReceiver para interactuar con el SDK en el entorno de ejecución después de que se haya cargado: En el siguiente ejemplo, el cliente usa una devolución de llamada para esperar hasta que el SDK se cargue de forma correcta y, luego, intenta renderizar una vista web desde el SDK. Las devoluciones de llamada se definen más adelante en este paso.

    Kotlin

        private inner class LoadSdkOutcomeReceiverImpl private constructor() :
                OutcomeReceiver {
    
          override fun onResult(sandboxedSdk: SandboxedSdk) {
              mSdkLoaded = true
    
              val binder: IBinder = sandboxedSdk.getInterface()
              if (!binderInterface.isPresent()) {
                  // SDK is not loaded anymore.
                  return
              }
              val sdkInterface: ISdkInterface = ISdkInterface.Stub.asInterface(binder)
              sdkInterface.doSomething()
    
              Handler(Looper.getMainLooper()).post {
                  val bundle = Bundle()
                  bundle.putInt(SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth())
                  bundle.putInt(SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight())
                  bundle.putInt(SdkSandboxManager.EXTRA_DISPLAY_ID, display!!.displayId)
                  bundle.putInt(SdkSandboxManager.EXTRA_HOST_TOKEN, mClientView.getHostToken())
                  mSdkSandboxManager!!.requestSurfacePackage(
                          SDK_NAME, bundle, { obj: Runnable -> obj.run() },
                          RequestSurfacePackageOutcomeReceiverImpl())
              }
          }
    
          override fun onError(error: LoadSdkException) {
                  // Log or show error.
          }
        }
    

    Java

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_DISPLAY_ID;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HOST_TOKEN;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS;
    
        private class LoadSdkOutcomeReceiverImpl
                implements OutcomeReceiver {
            private LoadSdkOutcomeReceiverImpl() {}
    
            @Override
            public void onResult(@NonNull SandboxedSdk sandboxedSdk) {
                mSdkLoaded = true;
    
                IBinder binder = sandboxedSdk.getInterface();
                if (!binderInterface.isPresent()) {
                    // SDK is not loaded anymore.
                    return;
                }
                ISdkInterface sdkInterface = ISdkInterface.Stub.asInterface(binder);
                sdkInterface.doSomething();
    
                new Handler(Looper.getMainLooper()).post(() -> {
                    Bundle bundle = new Bundle();
                    bundle.putInt(EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth());
                    bundle.putInt(EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight());
                    bundle.putInt(EXTRA_DISPLAY_ID, getDisplay().getDisplayId());
                    bundle.putInt(EXTRA_HOST_TOKEN, mClientView.getHostToken());
    
                    mSdkSandboxManager.requestSurfacePackage(
                            SDK_NAME, bundle, Runnable::run,
                            new RequestSurfacePackageOutcomeReceiverImpl());
                });
            }
    
            @Override
            public void onError(@NonNull LoadSdkException error) {
                // Log or show error.
            }
        }
    

    Para recuperar una vista remota del SDK en el entorno de ejecución mientras llamas a requestSurfacePackage(), implementa la interfaz OutcomeReceiver<Bundle, RequestSurfacePackageException>:

    Kotlin

        private inner class RequestSurfacePackageOutcomeReceiverImpl :
                OutcomeReceiver {
            fun onResult(@NonNull result: Bundle) {
                Handler(Looper.getMainLooper())
                        .post {
                            val surfacePackage: SurfacePackage = result.getParcelable(
                                    EXTRA_SURFACE_PACKAGE,
                                    SurfacePackage::class.java)
                            mRenderedView.setChildSurfacePackage(surfacePackage)
                            mRenderedView.setVisibility(View.VISIBLE)
                        }
            }
    
            fun onError(@NonNull error: RequestSurfacePackageException?) {
                // Error handling
            }
        }
    

    Java

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_SURFACE_PACKAGE;
    
        private class RequestSurfacePackageOutcomeReceiverImpl
                implements OutcomeReceiver {
            @Override
            public void onResult(@NonNull Bundle result) {
                new Handler(Looper.getMainLooper())
                        .post(
                                () -> {
                                    SurfacePackage surfacePackage =
                                            result.getParcelable(
                                                    EXTRA_SURFACE_PACKAGE,
                                                    SurfacePackage.class);
                                    mRenderedView.setChildSurfacePackage(surfacePackage);
                                    mRenderedView.setVisibility(View.VISIBLE);
                                });
            }
            @Override
            public void onError(@NonNull RequestSurfacePackageException error) {
                // Error handling
            }
        }
    

    Cuando termines de mostrar la vista, recuerda liberar a SurfacePackage con un llamado al siguiente comando:

    surfacePackage.notifyDetachedFromWindow()
    
  5. En onCreate(), inicializa SdkSandboxManager, las devoluciones de llamada necesarias y, luego, realiza una solicitud para cargar el SDK:

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mSdkSandboxManager = applicationContext.getSystemService(
                SdkSandboxManager::class.java
        )
    
        mClientView = findViewById(R.id.rendered_view)
        mClientView.setZOrderOnTop(true)
    
        val loadSdkCallback = LoadSdkCallbackImpl()
        mSdkSandboxManager.loadSdk(
                SDK_NAME, Bundle(), { obj: Runnable -> obj.run() }, loadSdkCallback
        )
    }
    

    Java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mSdkSandboxManager = getApplicationContext().getSystemService(
                SdkSandboxManager.class);
    
        mClientView = findViewById(R.id.rendered_view);
        mClientView.setZOrderOnTop(true);
    
        LoadSdkCallbackImpl loadSdkCallback = new LoadSdkCallbackImpl();
        mSdkSandboxManager.loadSdk(
                SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
    }
    
  6. Para manejar el caso cuando el proceso de la zona de pruebas del SDK finaliza de forma inesperada, define una implementación para la interfaz SdkSandboxProcessDeathCallback:

    Kotlin

        private inner class SdkSandboxLifecycleCallbackImpl() : SdkSandboxProcessDeathCallback {
            override fun onSdkSandboxDied() {
                // The SDK runtime process has terminated. To bring back up the
                // sandbox and continue using SDKs, load the SDKs again.
                val loadSdkCallback = LoadSdkOutcomeReceiverImpl()
                mSdkSandboxManager.loadSdk(
                          SDK_NAME, Bundle(), { obj: Runnable -> obj.run() },
                          loadSdkCallback)
            }
        }
    

    Java

          private class SdkSandboxLifecycleCallbackImpl
                  implements SdkSandboxProcessDeathCallback {
              @Override
              public void onSdkSandboxDied() {
                  // The SDK runtime process has terminated. To bring back up
                  // the sandbox and continue using SDKs, load the SDKs again.
                  LoadSdkOutcomeReceiverImpl loadSdkCallback =
                          new LoadSdkOutcomeReceiverImpl();
                  mSdkSandboxManager.loadSdk(
                              SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
              }
          }
    

    Para registrar esta devolución de llamada para recibir información sobre cuándo se cerró la zona de pruebas del SDK, agrega la siguiente línea en cualquier momento:

    Kotlin

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback({ obj: Runnable -> obj.run() },
                SdkSandboxLifecycleCallbackImpl())
    

    Java

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run,
                new SdkSandboxLifecycleCallbackImpl());
    

    Debido a que el estado de la zona de pruebas se pierde cuando finaliza su proceso, es posible que las vistas que haya renderizado el SDK de forma remota ya no funcionen correctamente. Para seguir interactuando con los SDKs, se deben volver a cargar estas vistas para que se inicie un nuevo proceso de zona de pruebas.

  7. Agrega una dependencia en el módulo del SDK al build.gradle de tu app cliente:

    dependencies {
        ...
        implementation project(':<your-sdk-module>')
        ...
    }

Prueba tus apps

Para ejecutar tu app cliente, instala la app del SDK y la app cliente en tu dispositivo de prueba mediante Android Studio o la línea de comandos.

Cómo implementar mediante Android Studio

Cuando realices implementaciones mediante Android Studio, sigue estos pasos:

  1. Abre el proyecto de Android Studio de tu app cliente.
  2. Ve a Run > Edit Configurations. Aparecerá la ventana Run/Debug Configuration.
  3. En Launch Options, establece Launch en Specified Activity.
  4. Haz clic en el menú de tres puntos junto a Activity y selecciona Main Activity para tu cliente.
  5. Haz clic en Apply y, luego, en OK.
  6. Haz clic en Run para instalar la app cliente y el SDK en tu dispositivo de prueba.

Cómo implementar mediante la línea de comandos

Cuando realices implementaciones con la línea de comandos, completa los pasos de la siguiente lista. En esta sección, se supone que el nombre del módulo de tu app del SDK es sdk-app y que el nombre del módulo de tu app cliente es client-app.

  1. Compila los APK del SDK de Privacy Sandbox desde la terminal de la línea de comandos:

    ./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
    

    Esto genera la ubicación para los APKs generados. Estos APKs están firmados con tu clave de depuración local. Necesitarás esta ruta de acceso en el siguiente comando.

  2. Instala el APK en tu dispositivo:

    adb install -t /path/to/your/standalone.apk
    
  3. En Android Studio, haz clic en Run > Edit Configurations. Aparecerá la ventana Run/Debug Configuration.

  4. En Installation Options, configura Deploy como Default APK.

  5. Haz clic en Apply y, luego, en OK.

  6. Haz clic en Run para instalar el paquete de APK en el dispositivo de prueba.

Depura tus apps

Para depurar la app cliente, haz clic en el botón Debug en Android Studio.

Para depurar la app del SDK, ve a Run > Attach to Process, que muestra una pantalla emergente (como se muestra a continuación). Marca la casilla Show all processes. En la lista que aparece, busca un proceso con el nombre CLIENT_APP_PROCESS_sdk_sandbox. Selecciona esta opción y agrega puntos de interrupción en el código de la app del SDK para comenzar a depurar tu SDK.

El proceso de la app del SDK aparece en una vista de lista cerca de la parte inferior del diálogo.
La pantalla Choose process, en la que puedes seleccionar la app del SDK que depurarás.

Inicia y detén el entorno de ejecución del SDK desde la línea de comandos

Para iniciar el proceso del entorno de ejecución del SDK de tu app, usa el siguiente comando shell:

adb shell cmd sdk_sandbox start [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

Del mismo modo, para detener el proceso del entorno de ejecución del SDK, ejecuta este comando:

adb shell cmd sdk_sandbox stop [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

Limitaciones

Si quieres obtener una lista de las funciones en curso para el entorno de ejecución del SDK, consulta las notas de la versión.

Muestras de código

El repositorio de APIs del entorno de ejecución y la preservación de la privacidad de SDK en GitHub contiene un conjunto de proyectos individuales de Android Studio que te ayudarán a comenzar, incluidos ejemplos que muestran cómo inicializar y llamar al entorno de ejecución de SDK.

Informa errores y problemas

Tus comentarios son una parte fundamental de Privacy Sandbox en Android. Avísanos si tienes problemas o ideas para mejorar Privacy Sandbox en Android.