Comenzar

El SDK de Google User Messaging Platform (UMP) es una herramienta de privacidad y mensajería que te ayuda a administrar las opciones de privacidad. Para obtener más información, consulta Acerca de Privacidad y mensajería.

Requisitos previos

  • Nivel de API de Android 21 o superior (para Android)

Crea un tipo de mensaje

Crea mensajes para los usuarios con uno de los tipos de mensajes disponibles para los usuarios en la pestaña Privacidad y mensajería de tu cuenta de AdMob. El SDK de UMP intenta mostrar un mensaje de privacidad creado a partir del ID de aplicación de AdMob establecido en tu proyecto.

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

Cómo instalar el SDK

  1. Sigue los pasos para instalar el SDK de Firebase para C++. El SDK de UMP para C++ se incluye en el SDK de Firebase C++.

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

  3. En tu código, llama a ConsentInfo::GetInstance() para inicializar el SDK de UMP.

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

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

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

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

Usa un Future para supervisar las operaciones asíncronas

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

Todas las funciones de C++ de la UMP y las llamadas de método que operan de forma asíncrona devuelven un objeto Future y también proporcionan una función "last result" para recuperar el objeto 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. Verifica periódicamente el status() del Future. Cuando el estado cambia de kFutureStatusPending a kFutureStatusCompleted, la operación se completó.

Una vez que se complete 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

A continuación, se muestra un ejemplo de cómo usar OnCompletion para establecer 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 para C++.

Debes solicitar una actualización de la información de consentimiento del usuario cada vez que se inicie la app con RequestConsentInfoUpdate(). Esta solicitud verifica lo siguiente:

  • Si se requiere consentimiento. Por ejemplo, se requiere el consentimiento por primera vez o venció la decisión de consentimiento anterior.
  • Si se requiere un punto de entrada de opciones de privacidad Algunos mensajes de privacidad requieren que las apps permitan a los usuarios modificar sus opciones de privacidad en cualquier 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.
    });
}

Carga y presenta el formulario de mensaje de privacidad

Después de recibir el estado de consentimiento más actualizado, llama a LoadAndShowConsentFormIfRequired() para cargar los formularios necesarios para obtener el consentimiento del usuario. Después de cargarse, los formularios se presentan de inmediato.

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

Consulta más arriba 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.

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

Opciones de privacidad

Algunos formularios de mensajes de privacidad se presentan desde un punto de entrada de opciones de privacidad renderizado por el publicador, lo que permite a los usuarios administrar sus opciones de privacidad en cualquier momento. Para obtener más información sobre qué mensaje ven los usuarios en el punto de entrada de las opciones de privacidad, consulta Tipos de mensajes disponibles para los usuarios.

Solicita anuncios con el consentimiento del usuario

Antes de solicitar anuncios, usa ConsentInfo::GetInstance()‑> CanRequestAds() para verificar si obtuviste el consentimiento del usuario:

A continuación, se indican los momentos en los que puedes verificar si puedes solicitar anuncios mientras recopilas el consentimiento:

  • Después de que el SDK de UMP recopile el consentimiento en la sesión actual
  • Inmediatamente después de que hayas llamado a RequestConsentInfoUpdate(). Es posible que el SDK de UMP haya obtenido el consentimiento en la sesión anterior de la app.

Si se produce un error durante el proceso de recopilación de consentimiento, verifica si puedes solicitar anuncios. El SDK de UMP usa el estado de consentimiento de la sesión anterior de la app.

Evita solicitudes de anuncios redundantes

Cuando verifiques ConsentInfo::GetInstance()‑> CanRequestAds() después de obtener el consentimiento y después de llamar a RequestConsentInfoUpdate(), asegúrate de que tu lógica evite solicitudes de anuncios redundantes que puedan ocurrir si ambas verificaciones devuelven true. Por ejemplo, con una variable booleana.

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

Pruebas

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

  1. Llamar a RequestConsentInfoUpdate()
  2. Verifica que la salida del registro incluya un mensaje como el del siguiente ejemplo, que indica tu ID de dispositivo y la manera de 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 tu ID de dispositivo de prueba en el portapapeles.

  4. Modifica tu código para establecer ConsentRequestParameters.debug_settings.debug_device_ids en una lista de tus IDs de 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);
    }
    

Fuerza el uso de una ubicación geográfica

El SDK de UMP proporciona una forma de probar el comportamiento de tu app como si el dispositivo estuviera ubicado en varias regiones, como el Espacio Económico Europeo (EEE), el Reino Unido (UK) y Suiza, con debug_settings.debug_geography. Ten en cuenta que la configuración de depuració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, puede resultarte ú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();