Guia do desenvolvedor do SDK Runtime

Ao ler a documentação do Sandbox de privacidade do Android, use o botão Prévia para desenvolvedores ou Beta para selecionar a versão do programa com que você está trabalhando, porque as instruções podem variar.


Enviar feedback

O SDK Runtime permite que os SDKs sejam executados em um sandbox dedicado e separado do app de chamada. O SDK Runtime fornece proteções e garantias aprimoradas para a coleta de dados do usuário. Isso é feito em um ambiente de execução modificado que limita os direitos de acesso a dados e o conjunto de permissões. Saiba mais sobre o SDK Runtime na proposta de design.

As etapas desta página ensinam você a criar um SDK ativado pelo ambiente de execução e capaz de definir uma visualização baseada na Web que pode ser renderizada remotamente em um app de chamada.

Limitações conhecidas

Para conferir uma lista de recursos em desenvolvimento para o SDK Runtime, consulte as notas da versão.

Esperamos que as limitações abaixo sejam corrigidas na próxima principal versão da plataforma Android.

  • Renderização de anúncios em uma visualização rolável. Por exemplo, RecyclerView não funciona corretamente.
    • Pode haver instabilidade no redimensionamento.
    • Os eventos de rolagem com toque do usuário não são transmitidos corretamente para o ambiente de execução.
  • API Storage

O problema abaixo será corrigido em 2023:

  • As APIs getAdId e getAppSetId ainda não funcionam corretamente porque o suporte a elas ainda não foi ativado.

Antes de começar

Antes de começar, siga estas etapas:

  1. Configure seu ambiente de desenvolvimento para o Sandbox de privacidade do Android. Ferramentas com suporte ao SDK Runtime ainda estão em desenvolvimento ativo. Por isso, neste guia é necessário usar a versão canário mais recente do Android Studio. É possível executar essa versão do Android Studio simultaneamente com outras versões. Entre em contato conosco se esse requisito não funcionar.

  2. Instale uma imagem do sistema em um dispositivo com suporte ou configure um emulador que inclua suporte ao Sandbox de privacidade do Android.

Configurar o projeto no Android Studio

Para testar o SDK Runtime, use um modelo semelhante ao cliente-servidor (link em inglês). A principal diferença é que os apps (o cliente) e os SDKs (o "servidor") são executados no mesmo dispositivo.

  1. Adicione um módulo de app ao projeto. Esse módulo atua como o cliente que gera o SDK.
  2. No módulo do app, ative o SDK Runtime, declare as permissões necessárias e configure os serviços de anúncio específicos da API.
  3. Adicione um módulo de biblioteca ao projeto. Esse módulo contém o código do SDK.
  4. No módulo do SDK, declare as permissões necessárias. Você não precisa configurar serviços de anúncio específicos da API neste módulo.
  5. Remova dependencies do arquivo build.gradle do módulo da biblioteca, se o SDK não usar esse arquivo. Na maioria dos casos, é possível remover todas as dependências. Para fazer isso, crie um novo diretório com um nome que corresponda ao seu SDK.
  6. Crie um módulo de forma manual usando o tipo com.android.privacy-sandbox-sdk. Ele é combinado com o código do SDK para criar um APK que possa ser implantado no dispositivo. Para fazer isso, crie um novo diretório com um nome que corresponda ao seu SDK. Adicione um arquivo build.gradle vazio. O conteúdo dele será preenchido mais adiante neste guia.

  7. Adicione o seguinte snippet ao seu arquivo gradle.properties:

    android.experimental.privacysandboxsdk.enable=true
    

  8. Faça o download do Tiramisu (extensão de nível 4) e crie um emulador com essa imagem que inclui a Play Store.

Dependendo se você é um desenvolvedor de SDK ou de apps, pode haver uma configuração final diferente da descrita no parágrafo anterior.

Instale o SDK em um dispositivo de teste, da mesma forma que você instalaria um app, usando o Android Studio ou Android Debug Bridge (ADB). Para ajudar você a começar, criamos apps de exemplo nas linguagens de programação Kotlin e Java, que podem ser encontrados neste repositório do GitHub (em inglês). Os arquivos README e de manifesto têm comentários sobre o que precisa ser mudado para executar o exemplo em versões estáveis do Android Studio.

Preparar o SDK

  1. Crie manualmente um diretório no nível do módulo. Ele atua como o wrapper ao redor do seu código de implementação para criar o APK do SDK. No novo diretório, adicione um arquivo build.gradle e o preencha com o snippet abaixo. Dê um nome exclusivo ao SDK ativado pelo ambiente de execução (RE-SDK) e forneça uma versão. Inclua o módulo da biblioteca na seção 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. Crie uma classe na biblioteca de implementação para servir como ponto de entrada para o SDK. O nome da classe precisa ser associado ao valor do sdkProviderClassName e estender o SandboxedSdkProvider.

O ponto de entrada do SDK estende SandboxedSdkProvider. O SandboxedSdkProvider contém um objeto Context para o SDK, que você pode acessar chamando getContext(). Esse contexto só pode ser acessado depois que onLoadSdk() for invocado.

