Criar e consumir um SDK ativado pelo ambiente de execução

1
Key concepts
2
Set up your development environment
3
Build an RE SDK
4
Consume the RE SDK
5
Testing, and building for distribution

Consumir o SDK ativado pelo ambiente de execução

Esta seção descreve como os clientes podem interagir com as APIs do SDK (RE) declaradas com ativação de execução.

No caso deste guia, nos referimos ao seu módulo do SDK existente (ou SDK baseado no ambiente de execução) como o cliente.

Se você quiser colocar o SDK ativado pelo ambiente de execução diretamente no seu app, o módulo do app é o cliente.

Carregar o SDK ativado pelo ambiente de execução

A primeira coisa que você quer fazer no seu SDK com reconhecimento de ambiente de execução ou app cliente é carregar o SDK ativado pelo ambiente de execução.

A classe SdkSandboxManager ajuda a carregar SDKs ativados pelo ambiente de execução, retornando uma classe IBinder que o SDK ciente do ambiente de execução pode vincular à interface declarada no SDK ativado pelo ambiente de execução.

Você precisa carregar cada SDK ativado pelo ambiente de execução apenas uma vez. Caso contrário, o SDK Manager vai retornar uma exceção.

As ferramentas de geração de paliativos geram classes auxiliares para converter a interface IBinder retornada pelo SdkSandboxManager na interface declarada da API SDK.

As ferramentas usam a interface anotada com @PrivacySandboxService para gerar uma classe *Factory.

Essa classe contém uma função wrapTo* estática que converte um objeto IBinder em uma instância da interface do SDK ativado pelo ambiente de execução.

O SDK ciente do ambiente de execução pode se comunicar com o SDK ativado pelo ambiente de execução usando essa interface e invocar as APIs do SDK declaradas na etapa anterior.

// Name of the SDK to be loaded, defined in your ASB module
private const val SDK_NAME = "com.example.sdk"

try {
    // SdkSandboxManagerCompat is used to communicate with the sandbox and load SDKs with backward compatibility.
    val sandboxManagerCompat = SdkSandboxManagerCompat.from(context)
    val sandboxedSdk = sandboxManagerCompat.loadSdk(SDK_NAME, Bundle.EMPTY)
    val mySdk = MySdkFactory.wrapToMySdk(sandboxedSdk.getInterface()!!)
} catch (e: LoadSdkCompatException) {
    Log.e(TAG, "Failed to load SDK, error code: ${e.loadSdkErrorCode}", e)
    return null
}

Uso da biblioteca de interface

Se você quiser usar a biblioteca da interface para exibir anúncios, adicione androidx.privacysandbox.ui:ui-core e androidx.privacysandbox.ui:ui-client às dependências no build.gradle do SDK com reconhecimento de ambiente de execução.

Carregar um anúncio de banner usando o SandboxedSdkView

O androidx.privacysandbox.ui:ui-client apresenta uma nova ViewGroup chamada SandboxedSdkView para hospedar a interface criada por um SDK ativado pelo ambiente de execução.

setAdapter() abre uma sessão com o SDK ativado pelo tempo de execução para receber a visualização do anúncio e notificações de mudanças na interface. Quando o SDK abre a sessão, o anúncio é mostrado.

Isso pode ser integrado da seguinte maneira:

class BannerAd(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
    suspend fun loadAd() {
        // mySdk is the previously loaded SDK in the SDK Runtime.
        val bannerAd = mySdk.loadAd()
        val sandboxedSdkView = SandboxedSdkView(context)
        addViewToLayout(sandboxedSdkView)

        // This renders the ad.
        sandboxedSdkView.setAdapter(bannerAd)
        return
    }
    private fun addViewToLayout(view: View) {
        view.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        super.addView(view)
    }
}

O SDK com reconhecimento de ambiente de execução também pode ser notificado quando o estado da sessão muda para a apresentação da interface. Para fazer isso:

  1. Crie uma classe SessionStateChangeListener() para lidar com os diferentes cenários:

    private class SessionStateChangeListener() : SandboxedSdkUiSessionStateChangedListener {
        override fun onStateChanged(state: SandboxedSdkUiSessionState) {
            if (state is SandboxedSdkUiSessionState.Error) {
            // Some error has occurred while opening the session. Handle
            // accordingly.
            Log.e(TAG, state.throwable.message!!);
            } else if (state is SandboxedSdkUiSessionState.Loading) {
                // The session is attempting to be opened.
            } else if (state is SandboxedSdkUiSessionState.Active) {
                // The session is open and the UI presentation was successful.
            } else if (state is SandboxedSdkUiSessionState.Idle) {
                // There is no open session.
            }
        }
    }
    
  2. Adicione um listener de mudança de estado ao SandboxedSdkView que você instanciou anteriormente. O listener é chamado imediatamente com o estado atual assim que é anexado à visualização.

Observe o seguinte:

  • Se o SDK com reconhecimento de ambiente de execução chamar métodos SandboxedSdkView quando a sessão ainda não tiver sido aberta, todos os efeitos serão aplicados após a abertura da sessão.
    • Métodos como SandboxedSdkView.orderProviderUiAboveClientUi(providerUiOnTop)
  • Não é possível chamar métodos que adicionam ou removem uma visualização de SandboxedSdkView (como addView(), removeView(), removeViewAt() etc.), gerando uma UnsupportedOperationException.
    • use setAdapter() para mostrar o anúncio.
  • SandboxedSdkView.orderProviderUiAboveClientUi(providerUiOnTop) alterna a ordem Z, o que afeta se MotionEvents da interação do usuário é enviado para o SDK ativado pelo ambiente de execução ou para o SDK compatível com o ambiente de execução.

Iniciar atividades

Para iniciar atividades de propriedade do SDK ativado pelo ambiente de execução, use a extensão createSdkActivityLauncher para criar uma tela de início no SDK com reconhecimento de ambiente de execução.

Esse iniciador pode ser transmitido para o SDK ativado pelo ambiente de execução, permitindo que ele inicie atividades conforme necessário.

É possível usar um predicado para controlar se a atividade será iniciada ou não. O predicado precisa retornar um valor true para que as atividades sejam permitidas.

val launchSdkActivityPredicate = {
    // Boolean which has to be true to launch the activities
    }
val launcher = baseActivity.createSdkActivityLauncher(launchSdkActivityPredicate)
fullscreenService.showActivity(launcher)

No SDK ativado pelo ambiente de execução, registre SdkSandboxActivityHandlerCompat e forneça-o para SdkActivityLauncher.LaunchSdkActivity(IBinder).

fun showActivity(activityLauncher: SdkActivityLauncher) {
    val handler = object : SdkSandboxActivityHandlerCompat {
        override fun onActivityCreated(activityHolder: ActivityHolder) {
            activityHolder.getActivity().setContentView(contentView)
        }
    }

    val token = controller.registerSdkSandboxActivityHandler(handler)
    activityLauncher.launchSdkActivity(token)
}

O ActivityHolder transmitido para SdkSandboxActivityHandlerCompat.onActivityCreated(ActivityHolder) implementa LifecycleOwner, fornecendo ao SDK ativado pelo ambiente de execução acesso ao ciclo de vida da atividade.

Ele também fornece a API getOnBackPressedDispatcher, que pode ser usada para registrar instâncias de getOnBackPressedCallback e processar o comportamento do botão "Voltar" dentro da atividade.


Etapa 3: criar um SDK ativado pelo ambiente de execução Etapa 5: testar e criar para distribuição