Cómo comenzar

Según la Política de Consentimiento de Usuarios de la UE de Google, debes divulgar determinada información a los usuarios del Espacio Económico Europeo (EEE) y el Reino Unido, y obtener su consentimiento para usar cookies y otro tipo de almacenamiento local cuando sea un requisito legal, así como utilizar datos personales (como el ID del anuncio) para publicar anuncios. Esta política refleja los requisitos de la Directiva de Privacidad Electrónica y el Reglamento General de Protección de Datos (GDPR) de la UE.

Para ayudar a los publicadores a cumplir con sus obligaciones en virtud de esta política, Google ofrece el SDK de User Messaging Platform (UMP). El SDK de UMP se actualizó para admitir los estándares más recientes de la IAB. Todas estas configuraciones ahora se pueden manejar de forma conveniente en AdMob privacidad y mensajería.

Requisitos previos

  • Nivel de API 21 o versiones posteriores(para Android)

Crea un tipo de mensaje

Crea mensajes para los usuarios con uno de los tipos de mensajes para el usuario disponibles en la pestaña Privacidad y mensajería de tu cuenta de AdMob . El SDK de UMP intenta mostrar un mensaje para el usuario creado a partir del AdMob ID de aplicación configurado en tu proyecto. Si no se configura ningún mensaje para tu aplicación, el SDK muestra un error.

Para obtener más detalles, consulta Acerca de la privacidad y la mensajería.

Cómo instalar el SDK

  1. Sigue los pasos para instalar el SDK de C++ de anuncios de Google para dispositivos móviles (GMA). El SDK de UMP para C++ se incluye en el SDK de GMA C++.

  2. Asegúrate de configurar el ID de app de AdMob de tu app en el proyecto antes de continuar.

  3. En tu código, inicializa el SDK de UMP llamando a ConsentInfo::GetInstance().

    • En Android, debes pasar los valores de JNIEnv y Activity que proporciona el NDK. Solo debes hacerlo la primera vez que llames al GetInstance().
    • Como alternativa, si ya usas el SDK de Firebase C++ en la app, puedes pasar un firebase::App la primera vez que llames a GetInstance().
    #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
    

Las llamadas posteriores a ConsentInfo::GetInstance() muestran la misma instancia.

Si terminaste de usar el SDK de UMP, puedes borrar la instancia ConsentInfo para cerrar el SDK:

void ShutdownUserMessagingPlatform() {
  ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance();
  delete consent_info;
}

Usa Future para supervisar operaciones asíncronas.

Un objeto firebase::Future te proporciona una manera de determinar el estado de las llamadas a métodos asíncronos.

Todas las funciones y llamadas de método de C++ de UMP que operan de forma asíncrona muestran un Future y también proporcionan una función de "último resultado" para recuperar el Future de la operación más reciente.

Existen dos maneras de obtener un resultado de un Future:

  1. Llama a OnCompletion() y pasa tu propia función de devolución de llamada, a la que se llama cuando se completa la operación.
  2. Revisa el status() de la Future de forma periódica. Cuando el estado cambie de kFutureStatusPending a kFutureStatusCompleted, significa que se completó la operación.

Una vez que se completa la operación asíncrona, debes verificar el error() de Future para obtener el código de error de la operación. Si el código de error es 0 (kConsentRequestSuccess o kConsentFormSuccess), la operación se completó correctamente. De lo contrario, verifica el código de error y error_message() para determinar qué salió mal.

Devolución de llamada de finalización

Este es un ejemplo de cómo usar OnCompletion para configurar una devolución de llamada de finalización, que se llama cuando se completa la operación asíncrona.

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

Actualiza el sondeo de bucle

En este ejemplo, después de que se inicia una operación asíncrona en el inicio de la app, los resultados se verifican en otro lugar, en la función de bucle de actualización del juego (que se ejecuta una vez por fotograma).

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 obtener más información sobre firebase::Future, consulta la documentación del SDK de Firebase C++ y la documentación del SDK de GMA C++.

Debes solicitar una actualización de la información de consentimiento del usuario en cada lanzamiento de la app mediante RequestConsentInfoUpdate(). Esto determina si tu usuario debe dar su consentimiento si aún no lo ha hecho o si venció.

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

