Wypróbuj

Zgodnie z polityką Google w zakresie zgody użytkownika z UE musisz udzielać odpowiednich informacji użytkownikom z Europejskiego Obszaru Gospodarczego (EOG) i Wielkiej Brytanii oraz uzyskiwać ich zgodę na stosowanie plików cookie lub innych środków do lokalnego przechowywania danych, jeśli jest to wymagane prawnie, oraz na wykorzystywanie danych osobowych (takich jak AdID) do wyświetlania reklam. Polityka ta odzwierciedla wymagania UE zawarte w dyrektywie o prywatności i łączności elektronicznej oraz w Ogólnym rozporządzeniu o ochronie danych (RODO).

Aby pomóc wydawcom w wypełnieniu obowiązków, jakie nakłada na nich ta polityka, Google oferuje pakiet SDK User Messaging Platform (UMP). Pakiet UMP SDK został zaktualizowany, aby był zgodny z najnowszymi standardami IAB. Wszystkimi tymi konfiguracjami można teraz wygodnie zarządzać AdMob na stronie „Prywatność i wyświetlanie wiadomości”.

Wymagania wstępne

  • Android API na poziomie 21 lub wyższym (w przypadku Androida)

Tworzenie typu wiadomości

Utwórz wiadomości dla użytkowników, używając jednego z dostępnych typów wiadomości dla użytkowników na karcie Prywatność i wyświetlanie wiadomości na koncie AdMob . Pakiet UMP SDK próbuje wyświetlić wiadomość dla użytkownika utworzoną na podstawie AdMob identyfikatora aplikacji ustawionego w Twoim projekcie. Jeśli dla aplikacji nie jest skonfigurowany żaden komunikat, pakiet SDK zwróci błąd.

Więcej informacji znajdziesz w artykule Prywatność i wyświetlanie wiadomości.

Zainstaluj pakiet SDK

  1. Wykonaj te czynności, by zainstalować pakiet SDK do reklam mobilnych Google (GMA) w języku C++. Pakiet UMP C++ SDK znajdziesz w pakiecie GMA C++ SDK.

  2. Zanim przejdziesz dalej, skonfiguruj identyfikator aplikacji AdMob w projekcie.

  3. W swoim kodzie zainicjuj pakiet UMP SDK, wywołując metodę ConsentInfo::GetInstance().

    • W przypadku Androida musisz przekazać JNIEnv i Activity udostępnione przez NDK. Wykonując tę czynność tylko przy pierwszym połączeniu z GetInstance().
    • Jeśli w swojej aplikacji używasz już pakietu SDK Firebase C++, możesz przekazać firebase::App przy pierwszym wywołaniu 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
    

Kolejne wywołania funkcji ConsentInfo::GetInstance() zwracają tę samą instancję.

Jeśli przestaniesz korzystać z pakietu UMP SDK, możesz go wyłączyć, usuwając instancję ConsentInfo:

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

Future do monitorowania operacji asynchronicznych

firebase::Future umożliwia określenie stanu zakończenia wywołań metod asynchronicznych.

Wszystkie funkcje i wywołania metod UMP w języku C++, które działają asynchronicznie, zwracają wartość Future oraz udostępniają funkcję „ostatni wynik” pobierającą Future z ostatniej operacji.

Wynik z Future można uzyskać na 2 sposoby:

  1. Wywołaj OnCompletion(), przekazując własną funkcję wywołania zwrotnego, która jest wywoływana po zakończeniu operacji.
  2. Co jakiś czas sprawdzaj: status() usługi Future. Gdy stan zmieni się z kFutureStatusPending na kFutureStatusCompleted, operacja została ukończona.

Po zakończeniu operacji asynchronicznej sprawdź error() w Future, aby uzyskać kod błędu operacji. Jeśli kod błędu to 0 (kConsentRequestSuccess lub kConsentFormSuccess), operacja została ukończona. W przeciwnym razie sprawdź kod błędu i error_message(), aby ustalić, co poszło nie tak.

Zakończenie oddzwaniania

Oto przykład użycia metody OnCompletion do ustawienia wywołania zwrotnego zakończenia, które jest wywoływane po zakończeniu operacji asynchronicznej.

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

Zaktualizuj odpytywanie w pętli

W tym przykładzie po uruchomieniu operacji asynchronicznej przy uruchamianiu aplikacji wyniki są sprawdzane w innym miejscu, w funkcji pętli aktualizacji gry (która jest uruchamiana raz na klatkę).

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

Więcej informacji o firebase::Future znajdziesz w dokumentacji pakietu SDK Firebase C++ i dokumentacji pakietu SDK GMA C++ SDK.

