Начало работы

SDK Google User Messaging Platform (UMP) – это инструмент конфиденциальности и обмена сообщениями, который поможет вам управлять настройками конфиденциальности. Для получения дополнительной информации см.О конфиденциальности и обмене сообщениями .

Предварительные условия

  • Android API уровня 21 или выше(для Android)

Создайте тип сообщения

Создавайте пользовательские сообщения с помощью одного изДоступных типов пользовательских сообщенийна вкладке Конфиденциальность и сообщения вашей учетной записиAdMob. UMP SDK пытается отобразить сообщение о конфиденциальности, созданное на основе идентификатора приложения AdMob установленного в вашем проекте.

Дополнительные сведения см.О конфиденциальности и обмене сообщениями .

Установите SDK

  1. Следуйте инструкциям по установке Google Mobile Ads (GMA) C++ SDK . UMP C++ SDK включен в GMA C++ SDK.

  2. Прежде чем продолжить, убедитесь, что вы настроили идентификатор приложения AdMob в проекте.

  3. В своем коде инициализируйте UMP SDK, вызвав ConsentInfo::GetInstance() .

    • На Android вам необходимо передать JNIEnv и Activity , предоставленные NDK. Вам нужно сделать это только при первом вызове GetInstance() .
    • В качестве альтернативы, если вы уже используете Firebase C++ SDK в своем приложении, вы можете передать firebase::App при первом вызове 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
    

Последующие вызовы ConsentInfo::GetInstance() возвращают один и тот же экземпляр.

Если вы закончили использовать UMP SDK, вы можете закрыть SDK, удалив экземпляр ConsentInfo :

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

Используйте Future для мониторинга асинхронных операций

firebase::Future предоставляет вам возможность определить статус завершения вызовов асинхронных методов.

Все функции и вызовы методов UMP C++, которые работают асинхронно, возвращают Future , а также предоставляют функцию «последнего результата» для получения Future из самой последней операции.

Есть два способа получить результат из Future :

  1. Вызовите OnCompletion() , передав собственную функцию обратного вызова, которая вызывается после завершения операции.
  2. Периодически проверяйте статус Future status() . Когда статус меняется с kFutureStatusPending на kFutureStatusCompleted , операция завершена.

После завершения асинхронной операции вам следует проверить функцию Future error() , чтобы получить код ошибки операции. Если код ошибки равен 0 ( kConsentRequestSuccess или kConsentFormSuccess ), операция завершена успешно; в противном случае проверьте код ошибки и error_message() чтобы определить, что пошло не так.

Обратный вызов завершения

Вот пример того, как использовать OnCompletion для установки обратного вызова завершения, который вызывается после завершения асинхронной операции.

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

Обновление опроса цикла

В этом примере после запуска асинхронной операции при запуске приложения результаты проверяются в другом месте, в функции цикла обновления игры (которая выполняется один раз за кадр).

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

Дополнительные сведения о firebase::Future см. в документации Firebase C++ SDK и документации GMA C++ SDK .

Добавьте идентификатор приложения

Идентификатор вашего приложения можно найти в пользовательском интерфейсе AdMob.Добавьте идентификатор в свойс помощью следующего фрагмента кода:

Вам следует запрашивать обновление информации о согласии пользователя при каждом запуске приложения, используя RequestConsentInfoUpdate(). Этот запрос проверяет следующее:

  • Требуется ли согласие . Например, согласие требуется в первый раз или срок действия предыдущего решения о согласии истек.
  • Требуется ли точка входа для параметров конфиденциальности . Некоторые сообщения о конфиденциальности требуют, чтобы приложения позволяли пользователям изменять параметры конфиденциальности в любое время.
#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.
      }
    });
}

См . выше пример проверки завершения с использованием опроса цикла обновления, а не обратного вызова завершения.

Загрузите и предоставьте форму сообщения о конфиденциальности, если требуется.

После того как вы получите самую последнюю информацию о статусе согласия, позвоните поLoadAndShowConsentFormIfRequired() чтобы загрузить все формы, необходимые для получения согласия пользователя. После загрузки формы отображаются сразу.

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

Если вам нужно выполнить какие-либо действия после того, как пользователь сделал выбор или закрыл форму, поместите эту логику в код, который обрабатывает Future возвращаемый LoadAndShowConsentFormIfRequired() .

Параметры конфиденциальности

Некоторые формы сообщений о конфиденциальности представляются из точки входа параметров конфиденциальности, созданной издателем, что позволяет пользователям управлять своими параметрами конфиденциальности в любое время. Чтобы узнать больше о том, какое сообщение ваши пользователи видят в точке входа в параметры конфиденциальности, см.Доступные типы сообщений пользователя .

Чтобы реализовать точку входа параметров конфиденциальности, выполните следующие действия:

  1. Проверьте getPrivacyOptionsRequirementStatus().
  2. Если требуется точка входа параметров конфиденциальности, добавьте в свое приложение видимый и интерактивный элемент пользовательского интерфейса.
  3. Запустите форму параметров конфиденциальности, используяshowPrivacyOptionsForm().

Следующий пример кода демонстрирует эти шаги:

Запросить рекламу

Прежде чем запрашивать рекламу в своем приложении, проверьте, получили ли вы согласие от пользователя с помощью ConsentInfo::GetInstance()‑>CanRequestAds(). При получении согласия необходимо проверить два места:

  • После того, как согласие было получено в текущем сеансе.
  • Сразу после того, как вы вызвали RequestConsentInfoUpdate(). Возможно, согласие было получено на предыдущем сеансе. В целях снижения задержки мы рекомендуем не дожидаться завершения обратного вызова, чтобы вы могли начать загрузку рекламы как можно скорее после запуска приложения.

Если в процессе сбора согласия возникает ошибка, вам все равно следует попытаться запросить рекламу. UMP SDK использует статус согласия из предыдущего сеанса.

В следующем полном примере используется опрос цикла обновления, но вы также можете использовать обратные вызовы OnCompletion для мониторинга асинхронных операций. Используйте тот метод, который лучше соответствует вашей структуре кода.

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

Тестирование

Если вы хотите протестировать интеграцию в своем приложении во время разработки, выполните следующие действия, чтобы программно зарегистрировать свое тестовое устройство. Обязательно удалите код, который устанавливает эти идентификаторы тестовых устройств, прежде чем выпускать приложение.

  1. Вызовите RequestConsentInfoUpdate().
  2. Проверьте вывод журнала на наличие сообщения, похожего на следующий пример, в котором показан идентификатор вашего устройства и способы его добавления в качестве тестового устройства:

    Андроид

    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. Скопируйте идентификатор тестового устройства в буфер обмена.

  4. Измените свой код на , установите дляConsentRequestParameters.debug_settings.debug_device_ids значение список идентификаторов тестовых устройств.

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

Принудительно использовать географию

UMP SDK предоставляет возможность протестировать поведение вашего приложения, как если бы устройство находилось в ЕЭЗ или Великобритании, с помощью ConsentRequestParameters.debug_settings.debug_geography. Обратите внимание, что настройки отладки работают только на тестовых устройствах.

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

При тестировании приложения с помощью UMP SDK вам может оказаться полезным сбросить состояние SDK, чтобы можно было имитировать первый опыт установки пользователя. Для этого в SDK предусмотрен метод Reset() .

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

Примеры на GitHub