O SDK Runtime permite que os SDKs de anúncios sejam executados em um ambiente em sandbox, impedindo que
eles acessem a hierarquia de visualização de um editor. Para mostrar anúncios, a
plataforma expõe uma API SandboxedSdkProvider.getView
ao SDK de modo a receber uma visualização
do anúncio e a empacota como um SurfacePackage
para ser enviado por
comunicação entre processos (IPC) ao aplicativo cliente. Isso tem várias
desvantagens, que serão discutidas abaixo. Este documento vai apresentar uma proposta
de biblioteca do Jetpack que está sendo criada para lidar com esses desafios.
Justificativa para aumentar as APIs da plataforma
As APIs de framework foram projetadas para oferecer flexibilidade e deixam a tarefa de criar um canal secundário para a apresentação da interface a cargo do app e do SDK. Esse canal secundário:
- Permite que o SDK gerencie várias visualizações de anúncios durante o ciclo de vida delas e entenda o que acontece com a interface do anúncio depois que ela é criada pelo SDK.
- Separa a criação de visualizações e a vinculação de conteúdo. O uso do canal secundário permite que o SDK retorne um objeto que corresponde à solicitação de anúncio para o app (o conteúdo), que poderá ser vinculado ao contêiner de anúncios sempre que o app considerar adequado.
- Abstrai as construções da plataforma usadas para mostrar a interface nos
processos. No momento, a plataforma usa um
SurfaceControlViewhost
e gera umSurfacePackage
baseado nele. - Permite que os SDKs de anúncios no SDK Runtime recebam notificações automaticamente quando a interface do contêiner do anúncio mudar. Se um editor mudar o layout do contêiner de anúncios, o SDK não vai saber dessas mudanças, a menos que o editor chame explicitamente uma API para avisá-lo.
- Sincroniza redimensionamentos da interface do anúncio e do contêiner de anúncios sem qualquer instabilidade visível para o usuário.
- Gerencia automaticamente a compatibilidade com versões anteriores. O
SurfacePackage
não está disponível antes do nível 30 da API. Além disso, em dispositivos em que não há um ambiente de execução do SDK e o SDK tem processamento local para o editor, não é útil criar umSurfacePackage
para um anúncio quando uma visualização pode ser recebida diretamente do SDK. O canal secundário abstrai essa complexidade do SDK e do código do desenvolvedor do app. - Permite que a interface do anúncio se integre perfeitamente a elementos combináveis. Os desenvolvedores do Jetpack Compose que não trabalham com visualizações também podem continuar hospedando a interface gerada pelo desenvolvedor do SDK, que ainda funciona com visualizações.
Bibliotecas de interface
As bibliotecas de interface abstraem as complexidades detalhadas acima. Além disso, elas fornecem o canal secundário que o editor e o SDK podem usar para mostrar a interface em todos os processos e mantê-lo atualizado à medida que o usuário interage com ela e com o dispositivo.
Há três bibliotecas de interface: principal, de cliente e de provedor. A biblioteca principal fornece as interfaces usadas pelas bibliotecas de cliente e de provedor. O provedor da interface (normalmente o SDK) depende da biblioteca de provedor, e o consumidor da interface (geralmente o editor) depende da biblioteca de cliente. Juntas, as bibliotecas de cliente e do provedor formam o canal secundário necessário para criar e manter uma sessão de interface.
As APIs
As APIs para apresentação da interface do SDK Runtime são as seguintes:
SandboxedUiAdapter
: criada pelo SDK, oferecendo uma maneira de acessar o conteúdo
a ser mostrado na interface do editor.
SandboxedSdkView
: criada pelo editor, é um contêiner que armazena
o conteúdo extraído pelo SandboxedUiAdapter
.
Session
: criada pelo SDK em resposta ao
SandboxedUiAdapter.openSession()
. Representa uma chamada da sessão de interface. Isso forma
o final do túnel de comunicação do SDK entre o SDK e o editor e
recebe notificações sobre mudanças no SandboxedSdkView
, como remoções
de janelas, redimensionamentos ou mudanças de configuração.
SessionClient
: criada pela biblioteca de cliente, forma a parte do editor
do túnel de comunicação entre o SDK e o editor.
SandboxedSdkUiSessionStateChangedListener
: criada pelo editor. Um
listener para mudanças no estado da sessão de interface associada a
SandboxedSdkView
.
Leia a documentação de referência de privacysandbox-ui para saber mais detalhes sobre essas APIs.
Fluxo de controle
Os diagramas a seguir mostram a interação entre as bibliotecas de interface do cliente e do provedor em vários cenários:
O diagrama anterior mostra como o editor pode criar um SandboxedSdkView
de forma programática ou usando o XML e anexar a um SdkSandboxUiAdapter
obtidos do SDK usando uma API definida pelo SDK. Para observar todas as mudanças de estado
da interface, o editor precisa adicionar um SandboxedSdkUiSessionStateChangedListener
à SandboxedSdkView
antes de anexar SdkSandboxUiAdapter
.
Este diagrama mostra como, se a atividade do editor lida com mudanças de configuração,
a biblioteca de cliente encaminha a alteração de configuração para o SDK,
para que possam atualizar a interface de acordo com isso. Por exemplo, esse fluxo pode ser acionado
quando o usuário gira o dispositivo e o editor declara que processa
mudanças de configuração na atividade, definindo
android:configChanges=["orientation"]
.
Este diagrama ilustra como o SDK pode solicitar uma mudança no contêiner de anúncios usando
métodos na SessionClient
. Essa API é acionada quando o SDK quer redimensionar
o anúncio e precisa que o editor redimensione o contêiner de anúncios para acomodar as novas
dimensões. Isso pode acontecer em resposta à interação do usuário, como
mraid.resize()
.
Este diagrama mostra como a sessão é encerrada quando a SandboxedSdkView
é removida
da janela. A sessão também pode ser encerrada a qualquer momento pelo SDK invocando
SessionClient.onSessionError()
. Isso pode acontecer, por exemplo, quando o usuário
perde a conectividade de rede.
Ordem Z
A biblioteca de interface do cliente usa uma SurfaceView
internamente para hospedar a interface do SDK.
A SurfaceView
pode usar a ordem Z para mostrar a interface acima ou
abaixo da janela do editor. Isso é controlado pelo método
SandboxedSdkView.orderProviderUiAboveClientUi()
, que aceita um
booleano setOnTop
.
Quando setOnTop
for true
, cada android.view.MotionEvent
no
SandboxedSdkView
será enviado ao SDK. Quando for false
, o envio será feito ao
editor. Por padrão, os eventos de movimento são enviados ao SDK.
Os editores normalmente não precisam mudar a ordem Z padrão das visualizações de anúncios. No entanto, ao mostrar a interface que cobre um anúncio, como um menu suspenso, a ordem Z precisa ser temporariamente invertida do padrão e restaurada quando o elemento da interface da cobertura é dispensado. Estamos avaliando maneiras de automatizar esse processo na biblioteca de interface do cliente.
Rolagem
Quando a interface do anúncio é ordenada usando o modo "Z acima" da janela do editor, MotionEvents
da
interface do anúncio são enviados ao SDK. Gestos de rolagem e de deslize rápido iniciados na interface do anúncio recebem
tratamento especial:
- Os gestos de rolagem vertical e deslize rápido são enviados e processados pelo contêiner do editor. Isso proporciona uma boa UX quando o contêiner do editor em que a interface do anúncio é posicionada tem rolagem vertical. Nenhum trabalho extra é exigido do SDK ou do editor.
- Os gestos de rolagem e deslize rápido horizontal são enviados e processados pelo SDK. Isso proporciona uma boa UX quando a própria interface do anúncio pode ser rolada horizontalmente (como um carrossel de anúncios).
Guia de implementação
O SDK precisa implementar o seguinte:
SandboxedUiAdapter
: é retornado ao editor em resposta a uma API definida pelo SDK, comoloadAd
. O métodoopenSession()
disso deve ser usada para fazer uma solicitação de anúncio aos servidores do SDK e preparar uma visualização de anúncio para essa solicitação.Session**
: é retornado em resposta aoSandboxedUiAdapter.openSession
. Ele oferece ao cliente uma forma para obter a interface do anúncio e notificar o SDK sobre alterações nessa API. Tudo Os métodosSession
precisam ser implementados aqui.
O editor precisa fazer o seguinte:
- Criar um
SandboxedSdkView
usando XML ou de forma programática. - Anexar um
SandboxedSdkUiSessionStateChangedListener
àSandboxedSdkView
para observar as mudanças na interface. - Anexar um
SandboxedUiAdapter
fornecido pelo SDK àSandboxedSdkView
. - Adicionar a
SandboxedSdkView
à janela como de costume e deixar a biblioteca de cliente criar e manter a sessão de interface com o SDK. - Em momentos adequados, reagir às mudanças no estado relatadas por
SandboxedSdkUiSessionChangedListener
. Por exemplo, se o SDK fechar a sessão inesperadamente, o editor poderá substituir aSandboxedSdkView
por uma imagem estática ou removê-la da hierarquia de visualização. - Ao fazer transições que podem cobrir a interface do anúncio, como um menu suspenso,
usar
orderProviderUiAboveClientUi
temporariamente para "false" e posicionar a interface abaixo da janela do editor. Depois que o menu suspenso for dispensado, chamarorderProviderUiAboveClientUi
paratrue
.
O futuro das APIs da plataforma
Quando as bibliotecas de interface entrarem na versão Beta, planejamos suspender o uso das APIs da plataforma
SDK Runtime relacionadas à apresentação da interface, ou seja,
SdkSandboxManager.requestSurfacePackage()
e SandbxedSdkProvider.getView()
.
Perguntas
- Existem casos de uso mais comuns da interface de anúncios que as bibliotecas de interface precisam processar automaticamente?
- Quais frameworks de interface você usa para mostrar a interface do anúncio? Você prevê problemas na integração das bibliotecas de interface com esses frameworks?
- A interface de anúncios rolável colocada em um contêiner de editor rolável é um caso de uso comum para você? Qual é a direção da rolagem da interface do anúncio e do contêiner nesse caso? Qual comportamento você espera quando o usuário inicia uma rolagem na interface do anúncio?