Começar

O SDK da plataforma de mensagens aos usuários (UMP) do Google é uma ferramenta de privacidade e mensagens para ajudar você a gerenciar as opções de privacidade. Para mais informações, consulte Sobre a página "Privacidade e mensagens".

Pré-requisitos

  • Nível 21 da API do Android ou mais recente (para Android)

Criar um tipo de mensagem

Crie mensagens aos usuários com um dos tipos de mensagens aos usuários disponíveis na guia Privacidade e mensagens da sua conta da AdMob. O SDK da UMP tenta mostrar uma mensagem de privacidade criada com base no ID do aplicativo da AdMob definido no seu projeto.

Para mais detalhes, consulte Sobre privacidade e mensagens.

Instalar o SDK

  1. Siga as etapas para instalar o SDK do Firebase para C++. O SDK da UMP para C++ está incluído no SDK do Firebase para C++.

  2. Configure o ID do app da AdMob no projeto antes de continuar.

  3. No seu código, inicialize o SDK da UMP chamando ConsentInfo::GetInstance().

    • No Android, você precisa transmitir o JNIEnv e o Activity fornecidos pelo NDK. Você só precisa fazer isso na primeira vez que chamar GetInstance().
    • Como alternativa, se você já estiver usando o SDK do Firebase C++ no seu app, transmita um firebase::App na primeira vez que chamar GetInstance().
    #include "firebase/ump/ump.h"
    
    namespace ump = ::firebase::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
    

As chamadas subsequentes para ConsentInfo::GetInstance() retornam a mesma instância.

Se você terminar de usar o SDK da UMP, poderá encerrá-lo 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 permite determinar o status de conclusão das chamadas de método assíncronas.

Todas as funções e chamadas de método C++ da UMP que operam de forma assíncrona retornam um Future e também fornecem uma função de "último resultado" para recuperar o Future da operação mais recente.

Há duas maneiras de receber um resultado de um Future:

  1. Chame OnCompletion(), transmitindo sua própria função de callback, que é chamada quando a operação é concluída.
  2. Verifique periodicamente o status() do Future. Quando o status muda de kFutureStatusPending para kFutureStatusCompleted, a operação foi concluída.

Depois que a operação assíncrona for concluída, verifique o Future do error() 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.
    }
  });
}

Pesquisa de loop de atualização

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++.

Você precisa solicitar uma atualização das informações de consentimento do usuário a cada inicialização do app usando RequestConsentInfoUpdate(). Essa solicitação verifica o seguinte:

  • Se o consentimento é obrigatório. Por exemplo, o consentimento é necessário pela primeira vez ou a decisão de consentimento anterior expirou.
  • Se um ponto de entrada de opções de privacidade é necessário. Algumas mensagens de privacidade exigem que os apps permitam que os usuários modifiquem as opções de privacidade a qualquer momento.
#include "firebase/ump/ump.h"

namespace ump = ::firebase::ump;

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());
      }
      // Consent information is successfully updated.
    });
}

Carregar e apresentar o formulário de mensagem de privacidade

Depois de receber o status de consentimento mais atualizado, chame LoadAndShowConsentFormIfRequired() para carregar os formulários necessários para coletar o consentimento do usuário. Depois do carregamento, os formulários aparecem imediatamente.

#include "firebase/ump/ump.h"

namespace ump = ::firebase::ump;

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 privacy message form: %s", form_result.error_message());
          } else {
            // Either the form was shown and completed by the user, or consent was not required.
          }
        });
      }
    });
}

Consulte acima para ver um exemplo de como verificar a conclusão usando a pesquisa de loop de atualização em vez de um callback de conclusão.

Se você precisar realizar 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().

Opções de privacidade

Alguns formulários de mensagens de privacidade são apresentados em um ponto de entrada de opções de privacidade renderizado pelo editor, permitindo que os usuários gerenciem as opções de privacidade a qualquer momento. Para saber mais sobre qual mensagem é exibida aos usuários no ponto de entrada das opções de privacidade, consulte Tipos de mensagens disponíveis para o usuário.

Solicitar anúncios com o consentimento do usuário

Antes de solicitar anúncios, use ConsentInfo::GetInstance()‑> CanRequestAds() para verificar se você obteve o consentimento do usuário:

Confira a seguir os locais em que você pode pedir anúncios enquanto coleta consentimento:

  • Depois que o SDK da UMP coleta o consentimento na sessão atual.
  • Imediatamente depois de chamar RequestConsentInfoUpdate(). O SDK da UMP pode ter recebido consentimento na sessão anterior do app.

Se ocorrer um erro durante o processo de coleta de consentimento, verifique se você pode solicitar anúncios. O SDK da UMP usa o status de consentimento da sessão anterior do app.

O exemplo completo a seguir usa a pesquisa de loop de atualização, mas você também pode usar callbacks OnCompletion para monitorar operações assíncronas. Use a técnica que melhor se adapta à estrutura do seu código.

#include "firebase/future.h"
#include "firebase/gma/gma.h"
#include "firebase/ump/ump.h"

namespace gma = ::firebase::gma;
namespace ump = ::firebase::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 privacy message 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;
      }
    }
  }
}

Teste

Se você quiser testar a integração no app durante o desenvolvimento, siga estas etapas para registrar seu dispositivo de teste de maneira programática. Remova o código que define esses IDs de dispositivo de teste antes de lançar o app.

  1. Ligue para a RequestConsentInfoUpdate().
  2. Verifique a saída do registro em busca de 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]
    
  3. Copie o ID do dispositivo de teste para a área de transferência.

  4. Modifique seu código para definir ConsentRequestParameters.debug_settings.debug_device_ids como 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 em várias regiões, como o EEE ou o Reino Unido, usando 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);
}

Ao testar o app com o SDK da UMP, talvez seja útil redefinir o estado do SDK para simular a experiência de primeira instalação de um usuário. O SDK fornece o método Reset() para fazer isso.

  ConsentInfo::GetInstance()->Reset();