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 uzyskać ich zgodę na stosowanie plików cookie lub innych środków do lokalnego przechowywania danych, jeśli jest to wymagane prawnie. Musisz też uzyskać ich zgodę 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). Zaktualizowaliśmy pakiet UMP SDK, aby obsługiwał najnowsze standardy IAB. Wszystkimi tymi konfiguracjami możesz teraz wygodnie zarządzać na stronie AdMob prywatności i przesyłania wiadomości.

Wymagania wstępne

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

Tworzenie typu wiadomości

Utwórz wiadomości dla użytkowników za pomocą dostępnego typu 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 zwraca błąd.

Więcej informacji znajdziesz w artykule Informacje o prywatności i przesyłaniu wiadomości.

Zainstaluj pakiet SDK

  1. Wykonaj te czynności, aby zainstalować pakiet SDK do reklam mobilnych Google (GMA) C++. Pakiet UMP C++ SDK jest częścią pakietu GMA C++ SDK.

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

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

    • W Androidzie musisz zaliczyć JNIEnv i Activity dostarczone przez NDK. Musisz to zrobić tylko przy pierwszym połączeniu z numerem GetInstance().
    • Jeśli w swojej aplikacji używasz już pakietu SDK Firebase w C++, możesz też 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 ConsentInfo::GetInstance() zwracają tę samą instancję.

Jeśli korzystasz już 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;
}

Używanie metody Future do monitorowania operacji asynchronicznych

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

Wszystkie funkcje i wywołania metod UMP C++, które działają asynchronicznie, zwracają parametr Future oraz zapewniają funkcję „ostatniego wyniku”, która pobiera Future z ostatniej operacji.

Wynik można uzyskać z Future 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. Okresowo sprawdzaj status() na urządzeniu Future. Gdy stan zmieni się z kFutureStatusPending na kFutureStatusCompleted, operacja została ukończona.

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

Ukończenie wywołania zwrotnego

Oto przykład użycia funkcji OnCompletion do ustawienia wywołania zwrotnego uzupełniającego, 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.
    }
  });
}

Aktualizowanie sondowania w pętli

W tym przykładzie, gdy operacja asynchroniczna zostanie uruchomiona przy uruchomieniu aplikacji, wyniki są sprawdzane w innym miejscu – w funkcji pętli aktualizacji gry (która uruchamia się 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 na temat firebase::Future znajdziesz w dokumentacji pakietu SDK Firebase C++ SDK i dokumentacji pakietu SDK do reklam mobilnych Google C++ SDK.

Po każdym uruchomieniu aplikacji musisz prosić użytkownika o aktualizację informacji o zgodzie użytkownika za pomocą funkcji RequestConsentInfoUpdate(). Pozwala to określić, 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 zamiast wywołania zwrotnego w trakcie całego procesu.

Wczytaj i wyświetl formularz zgody, jeśli jest to wymagane

Gdy otrzymasz najbardziej aktualny stan zgody, zadzwońLoadAndShowConsentFormIfRequired() naConsentInfo zajęcia, aby wczytać formularz zgody. Jeśli stan zgody jest wymagany, pakiet SDK wczytuje formularz i od razu wyświetla go z przesłanych FormParent. Po zamknięciu formularza Future jest ukończony . Jeśli zgoda nie jest wymagana, proces Future jest ukończony .

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 po dokonaniu wyboru przez użytkownika lub zamknięciu formularza musisz wykonać jakieś działanie, umieść tę logikę w kodzie obsługującym Future zwracany przez LoadAndShowConsentFormIfRequired().

Wyślij żądanie

Zanim poprosisz o reklamy w aplikacji, sprawdź, czy masz zgodę użytkownika korzystającego z usługi ConsentInfo::GetInstance()‑>CanRequestAds(). Zgodę należy sprawdzić w 2 miejscach:

  1. Gdy w bieżącej sesji uzyskasz zgodę użytkowników.
  2. Zaraz po rozmowie telefonicznej z firmą RequestConsentInfoUpdate(). Możliwe, że zgoda została udzielona w poprzedniej sesji. Zalecamy, aby nie czekać na zakończenie wywołania zwrotnego, ponieważ pozwoli to rozpocząć ładowanie reklam jak najszybciej po uruchomieniu aplikacji.

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

Poniższy pełny przykład wykorzystuje odpytywanie w pętli aktualizacji, ale do monitorowania operacji asynchronicznych możesz używać też wywołań zwrotnych OnCompletion. Używaj tej metody, która lepiej pasuje do Twojej struktury 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 wprowadzenia zmian w dowolnym momencie. Aby w razie potrzeby zaimplementować przycisk opcji prywatności, postępuj zgodnie z poniższymi instrukcjami.

W tym celu:

  1. Zaimplementuj element interfejsu, np. przycisk na stronie ustawień aplikacji, który może uruchamiać formularz opcji prywatności.
  2. Gdy LoadAndShowConsentFormIfRequired() to się zakończy, zaznaczgetPrivacyOptionsRequirementStatus() , aby określić, czy wyświetlić element interfejsu, który może wyświetlać formularz opcji prywatności.
  3. Gdy użytkownik wejdzie w interakcję z elementem interfejsu, wywołajshowPrivacyOptionsForm() , aby wyświetlić formularz. Dzięki temu będzie mógł w dowolnym momencie zaktualizować swoje opcje prywatności.

Testowanie

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

  1. Zadzwoń pod numer RequestConsentInfoUpdate().
  2. Sprawdź, czy w danych wyjściowych logu nie pojawia się komunikat podobny do tego przykładowego poniżej, który zawiera identyfikator urządzenia i informuje, jak dodać go jako urządzenie testowe:

    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 tak, aby 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ś ustawienie geograficzne

Pakiet UMP SDK umożliwia przetestowanie działania aplikacji tak, jakby urządzenie znajdowało się w Europejskim Obszarze Gospodarczym lub Wielkiej Brytanii w ramach 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 UMP SDK warto zresetować stan tego pakietu, aby zasymulować proces pierwszej instalacji przez użytkownika. Pakiet SDK udostępnia Reset() metodę pozwalającą to zrobić.

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