Memulai

Berdasarkan Kebijakan Izin Pengguna Uni Eropa Google, Anda harus membuat pengungkapan tertentu untuk pengguna di Wilayah Ekonomi Eropa (EEA) bersama dengan Inggris Raya dan mendapatkan izin mereka untuk menggunakan cookie atau penyimpanan lokal lainnya, jika diwajibkan secara hukum, dan untuk menggunakan data pribadi (seperti ID iklan) untuk menayangkan iklan. Kebijakan ini mencerminkan persyaratan dalam ePrivacy Directive dan General Data Protection Regulation (GDPR) Uni Eropa.

Untuk mendukung penayang dalam memenuhi kewajibannya berdasarkan kebijakan ini, Google menawarkan User Messaging Platform (UMP) SDK. UMP SDK telah diperbarui untuk mendukung standar IAB terbaru. Semua konfigurasi ini kini dapat ditangani dengan mudah di AdMob privasi & pesan.

Prasyarat

  • API Android level 21 atau yang lebih tinggi (untuk Android)

Membuat jenis pesan

Buat pesan pengguna dengan salah satu jenis pesan pengguna yang tersedia di tab Privasi & pesan di akun AdMob Anda. UMP SDK mencoba menampilkan pesan pengguna yang dibuat dari AdMob ID Aplikasi yang ditetapkan dalam project Anda. Jika tidak ada pesan yang dikonfigurasi untuk aplikasi Anda, SDK akan menampilkan error.

Untuk mengetahui detail selengkapnya, lihat Tentang privasi dan pesan.

Menginstal SDK

  1. Ikuti langkah-langkah untuk menginstal Google Mobile Ads (GMA) C++ SDK. UMP C++ SDK disertakan dalam GMA C++ SDK.

  2. Pastikan untuk mengonfigurasi ID aplikasi AdMob aplikasi Anda di project sebelum melanjutkan.

  3. Dalam kode Anda, inisialisasi UMP SDK dengan memanggil ConsentInfo::GetInstance().

    • Di Android, Anda harus meneruskan JNIEnv dan Activity yang disediakan oleh NDK. Anda hanya perlu melakukannya saat pertama kali memanggil GetInstance().
    • Atau, jika sudah menggunakan Firebase C++ SDK di aplikasi, Anda dapat meneruskan firebase::App saat pertama kali memanggil 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
    

Semua panggilan berikutnya ke ConsentInfo::GetInstance() akan menampilkan instance yang sama.

Jika sudah selesai menggunakan UMP SDK, Anda dapat menonaktifkan SDK dengan menghapus instance ConsentInfo:

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

Menggunakan Future untuk memantau operasi asinkron

firebase::Future menyediakan cara untuk menentukan status penyelesaian panggilan metode asinkron.

Semua fungsi dan panggilan metode UMP C++ yang beroperasi secara asinkron akan menampilkan Future, dan juga menyediakan fungsi "hasil terakhir" untuk mengambil Future dari operasi terbaru.

Ada dua cara untuk mendapatkan hasil dari Future:

  1. Panggil OnCompletion(), dengan meneruskan fungsi callback Anda sendiri, yang dipanggil saat operasi selesai.
  2. Periksa status() Future secara berkala. Jika status berubah dari kFutureStatusPending menjadi kFutureStatusCompleted, operasi telah selesai.

Setelah operasi asinkron selesai, Anda harus memeriksa error() Future untuk mendapatkan kode error operasi. Jika kode error adalah 0 (kConsentRequestSuccess atau kConsentFormSuccess), operasi berhasil diselesaikan; jika tidak, periksa kode error dan error_message() untuk menentukan apa yang salah.

Callback penyelesaian

Berikut adalah contoh cara menggunakan OnCompletion untuk menetapkan callback penyelesaian, yang dipanggil saat operasi asinkron selesai.

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

Memperbarui polling loop

Dalam contoh ini, setelah operasi asinkron dimulai saat peluncuran aplikasi, hasilnya diperiksa di tempat lain, dalam fungsi loop update game (yang berjalan sekali per frame).

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

Untuk mengetahui informasi selengkapnya tentang firebase::Future, lihat dokumentasi Firebase C++ SDK dan dokumentasi GMA C++ SDK.

