Начать

Google User Messaging Platform (UMP) SDK – это инструмент для управления настройками конфиденциальности и сообщениями. Подробнее о разделе "Конфиденциальность и сообщения"…

Требования

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

Как создать тип сообщения

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

Подробнее о конфиденциальности и сообщениях…

Установите SDK

  1. Следуйте инструкциям по установке Firebase C++ SDK. UMP C++ SDK входит в состав Firebase C++ SDK.

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

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

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

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

Если вы закончили использовать UMP 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. Периодически проверяйте Futurestatus(). Когда статус изменится с kFutureStatusPending на kFutureStatusCompleted, операция будет завершена.

После завершения асинхронной операции проверьте Futureerror(), чтобы узнать код ошибки. Если код ошибки 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…

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

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

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

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

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

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

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

Настройки конфиденциальности

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

Как запрашивать объявления с согласием пользователя

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

Ниже перечислены места, где можно проверить, можно ли запрашивать объявления при сборе согласия:

  • После того как UMP SDK получит согласие в текущем сеансе.
  • Сразу после вызова метода RequestConsentInfoUpdate(). UMP SDK мог получить согласие в предыдущем сеансе приложения.

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

Предотвращение избыточной работы по запросу объявлений

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

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

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

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

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

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

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

  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 позволяет тестировать поведение приложения так, как если бы устройство находилось в разных регионах, например в Европейской экономической зоне (ЕЭЗ), Великобритании и Швейцарии, с помощью 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();