De acordo com a Política de consentimento de usuários da União Europeia do Google, você precisa divulgar algumas informações aos seus usuários no Espaço Econômico Europeu (EEE) e no Reino Unido. Além disso, é necessário solicitar o consentimento deles para usar cookies ou outro armazenamento local (quando exigido por lei) e usar dados pessoais (como o ID de publicidade) para veicular anúncios. Essa política reflete os requisitos da Diretiva de privacidade eletrônica da UE e do Regulamento geral de proteção de dados (GDPR).
Para ajudar os editores a cumprir as obrigações de acordo com essa política, o Google oferece o SDK da plataforma de mensagens aos usuários (UMP). O SDK da UMP foi atualizado para oferecer suporte aos padrões mais recentes do IAB. Todas essas configurações agora podem ser gerenciadas na AdMob privacidade e mensagens.
Pré-requisitos
- ler o Guia explicativo
- API do Android de nível 21 ou mais recente (para Android)
- Se você estiver trabalhando com requisitos relacionados ao GDPR, leiaComo os requisitos do IAB afetam as mensagens de consentimento da UE
Criar um tipo de mensagem
Crie mensagens para os usuários com um dos tipos de mensagens disponíveis na guia Privacidade e mensagens da sua conta da AdMob O SDK da UMP tenta mostrar uma mensagem do usuário criada com base no AdMob ID do aplicativo definido no projeto. Se nenhuma mensagem for configurada para o aplicativo, o SDK retornará um erro.
Para mais detalhes, consulte Sobre privacidade e mensagens.
Instalar o SDK
Siga as etapas para instalar o SDK dos anúncios para dispositivos móveis do Google (GMA) para C++. O SDK da UMP para C++ está incluído no SDK do GMA para C++.
Configure o ID do app AdMob do seu app no projeto antes de continuar.
No seu código, inicialize o SDK da UMP chamando
ConsentInfo::GetInstance()
.- No Android, você precisa transmitir o
JNIEnv
e oActivity
fornecidos pelo NDK. Você só precisa fazer isso na primeira vez que chamarGetInstance()
. - Como alternativa, se você já estiver usando o SDK do Firebase para
C++ no seu app, é possível transmitir
um
firebase::App
na primeira vez que chamarGetInstance()
.
#include "firebase/gma/ump.h" namespace ump = ::firebase::gma::ump; // Initialize using a firebase::App void InitializeUserMessagingPlatform(const firebase::App& app) { ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance(app); } // Initialize without a firebase::App #ifdef ANDROID void InitializeUserMessagingPlatform(JNIEnv* jni_env, jobject activity) { ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance(jni_env, activity); } #else // non-Android void InitializeUserMessagingPlatform() { ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance(); } #endif
- No Android, você precisa transmitir o
As chamadas subsequentes para ConsentInfo::GetInstance()
retornam a mesma instância.
Se você terminar de usar o SDK da UMP, encerre o SDK excluindo a
instância ConsentInfo
:
void ShutdownUserMessagingPlatform() {
ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance();
delete consent_info;
}
Usar um Future
para monitorar operações assíncronas
Um
firebase::Future
oferece uma maneira de determinar o status de conclusão das chamadas de método
assíncronas.
Todas as chamadas de método e funções C++ da UMP que operam de forma assíncrona retornam um
Future
e também fornecem uma função de "último resultado" para extrair o Future
da operação mais recente.
Há duas maneiras de conferir um resultado de uma Future
:
- Chame
OnCompletion()
, transmitindo sua própria função de callback, que é chamada quando a operação é concluída. - Verifique o
status()
doFuture
periodicamente. Quando o status muda dekFutureStatusPending
parakFutureStatusCompleted
, a operação foi concluída.
Após a conclusão da operação assíncrona, verifique o
error()
do Future
para receber o código de erro
da operação. Se o código do erro for 0
(kConsentRequestSuccess
ou kConsentFormSuccess
),
a operação foi concluída com sucesso. Caso contrário, verifique o código do erro e
error_message()
para determinar o que deu errado.
Callback de conclusão
Confira um exemplo de como usar OnCompletion
para definir um callback de conclusão,
que é chamado quando a operação assíncrona é concluída.
void MyApplicationStart() {
// [... other app initialization code ...]
ump::ConsentInfo *consent_info = ump::ConsentInfo::GetInstance();
// See the section below for more information about RequestConsentInfoUpdate.
firebase::Future<void> result = consent_info->RequestConsentInfoUpdate(...);
result.OnCompletion([](const firebase::Future<void>& req_result) {
if (req_result.error() == ump::kConsentRequestSuccess) {
// Operation succeeded. You can now call LoadAndShowConsentFormIfRequired().
} else {
// Operation failed. Check req_result.error_message() for more information.
}
});
}
Atualizar sondagem de loop
Neste exemplo, depois que uma operação assíncrona é iniciada na inicialização do app, os resultados são verificados em outro lugar, na função de loop de atualização do jogo, que é executada uma vez por frame.
ump::ConsentInfo *g_consent_info = nullptr;
bool g_waiting_for_request = false;
void MyApplicationStart() {
// [... other app initialization code ...]
g_consent_info = ump::ConsentInfo::GetInstance();
// See the section below for more information about RequestConsentInfoUpdate.
g_consent_info->RequestConsentInfoUpdate(...);
g_waiting_for_request = true;
}
// Elsewhere, in the game's update loop, which runs once per frame:
void MyGameUpdateLoop() {
// [... other game logic here ...]
if (g_waiting_for_request) {
// Check whether RequestConsentInfoUpdate() has finished.
// Calling "LastResult" returns the Future for the most recent operation.
firebase::Future<void> result =
g_consent_info->RequestConsentInfoUpdateLastResult();
if (result.status() == firebase::kFutureStatusComplete) {
g_waiting_for_request = false;
if (result.error() == ump::kConsentRequestSuccess) {
// Operation succeeded. You can call LoadAndShowConsentFormIfRequired().
} else {
// Operation failed. Check result.error_message() for more information.
}
}
}
}
Para mais informações sobre firebase::Future
, consulte a documentação do SDK do Firebase para C++ e a documentação do SDK do GMA para C++.
Solicitação de informações de consentimento
Solicite uma atualização das informações de consentimento do usuário a cada inicialização do app usando RequestConsentInfoUpdate()
. Isso determina se o usuário precisa dar o consentimento, caso ainda não tenha feito isso ou se o consentimento expirou.
#include "firebase/gma/ump.h"
namespace ump = ::firebase::gma::ump;
void MyApplicationStart() {
ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance();
// Create a ConsentRequestParameters struct.
ump::ConsentRequestParameters params;
// Set tag for under age of consent. False means users are NOT under age
// of consent.
params.tag_for_under_age_of_consent = false;
consent_info->RequestConsentInfoUpdate(params).OnCompletion(
[](const Future<void>& result) {
if (result.error() != ump::kConsentRequestSuccess) {
LogMessage("Error requesting consent update: %s", result.error_message());
} else {
// Consent status is now available.
}
});
}
Consulte acima um exemplo de verificação da conclusão usando a pesquisa de loop de atualização em vez de um callback de conclusão.
Carregar e mostrar um formulário de consentimento, se necessário
Depois de receber o status de consentimento mais atualizado, chameLoadAndShowConsentFormIfRequired()
na classeConsentInfo
para carregar um formulário de consentimento. Se o status de consentimento for obrigatório, o SDK vai carregar um formulário e apresentar imediatamente do FormParent
fornecido. A chamada Future
é concluída depois que o formulário é dispensado. Se o consentimento não for necessário, a Future
será concluída imediatamente.
void MyApplicationStart(ump::FormParent parent) {
ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance();
// Create a ConsentRequestParameters struct..
ump::ConsentRequestParameters params;
// Set tag for under age of consent. False means users are NOT under age of consent.
params.tag_for_under_age_of_consent = false;
consent_info->RequestConsentInfoUpdate(params).OnCompletion(
[*](const Future<void>& req_result) {
if (req_result.error() != ump::kConsentRequestSuccess) {
// req_result.error() is a kConsentRequestError enum.
LogMessage("Error requesting consent update: %s", req_result.error_message());
} else {
consent_info->LoadAndShowConsentFormIfRequired(parent).OnCompletion(
[*](const Future<void>& form_result) {
if (form_result.error() != ump::kConsentFormSuccess) {
// form_result.error() is a kConsentFormError enum.
LogMessage("Error showing consent form: %s", form_result.error_message());
} else {
// Either the form was shown and completed by the user, or consent was not required.
}
});
}
});
}
Se você precisar executar alguma ação depois que o usuário fizer uma escolha ou dispensar
o formulário, coloque essa lógica no código que processa o Future
retornado por LoadAndShowConsentFormIfRequired()
.
Solicitar anúncios
Antes de solicitar anúncios no seu app, verifique se você recebeu o consentimento do usuário usando ConsentInfo::GetInstance()‑>CanRequestAds()
. Há dois lugares para verificar ao solicitar o consentimento:
- Depois que o consentimento for coletado na sessão atual.
- Imediatamente depois de chamar
RequestConsentInfoUpdate()
. É possível que o consentimento tenha sido obtido na sessão anterior. Como prática recomendada de latência, não aguarde a conclusão do callback para que você possa começar a carregar anúncios assim que possível após o lançamento do app.
Se ocorrer um erro durante o processo de solicitação de consentimento, ainda assim tente solicitar anúncios. O SDK da UMP usa o status de consentimento da sessão anterior.
O exemplo completo a seguir usa a pesquisa de loop de atualização, mas é possível também usar
callbacks OnCompletion
para monitorar operações assíncronas. Use
a técnica mais adequada à estrutura do seu código.
#include "firebase/future.h"
#include "firebase/gma/gma.h"
#include "firebase/gma/ump.h"
namespace gma = ::firebase::gma;
namespace ump = ::firebase::gma::ump;
using firebase::Future;
ump::ConsentInfo* g_consent_info = nullptr;
// State variable for tracking the UMP consent flow.
enum { kStart, kRequest, kLoadAndShow, kInitGma, kFinished, kErrorState } g_state = kStart;
bool g_ads_allowed = false;
void MyApplicationStart() {
g_consent_info = ump::ConsentInfo::GetInstance(...);
// Create a ConsentRequestParameters struct..
ump::ConsentRequestParameters params;
// Set tag for under age of consent. False means users are NOT under age of consent.
params.tag_for_under_age_of_consent = false;
g_consent_info->RequestConsentInfoUpdate(params);
// CanRequestAds() can return a cached value from a previous run immediately.
g_ads_allowed = g_consent_info->CanRequestAds();
g_state = kRequest;
}
// This function runs once per frame.
void MyGameUpdateLoop() {
// [... other game logic here ...]
if (g_state == kRequest) {
Future<void> req_result = g_consent_info->RequestConsentInfoUpdateLastResult();
if (req_result.status() == firebase::kFutureStatusComplete) {
g_ads_allowed = g_consent_info->CanRequestAds();
if (req_result.error() == ump::kConsentRequestSuccess) {
// You must provide the FormParent (Android Activity or iOS UIViewController).
ump::FormParent parent = GetMyFormParent();
g_consent_info->LoadAndShowConsentFormIfRequired(parent);
g_state = kLoadAndShow;
} else {
LogMessage("Error requesting consent status: %s", req_result.error_message());
g_state = kErrorState;
}
}
}
if (g_state == kLoadAndShow) {
Future<void> form_result = g_consent_info->LoadAndShowConsentFormIfRequiredLastResult();
if (form_result.status() == firebase::kFutureStatusComplete) {
g_ads_allowed = g_consent_info->CanRequestAds();
if (form_result.error() == ump::kConsentRequestSuccess) {
if (g_ads_allowed) {
// Initialize GMA. This is another asynchronous operation.
firebase::gma::Initialize();
g_state = kInitGma;
} else {
g_state = kFinished;
}
// Optional: shut down the UMP SDK to save memory.
delete g_consent_info;
g_consent_info = nullptr;
} else {
LogMessage("Error displaying consent form: %s", form_result.error_message());
g_state = kErrorState;
}
}
}
if (g_state == kInitGma && g_ads_allowed) {
Future<gma::AdapterInitializationStatus> gma_future = gma::InitializeLastResult();
if (gma_future.status() == firebase::kFutureStatusComplete) {
if (gma_future.error() == gma::kAdErrorCodeNone) {
g_state = kFinished;
// TODO: Request an ad.
} else {
LogMessage("Error initializing GMA: %s", gma_future.error_message());
g_state = kErrorState;
}
}
}
}
Opções de privacidade
Alguns formulários de consentimento exigem que o usuário modifique o consentimento a qualquer momento. Siga as etapas abaixo para implementar um botão de opções de privacidade, se necessário.
Para fazer isso:
- Implemente um elemento da interface, como um botão na página de configurações do app, que possa acionar um formulário de opções de privacidade.
- Quando a
LoadAndShowConsentFormIfRequired()
for concluída, verifiquegetPrivacyOptionsRequirementStatus()
para determinar se o elemento da interface que pode apresentar o formulário de opções de privacidade será mostrado. - Quando um usuário interagir com o elemento da interface, chame
showPrivacyOptionsForm()
para mostrar o formulário. Assim, o usuário pode atualizar as opções de privacidade a qualquer momento.
testes
Se você quiser testar a integração no app durante o desenvolvimento, siga estas etapas para registrar o dispositivo de teste de forma programática. Remova o código que define esses IDs de dispositivo de teste antes de lançar o app.
- Chame
RequestConsentInfoUpdate()
. Verifique a saída do registro para encontrar uma mensagem semelhante ao exemplo a seguir, que mostra o ID do dispositivo e como adicioná-lo como um dispositivo de teste:
Android
Use new ConsentDebugSettings.Builder().addTestDeviceHashedId("33BE2250B43518CCDA7DE426D04EE231") to set this as a debug device.
iOS
<UMP SDK>To enable debug mode for this device, set: UMPDebugSettings.testDeviceIdentifiers = @[2077ef9a63d2b398840261c8221a0c9b]
Copie o ID do dispositivo de teste para a área de transferência.
Modifique seu código para definir
ConsentRequestParameters.debug_settings.debug_device_ids
para uma lista dos IDs dos dispositivos de teste.void MyApplicationStart() { ump::ConsentInfo consent_info = ump::ConsentInfo::GetInstance(...); ump::ConsentRequestParameters params; params.tag_for_under_age_of_consent = false; params.debug_settings.debug_device_ids = {"TEST-DEVICE-HASHED-ID"}; consent_info->RequestConsentInfoUpdate(params); }
Forçar uma região geográfica
O SDK da UMP oferece uma maneira de testar o comportamento do app como se o dispositivo estivesse
localizado no EEE ou no Reino Unido usando ConsentRequestParameters.debug_settings.debug_geography
. As
configurações de depuração só funcionam em dispositivos de teste.
void MyApplicationStart() {
ump::ConsentInfo consent_info = ump::ConsentInfo::GetInstance(...);
ump::ConsentRequestParameters params;
params.tag_for_under_age_of_consent = false;
params.debug_settings.debug_device_ids = {"TEST-DEVICE-HASHED-ID"};
// Geography appears as EEA for debug devices.
params.debug_settings.debug_geography = ump::kConsentDebugGeographyEEA
consent_info->RequestConsentInfoUpdate(params);
}
Redefinir estado de consentimento
Ao testar seu app com o SDK da UMP, pode ser útil redefinir o
estado do SDK para que você possa simular a primeira experiência de instalação de um usuário.
O SDK fornece o método Reset()
para fazer isso.
ConsentInfo::GetInstance()->Reset();