Anda harus meminta pembaruan informasi izin pengguna setiap kali aplikasi diluncurkan, menggunakan RequestConsentInfoUpdate(). Langkah ini menentukan apakah pengguna Anda perlu memberikan izin jika mereka belum melakukannya, atau apakah izin mereka sudah tidak berlaku.

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

Lihat di atas untuk contoh memeriksa penyelesaian menggunakan polling loop update, bukan callback penyelesaian.

Muat dan tampilkan formulir izin jika diperlukan

Setelah Anda menerima status izin terbaru, panggilLoadAndShowConsentFormIfRequired() di classConsentInfo untuk memuat formulir izin. Jika status izin diwajibkan, SDK akan memuat formulir dan segera menampilkannya dari FormParentyang disediakan. Formulir Future diselesaikan setelah formulir ditutup. Jika izin tidak diperlukan, Future diselesaikan .

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

Jika Anda perlu melakukan tindakan apa pun setelah pengguna menentukan pilihan atau menutup formulir, tempatkan logika tersebut dalam kode yang menangani Future yang ditampilkan oleh LoadAndShowConsentFormIfRequired().

Permintaan iklan

Sebelum meminta iklan di aplikasi, periksa apakah Anda telah mendapatkan izin dari pengguna menggunakan ConsentInfo::GetInstance()‑>CanRequestAds(). Ada dua tempat yang harus diperiksa saat mengumpulkan izin:

  1. Setelah izin dikumpulkan di sesi saat ini.
  2. Segera setelah Anda menelepon RequestConsentInfoUpdate(). Kemungkinan izin telah diperoleh di sesi sebelumnya. Sebagai praktik terbaik latensi, sebaiknya jangan menunggu callback selesai sehingga Anda dapat mulai memuat iklan sesegera mungkin setelah aplikasi diluncurkan.

Jika terjadi error selama proses pengumpulan izin, sebaiknya Anda tetap mencoba meminta iklan. UMP SDK menggunakan status izin dari sesi sebelumnya.

Contoh lengkap berikut menggunakan polling loop update, tetapi Anda juga dapat menggunakan callback OnCompletion untuk memantau operasi asinkron. Gunakan teknik mana pun yang lebih cocok dengan struktur kode Anda.

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

Opsi privasi

Beberapa formulir izin mewajibkan pengguna untuk mengubah izinnya kapan saja. Patuhi langkah-langkah berikut untuk menerapkan tombol opsi privasi jika diperlukan.

Untuk melakukan hal ini:

  1. Implementasikan elemen UI, seperti tombol di halaman setelan aplikasi, yang dapat memicu formulir opsi privasi.
  2. Setelah LoadAndShowConsentFormIfRequired() selesai, periksa getPrivacyOptionsRequirementStatus() untuk menentukan apakah akan menampilkan elemen UI yang dapat menampilkan formulir opsi privasi.
  3. Saat pengguna berinteraksi dengan elemen UI, panggil showPrivacyOptionsForm() untuk menampilkan formulir tersebut sehingga pengguna dapat memperbarui opsi privasi kapan saja.

Pengujian

Jika Anda ingin menguji integrasi di aplikasi saat mengembangkan, ikuti langkah-langkah berikut untuk mendaftarkan perangkat pengujian secara terprogram. Pastikan Anda menghapus kode yang menetapkan ID perangkat pengujian ini sebelum merilis aplikasi.

  1. Panggil RequestConsentInfoUpdate().
  2. Periksa output log untuk melihat pesan yang mirip dengan contoh berikut, yang menampilkan ID perangkat Anda dan cara menambahkannya sebagai perangkat pengujian:

    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. Salin ID perangkat pengujian Anda ke papan klip.

  4. Ubah kode Anda untuk menetapkan ConsentRequestParameters.debug_settings.debug_device_ids untuk daftar ID perangkat pengujian Anda.

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

Paksa geografi

UMP SDK menyediakan cara untuk menguji perilaku aplikasi Anda seolah-olah perangkat tersebut berada di EEA atau Inggris Raya menggunakan ConsentRequestParameters.debug_settings.debug_geography. Perhatikan bahwa setelan debug hanya berfungsi pada perangkat pengujian.

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

Dalam menguji aplikasi dengan UMP SDK, mereset status SDK mungkin dapat membantu Anda menyimulasikan pengalaman penginstalan pertama pengguna. SDK menyediakan metode Reset() untuk melakukannya.

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