Para compilar o app do SDK, substitua os métodos para processar o ciclo de vida do SDK.

onLoadSdk()

Carrega o SDK no sandbox e notifica o app de chamada quando o SDK está pronto para processar solicitações, transmitindo a interface dele como um objeto IBinder encapsulado em um novo objeto SandboxedSdk. O guia de serviços vinculados oferece maneiras diferentes de fornecer IBinder. Você tem flexibilidade para escolher como quer fazer isso, mas precisa manter a consistência entre o SDK e o app de chamada.

Usando AIDL como exemplo, é necessário definir um arquivo AIDL para apresentar o IBinder, que será compartilhado e usado pelo app:

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

Cria e configura a visualização do anúncio, faz a inicialização dela da mesma forma que qualquer outra visualização do Android e a retorna para renderização remota em uma janela de uma determinada largura e altura em pixels.

O snippet de código abaixo demonstra como substituir esses 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.
        }
    }
}

Testar players de vídeo no SDK Runtime

Além do suporte a anúncios de banner, o Sandbox de privacidade tem o compromisso de oferecer suporte a players de vídeo em execução no SDK Runtime.

O fluxo para testar players de vídeo é semelhante ao teste de anúncios de banner. Mude o método getView() do ponto de entrada do SDK para incluir um player de vídeo no objeto View retornado. Teste todos os fluxos do player de vídeo que precisam ter suporte do Sandbox de privacidade. Observe que a comunicação entre o SDK e o app cliente sobre o ciclo de vida do vídeo está fora do escopo, então um feedback para isso ainda não é necessário para essa funcionalidade.

Seus testes e feedback vão garantir que o SDK Runtime tenha suporte a todos os casos de uso do seu player de vídeo preferido.

O snippet de código abaixo demonstra como retornar uma exibição de vídeo simples que é carregada por um 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;
        }
    }

Como usar APIs de armazenamento no SDK

Os SDKs no SDK Runtime não podem mais acessar, ler ou gravar no armazenamento interno de um app e vice-versa. O SDK Runtime vai receber uma área de armazenamento interno só para ele, separada do app.

Os SDKs poderão acessar esse armazenamento interno separado usando as APIs de armazenamento de arquivos no objeto Context retornado pelo SandboxedSdkProvider#getContext(). Os SDKs só podem usar o armazenamento interno. Portanto, apenas as APIs de armazenamento interno vão funcionar, por exemplo, Context.getFilesDir() ou Context.getCacheDir(). Confira mais exemplos em Acessar pelo armazenamento interno.

Não há suporte para acesso ao armazenamento externo pelo SDK Runtime. Chamar APIs para acessar o armazenamento externo vai gerar uma exceção ou retornar null. Alguns exemplos:

No Android 13, todos os SDKs no SDK Runtime vão compartilhar o armazenamento interno alocado ao SDK Runtime. Esse armazenamento será mantido até que o app cliente seja desinstalado ou até a exclusão dos dados do app cliente.

É preciso usar o Context retornado por SandboxedSdkProvider.getContext() para armazenamento. O uso da API de armazenamento de arquivos em qualquer outra instância de objeto Context pode não funcionar conforme o esperado em todas as situações ou no futuro. Um exemplo é o contexto do app.

O snippet de código a seguir demonstra como usar o armazenamento no SDK Runtime:

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);
        }
    }

}

    

Armazenamento por SDK

No armazenamento interno separado de cada SDK Runtime, cada SDK tem o próprio diretório de armazenamento. Essa é uma separação lógica do armazenamento interno do SDK Runtime, que ajuda a contabilizar a quantidade de armazenamento usada por um SDK.

No Android 13, apenas uma API retorna um caminho para o armazenamento por SDK: Context#getDataDir().

No Android 14, todas as APIs de armazenamento interno no objeto Context retornam um caminho de armazenamento para cada SDK. Talvez seja necessário ativar esse recurso executando este comando adb:

adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true

Acessar o ID de publicidade fornecido pelo Google Play Services

Se o SDK precisar de acesso ao ID de publicidade fornecido pelo Google Play Services, faça o seguinte:

  • Declare a permissão android.permission.ACCESS_ADSERVICES_AD_ID no manifesto do SDK.
  • Use AdIdManager#getAdId() para extrair o valor de maneira assíncrona.

Acessar o ID do conjunto de apps fornecido pelo Google Play Services

Caso o SDK precise acessar o ID do conjunto de apps fornecido pelo Google Play Services, faça o seguinte:

  • Use AppSetIdManager#getAppSetId() para extrair o valor de maneira assíncrona.

Atualizar apps clientes

