Rozpocznij

Pakiet SDK platformy do personalizowania wiadomości wyświetlanych użytkownikom (UMP) od Google to narzędzie do obsługi prywatności i wyświetlania wiadomości, które pomaga zarządzać ustawieniami prywatności. Więcej informacji znajdziesz w artykule Prywatność i wyświetlanie wiadomości.

Wymagania wstępne

  • Android API w wersji 21 lub nowszej (w przypadku Androida)

Tworzenie typu wiadomości

Twórz wiadomości dla użytkowników, korzystając z jednego z dostępnych typów wiadomości na karcie Prywatność i wyświetlanie wiadomości na koncie AdMob. Pakiet SDK UMP próbuje wyświetlić wiadomość dotyczącą prywatności utworzoną na podstawie identyfikatora aplikacji AdMob ustawionego w projekcie.

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

Instalowanie pakietu SDK

  1. Wykonaj czynności opisane w instrukcji instalowania pakietu SDK Firebase C++. Pakiet SDK UMP C++ jest zawarty w pakiecie SDK Firebase C++.

  2. Zanim przejdziesz dalej, upewnij się, że w projekcie skonfigurowano identyfikator aplikacji w AdMob.

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

    • W Androidzie musisz przekazać JNIEnv i Activity udostępniane przez NDK. Musisz to zrobić tylko przy pierwszym wywołaniu funkcji GetInstance().
    • Jeśli w aplikacji używasz już pakietu SDK Firebase C++, możesz też przekazać firebase::App przy pierwszym wywołaniu funkcji 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
    

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

Gdy skończysz korzystać z pakietu SDK UMP, możesz go wyłączyć, usuwając instancję ConsentInfo:

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

Używanie Future do monitorowania operacji asynchronicznych

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

Wszystkie funkcje i wywołania metod UMP C++, które działają asynchronicznie, zwracają Future, a także udostępniają funkcję „ostatni wynik” do pobierania Future z najnowszej operacji.

Wynik z Future możesz 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. Okresowo sprawdzaj status() funkcji Future. Gdy stan zmieni się z kFutureStatusPending na kFutureStatusCompleted, operacja zostanie zakończona.

Po zakończeniu operacji asynchronicznej sprawdź error() funkcji Future, aby uzyskać kod błędu operacji. 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.

Wywołanie zwrotne po zakończeniu

Oto przykład użycia OnCompletion do ustawienia wywołania zwrotnego po zakończeniu, 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.
    }
  });
}

Odpytywanie pętli aktualizacji

W tym przykładzie po rozpoczęciu operacji asynchronicznej podczas uruchamiania 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 Firebase C++ SDK i dokumentacji pakietu SDK GMA C++.

Przy każdym uruchomieniu aplikacji należy prosić o aktualizację informacji o zgodzie użytkownika za pomocą funkcji RequestConsentInfoUpdate(). To żądanie sprawdza te kwestie:

  • Czy wymagana jest zgoda. Na przykład zgoda jest wymagana po raz pierwszy lub poprzednia decyzja o zgodzie wygasła.
  • Czy wymagany jest punkt wejścia opcji prywatności. Niektóre wiadomości dotyczące prywatności wymagają, aby aplikacje umożliwiały użytkownikom modyfikowanie ustawień prywatności w dowolnym momencie.
#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.
    });
}

Wczytywanie i wyświetlanie formularza wiadomości dotyczącej prywatności

Po otrzymaniu najnowszych informacji o stanie zgody wywołaj funkcję LoadAndShowConsentFormIfRequired(), aby wczytać formularze wymagane do uzyskania zgody użytkownika. Po wczytaniu formularze są wyświetlane natychmiast.

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

Powyżej znajdziesz przykład sprawdzania zakończenia za pomocą odpytywania pętli aktualizacji zamiast wywołania zwrotnego po zakończeniu.

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

Opcje prywatności

Niektóre formularze wiadomości dotyczących prywatności są wyświetlane z punktu wejścia opcji prywatności renderowanego przez wydawcę, co umożliwia użytkownikom zarządzanie ustawieniami prywatności w dowolnym momencie. Aby dowiedzieć się więcej o tym, którą wiadomość widzą użytkownicy w punkcie wejścia opcji prywatności , zapoznaj się z artykułem Dostępne typy wiadomości dla użytkowników.

Wysyłanie żądań reklam z uwzględnieniem zgody użytkownika

Zanim wyślesz żądanie reklamy, sprawdź, czy masz zgodę użytkownika, używając funkcji ConsentInfo::GetInstance()‑> CanRequestAds():

Poniżej znajdziesz miejsca, w których możesz sprawdzić, czy możesz wysyłać żądania reklam podczas zbierania zgody:

  • Po tym, jak pakiet SDK UMP uzyska zgodę w bieżącej sesji.
  • Natychmiast po wywołaniu funkcji RequestConsentInfoUpdate(). Pakiet SDK UMP mógł uzyskać zgodę w poprzedniej sesji aplikacji.

Jeśli podczas procesu zbierania zgody wystąpi błąd, sprawdź, czy możesz wysyłać żądania reklam. Pakiet SDK UMP używa stanu zgody z poprzedniej sesji aplikacji.

Zapobieganie zbędnym żądaniom reklam

Gdy sprawdzasz ConsentInfo::GetInstance()‑> CanRequestAds() po zebraniu zgody i po wywołaniu RequestConsentInfoUpdate(), upewnij się, że logika zapobiega zbędnym żądaniom reklam, które mogą spowodować, że oba sprawdzenia zwrócą wartość true. Możesz na przykład użyć zmiennej logicznej.

Poniższy kompletny przykład używa odpytywania pętli aktualizacji, ale do monitorowania operacji asynchronicznych możesz też używać OnCompletion wywołań zwrotnych. Użyj techniki, która lepiej pasuje do struktury Twojego kodu.

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

Testowanie

Jeśli podczas tworzenia aplikacji chcesz przetestować integrację, wykonaj te czynności, aby programowo zarejestrować urządzenie testowe. Zanim opublikujesz aplikację, usuń kod, który ustawia te identyfikatory urządzeń testowych.

  1. Wywołaj funkcję RequestConsentInfoUpdate().
  2. Sprawdź dane wyjściowe logu pod kątem wiadomości podobnej do tej, która pokazuje identyfikator urządzenia i sposób dodania 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 ustawić ConsentRequestParameters.debug_settings.debug_device_ids na 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);
    }
    

Wymuszanie lokalizacji geograficznej

Pakiet SDK UMP umożliwia testowanie działania aplikacji tak, jakby urządzenie znajdowało się w różnych regionach, np. w Europejskim Obszarze Gospodarczym (EOG), w Wielkiej Brytanii i Szwajcarii, za pomocą funkcji 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 może się okazać przydatne zresetowanie stanu pakietu SDK, aby można było symulować pierwsze uruchomienie aplikacji przez użytkownika. Pakiet SDK udostępnia do tego metodę Reset().

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