Google User Messaging Platform (UMP) SDK — это инструмент конфиденциальности и обмена сообщениями, который поможет вам управлять вариантами конфиденциальности. Для получения дополнительной информации см. раздел О конфиденциальности и обмене сообщениями .
Предпосылки
- Android API уровня 21 или выше (для Android)
Создать тип сообщения
Создайте пользовательские сообщения с одним из доступных типов пользовательских сообщений на вкладке Конфиденциальность и сообщения вашего аккаунта AdMob. UMP SDK пытается отобразить сообщение о конфиденциальности, созданное из идентификатора приложения AdMob, установленного в вашем проекте.
Более подробную информацию см. в разделе О конфиденциальности и обмене сообщениями .
Установить SDK
Следуйте инструкциям по установке Firebase C++ SDK . UMP C++ SDK включен в Firebase C++ SDK.
Прежде чем продолжить, убедитесь, что вы настроили идентификатор приложения AdMob в проекте.
В своем коде инициализируйте 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
- На Android вам нужно передать
Последующие вызовы 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
:
- Вызовите
OnCompletion()
, передав собственную функцию обратного вызова, которая вызывается после завершения операции. - Периодически проверяйте
Future
status()
. Когда статус изменится сkFutureStatusPending
наkFutureStatusCompleted
, операция будет завершена.
После завершения асинхронной операции следует проверить Future
's 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 .
Получить информацию о согласии пользователя
Вам следует запрашивать обновление информации о согласии пользователя при каждом запуске приложения, используя 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 использует статус согласия из предыдущего сеанса приложения.
Следующий полный пример использует опрос цикла обновления, но вы также можете использовать обратные вызовы 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;
}
}
}
}
Тестирование
Если вы хотите протестировать интеграцию в своем приложении по мере разработки, выполните следующие шаги для программной регистрации вашего тестового устройства. Обязательно удалите код, который устанавливает эти идентификаторы тестовых устройств, прежде чем выпустить свое приложение.
- Вызовите
RequestConsentInfoUpdate()
. Проверьте вывод журнала на наличие сообщения, похожего на следующее, в котором указан идентификатор вашего устройства и порядок его добавления в качестве тестового устройства:
андроид
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]
Скопируйте идентификатор тестового устройства в буфер обмена.
Измените свой код, чтобы задать
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();