Consulta la sección anterior para ver un ejemplo de cómo verificar la finalización con un sondeo de bucle de actualización en lugar de una devolución de llamada de finalización.

Carga y muestra un formulario de consentimiento si es necesario

Una vez que hayas recibido el estado de consentimiento más actualizado, llama aLoadAndShowConsentFormIfRequired() en la claseConsentInfo para cargar un formulario de consentimiento. Si se requiere el estado de consentimiento, el SDK carga un formulario y lo presenta de inmediato desde el FormParentproporcionado. Se llama a la Future se completa después de que se cierra el formulario. Si no se requiere consentimiento, el Future se completa de inmediato.

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

Si necesitas realizar alguna acción después de que el usuario haya elegido o descartado el formulario, coloca esa lógica en el código que controla el Future que muestra LoadAndShowConsentFormIfRequired().

Solicitar anuncios

Antes de solicitar anuncios en tu app, verifica si obtuviste el consentimiento del usuario que usa ConsentInfo::GetInstance()‑>CanRequestAds(). Hay dos lugares que debes verificar cuando obtienes el consentimiento:

  1. Una vez que se obtenga el consentimiento en la sesión actual.
  2. Inmediatamente después de llamar a RequestConsentInfoUpdate(). Es posible que se haya obtenido el consentimiento en la sesión anterior. Como práctica recomendada de latencia, te sugerimos no esperar a que se complete la devolución de llamada para que puedas comenzar a cargar anuncios lo antes posible después del lanzamiento de la app.
.

Si se produce un error durante el proceso de obtención del consentimiento, aún debes intentar solicitar anuncios. El SDK de UMP usa el estado de consentimiento de la sesión anterior.

En el siguiente ejemplo completo, se usa el sondeo de bucle de actualización, pero también puedes usar las devoluciones de llamada OnCompletion para supervisar las operaciones asíncronas. Usa la técnica que se adapte mejor a la estructura de tu 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;
      }
    }
  }
}

Opciones de privacidad

Algunos formularios de consentimiento requieren que el usuario modifique su consentimiento en cualquier momento. Sigue los pasos que se indican a continuación para implementar un botón de opciones de privacidad si es necesario.

Entonces:

  1. Implementa un elemento de la IU, como un botón en la página de configuración de la app, que pueda activar un formulario de opciones de privacidad.
  2. Una vez que se complete LoadAndShowConsentFormIfRequired() , verificagetPrivacyOptionsRequirementStatus() para determinar si quieres mostrar el elemento de la IU que puede presentar el formulario de opciones de privacidad.
  3. Cuando un usuario interactúe con tu elemento de la IU, llama ashowPrivacyOptionsForm() para mostrar el formulario, de modo que el usuario pueda actualizar sus opciones de privacidad en cualquier momento.

Prueba

Si quieres probar la integración en la app mientras desarrollas, sigue estos pasos para registrar tu dispositivo de prueba de manera programática. Asegúrate de quitar el código que establece estos IDs de dispositivos de prueba antes de lanzar la app.

  1. Llama a RequestConsentInfoUpdate().
  2. Busca el resultado del registro en busca de un mensaje similar al siguiente ejemplo, que muestre el ID de tu dispositivo y cómo agregarlo como un dispositivo de prueba:

    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. Copia el ID de tu dispositivo de prueba en el portapapeles.

  4. Modifica tu código para configurar ConsentRequestParameters.debug_settings.debug_device_ids para una lista de los IDs de tus dispositivos de prueba.

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

Cómo forzar una ubicación geográfica

El SDK de UMP proporciona una forma de probar el comportamiento de tu app como si el dispositivo se encontrara en el EEE o el Reino Unido con ConsentRequestParameters.debug_settings.debug_geography. Ten en cuenta que esta configuración solo funciona en dispositivos de prueba.

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

Cuando pruebes tu app con el SDK de UMP, tal vez te resulte útil restablecer el estado del SDK para simular la experiencia de la primera instalación de un usuario. El SDK proporciona el método Reset() para hacerlo.

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