Para chamar um SDK em execução no SDK Runtime, faça as seguintes mudanças no app cliente de chamada:

  1. Adicione as permissões INTERNET e ACCESS_NETWORK_STATE ao manifesto do seu app:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
  2. Na atividade do app que inclui um anúncio, declare uma referência ao SdkSandboxManager, um booleano para saber se o SDK está carregado e um objeto SurfaceView para renderização 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. Confira se o processo do SDK Runtime está disponível no dispositivo.

    1. Verifique a constante SdkSandboxState (getSdkSandboxState()). SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION significa que o SDK Runtime está disponível.

    2. Confirme se a chamada de loadSdk() foi concluída. O resultado só é válido se não há exceções e se o receptor é a instância do SandboxedSdk.

      • Chame loadSdk() do primeiro plano. Se chamado em segundo plano, é gerada uma SecurityException.

      • Confira se há uma instância do SandboxedSdk no OutcomeReceiver para verificar se uma LoadSdkException foi gerada. Uma exceção indica que o SDK Runtime pode não estar disponível.

    Se a chamada SdkSandboxState ou loadSdk falhar, o SDK Runtime não está disponível, e a chamada vai substituir o SDK existente.

  4. Defina uma classe de callback implementando OutcomeReceiver para interagir com o SDK durante a execução e após o carregamento. No exemplo a seguir, o cliente usa um callback para esperar que o SDK seja carregado e depois ele tenta renderizar uma visualização da Web pelo SDK. Os callbacks são definidos mais tarde nesta etapa.

    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 extrair uma visualização remota do SDK durante a execução ao chamar requestSurfacePackage(), implemente a interface 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
            }
        }
    

    Quando terminar de mostrar a visualização, lembre-se de liberar SurfacePackage chamando:

    surfacePackage.notifyDetachedFromWindow()
    
  5. Em onCreate(), inicialize o SdkSandboxManager e os callbacks necessários e faça uma solicitação para carregar o 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 lidar com o caso em que o processo de sandbox do SDK é encerrado inesperadamente, defina uma implementação para a interface 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 esse callback e receber informações sobre o encerramento do sandbox do SDK, adicione a seguinte linha a qualquer momento:

    Kotlin

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

    Java

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

    Como o estado do sandbox é perdido quando o processo é encerrado, as visualizações renderizadas remotamente pelo SDK podem não funcionar mais corretamente. Para continuar interagindo com os SDKs, essas visualizações precisam ser carregadas novamente para que um novo processo de sandbox seja iniciado.

  7. Adicione uma dependência ao módulo do SDK para o build.gradle do app cliente:

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

Testar os apps

Para executar o app cliente, instale o app do SDK e o app cliente no dispositivo de teste usando o Android Studio ou a linha de comando.

Implantar pelo Android Studio

Ao implantar pelo Android Studio, siga estas etapas:

  1. Abra o projeto do app cliente no Android Studio.
  2. Acesse Run > Edit Configurations. A janela Run/Debug Configuration vai aparecer.
  3. Em Launch Options, defina Launch como Specified Activity.
  4. Clique no menu de três pontos ao lado de "Activity" e selecione a Main Activity do cliente.
  5. Clique em Apply e em OK.
  6. Clique em Run para instalar o app cliente e o SDK no dispositivo de teste.

Implantar na linha de comando

Ao implantar usando a linha de comando, siga as etapas na lista abaixo. Esta seção pressupõe que o nome do módulo do app do SDK é sdk-app e que o nome do módulo do app cliente é client-app.

  1. Em um terminal de linha de comando, crie os APKs do SDK do Sandbox de privacidade:

    ./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
    

    Isso resulta em um local para os APKs gerados. Esses APKs são assinados com a chave de depuração local. Você vai precisar desse caminho no próximo comando.

  2. Instale o APK no dispositivo:

    adb install -t /path/to/your/standalone.apk
    
  3. No Android Studio, clique em Run > Edit Configurations. A janela Run/Debug Configuration vai aparecer.

  4. Em Installation Options, defina Deploy como Default APK.

  5. Clique em Apply e em OK.

  6. Clique em Run para instalar o pacote do APK no dispositivo de teste.

Depurar apps

Para depurar o app cliente, clique no botão Debug no Android Studio.

Para depurar o app do SDK, acesse Run > Attach to Process, que mostra uma tela pop-up (mostrada abaixo). Marque a caixa Show all processes. Na lista exibida, procure um processo com o nome CLIENT_APP_PROCESS_sdk_sandbox. Selecione essa opção e adicione pontos de interrupção no código do app do SDK para começar a depuração.

O processo do app do SDK aparece em uma visualização em lista perto da parte de baixo
  da caixa de diálogo.
A tela Choose process, em que você pode selecionar o app do SDK para depurar.

Iniciar e interromper o ambiente de execução do SDK na linha de comando

Para iniciar o processo de execução do SDK para seu app, use o seguinte comando do shell:

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

Da mesma forma, para interromper o processo de execução do SDK, execute este comando:

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

Limitações

Para conferir uma lista de recursos em desenvolvimento para o SDK Runtime, consulte as notas da versão.

Amostras de código

O repositório do SDK Runtime e de APIs para preservação de privacidade (em inglês) no GitHub contém um conjunto de projetos individuais do Android Studio para ajudar você a começar, incluindo exemplos que demonstram como inicializar e chamar o SDK Runtime.

Informar bugs e problemas

Seu feedback é uma parte crucial do Sandbox de privacidade no Android. Avise nossa equipe sobre problemas encontrados ou ideias para melhorar o Sandbox de privacidade do Android.