Należy prosić o aktualizację informacji o zgodzie użytkownika przy każdym uruchomieniu aplikacji za pomocą narzędzia RequestConsentInfoUpdate(). Określa, czy użytkownik musi wyrazić zgodę, jeśli jeszcze tego nie zrobił, czy też wygasła.

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

powyżej znajdziesz przykład sprawdzania ukończenia za pomocą odpytywania w pętli aktualizacji, a nie wywołania zwrotnego jako zakończenia.

W razie potrzeby wczytaj i wyświetl formularz zgody

Po uzyskaniu najbardziej aktualnego stanu zgody wywołajLoadAndShowConsentFormIfRequired() wConsentInfo klasie, aby wczytać formularz zgody. Jeśli stan zgody użytkownika jest wymagany, pakiet SDK wczytuje formularz i natychmiast wyświetla go z przesłanego FormParent. Po zamknięciu formularza Future jest wypełniany . Jeśli zgoda nie jest wymagana, Future zostanie zrealizowane natychmiast.

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

Jeśli musisz wykonać jakieś działania po dokonaniu wyboru lub zamknięciu formularza przez użytkownika, umieść tę logikę w kodzie, który obsługuje polecenie Future zwrócone przez LoadAndShowConsentFormIfRequired().

Wyślij żądanie

Zanim wyślesz prośbę o reklamy w aplikacji, sprawdź, czy masz zgodę użytkownika za pomocą ConsentInfo::GetInstance()‑>CanRequestAds(). Uzyskując zgodę, można to sprawdzić w dwóch miejscach:

  1. Po uzyskaniu zgody użytkownika podczas bieżącej sesji.
  2. Zaraz po nawiązaniu połączenia z firmą RequestConsentInfoUpdate(). Możliwe, że w poprzedniej sesji użytkownik wyraził zgodę. Zalecamy, aby nie czekać na zakończenie wywołania zwrotnego i w razie potrzeby zacząć wczytywać reklamy jak najszybciej po uruchomieniu aplikacji.

Jeśli podczas uzyskiwania zgody użytkowników wystąpi błąd, nadal próbuj wysyłać żądania reklam. Pakiet UMP SDK używa stanu zgody z poprzedniej sesji.

Pełny przykład poniżej korzysta z odpytywania w pętlę aktualizacji, ale do monitorowania operacji asynchronicznych możesz też używać wywołań zwrotnych OnCompletion. Użyj metody, która lepiej pasuje do struktury Twojego kodu.

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

Opcje prywatności

Niektóre formularze zgody wymagają od użytkownika zmiany zgody w dowolnym momencie. Aby w razie potrzeby zaimplementować przycisk opcji prywatności, wykonaj te czynności.

W tym celu:

  1. Zaimplementuj element interfejsu, np. przycisk na stronie ustawień aplikacji, który będzie uruchamiać formularz opcji prywatności.
  2. Po LoadAndShowConsentFormIfRequired() zakończenia sprawdźgetPrivacyOptionsRequirementStatus() , czy wyświetlić element interfejsu, który może wyświetlić formularz opcji prywatności.
  3. Gdy użytkownik wejdzie w interakcję z elementem interfejsu, wywołajshowPrivacyOptionsForm() , aby wyświetlić formularz. Dzięki temu w każdej chwili będzie mógł zaktualizować swoje opcje prywatności.

Testuję

Jeśli chcesz przetestować integrację ze swoją aplikacją w trakcie jej programowania, wykonaj te czynności, aby automatycznie zarejestrować urządzenie testowe. Pamiętaj, by przed opublikowaniem aplikacji usunąć kod, który ustawia te identyfikatory urządzeń testowych.

  1. Zadzwoń pod numer RequestConsentInfoUpdate().
  2. Sprawdź w logu, czy w danych wyjściowych znajduje się komunikat podobny do tego poniżej. Zawiera on identyfikator urządzenia i sposób dodawania go jako urządzenia testowego:

    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. Skopiuj identyfikator urządzenia testowego do schowka.

  4. Zmodyfikuj kod, aby ustawiać ConsentRequestParameters.debug_settings.debug_device_ids listę identyfikatorów urządzeń testowych.

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

Wymuś użycie lokalizacji geograficznej

Pakiet UMP SDK umożliwia przetestowanie działania aplikacji w taki sposób, jakby urządzenie znajdowało się w Europejskim Obszarze Gospodarczym lub Wielkiej Brytanii za pomocą usługi ConsentRequestParameters.debug_settings.debug_geography. Pamiętaj, że ustawienia debugowania działają tylko na urządzeniach testowych.

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

Podczas testowania aplikacji za pomocą pakietu SDK UMP warto zresetować stan pakietu SDK, aby przeprowadzić symulację pierwszej instalacji aplikacji u użytkownika. Pakiet SDK udostępnia metodę Reset() .

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