開始使用

根據 Google 歐盟地區使用者同意聲明 政策,您必須 向歐洲經濟區境內的使用者揭露特定資訊 取得使用 Cookie 或其他本機儲存空間的同意聲明。 並根據法律要求使用個人資料 (如 AdID) 放送廣告。 本政策是配合《歐盟地區電子通訊隱私指令》和 《一般資料保護規則》(GDPR) 規定)。

為了協助發布商根據這項政策履行自身職責,Google 提供 User Messaging Platform (UMP) SDK。UMP SDK 已更新,現已支援 符合最新的 IAB 標準這些設定現在都很方便 處理 AdMob 隱私權與傳送訊息

必要條件

  • Android API 級別 21 以上 (Android 專用)

建立訊息類型

使用以下其中一則文字建立使用者訊息: 可用的使用者訊息類型 中,隱私權與訊息分頁 AdMob 。 讓他們使用服務帳戶UMP SDK 會嘗試顯示 透過應用程式 ID AdMob 建立的使用者訊息 您在專案中設定的內容如果未設定應用程式訊息,則 SDK 傳回錯誤。

詳情請參閱 關於隱私權與訊息

安裝 SDK

  1. 請按照下列步驟安裝 Google 行動廣告 (GMA) C++ SDK。UMP C++ GMA C++ SDK 已納入 SDK。

  2. 請務必設定應用程式的 AdMob 應用程式 專案中的 ID 才能繼續。

  3. 在程式碼中,呼叫 ConsentInfo::GetInstance()

    • 在 Android 上,您需要傳入 JNIEnvActivity NDK只有在首次呼叫 GetInstance() 時才需要執行這項操作。
    • 如果您已在使用 Firebase C++ SDK,呼叫 您第一次呼叫 GetInstance() 時,就在 firebase::App 中。
    #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
    

後續呼叫 ConsentInfo::GetInstance() 時,所有呼叫都會傳回同一個例項。

已使用 UMP SDK 後,只要刪除 ConsentInfo 執行個體:

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

使用 Future 監控非同步作業

A 罩杯 firebase::Future 可讓您判斷非同步方法的完成狀態 呼叫。

所有非同步作業的 UMP C++ 函式和方法呼叫,都會傳回 Future,並提供「最後一個結果」用來擷取 Future 的函式 最近的作業中

有兩種方法可以從 Future 取得結果:

  1. 呼叫 OnCompletion()。 傳入您自己的回呼函式,系統會在作業完成時呼叫該函式 完成。
  2. 定期檢查 Futurestatus()。當 狀態kFutureStatusPending 改為 kFutureStatusCompleted 作業已完成。

非同步作業完成後,您應該檢查 Futureerror(),可取得作業的錯誤 再也不是件繁重乏味的工作如果錯誤代碼為 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 說明文件

新增應用程式 ID

您可以在「 AdMob UI: 將身分證件新增至 替換為下列程式碼片段:

在每個應用程式中,應要求使用者更新同意聲明資訊 使用 RequestConsentInfoUpdate()啟動。這決定 廣告在使用者尚未提供同意聲明的情況下才需提供;或者 以及同意聲明已失效。

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

請參閱上述範例,瞭解如何使用 update 迴圈輪詢,而非完成回呼。

視需要載入並顯示同意聲明表單

收到最新的同意聲明狀態後,請致電 LoadAndShowConsentFormIfRequired()ConsentInfo 類別,載入同意聲明表單。如果 SDK 載入表單並立即顯示 可用資料 FormParentFuture 關閉表單後,系統就會 已完成。如果不需要同意聲明, Future 將立即完成

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

您需要在使用者做出選擇或關閉廣告後執行任何動作 表單,請將該邏輯放入處理 Future 的程式碼中 由 LoadAndShowConsentFormIfRequired() 傳回。

請求廣告

在應用程式中請求廣告前,請確認您已取得同意聲明 透過 ConsentInfo::GetInstance()‑>CanRequestAds()存取。這裡共有兩個 收集同意聲明時的檢查地點:

  1. 從目前的工作階段中收集到同意聲明後,
  2. 呼叫 RequestConsentInfoUpdate()後立即執行。 您可能已在上一個工作階段取得同意聲明。一段延遲時間 最佳做法,建議您不要等待回呼完成 在應用程式啟動後盡快載入廣告。

如果在收集同意聲明的過程中發生錯誤, 請求廣告UMP SDK 會使用上一個 會很有幫助

下列範例使用更新迴圈輪詢,但您也可以使用 OnCompletion 回呼來監控非同步作業。使用 找出最適合您程式碼結構的技術

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

隱私權選項

部分同意聲明表單會要求使用者隨時修改同意聲明。滿足 以下的步驟,視需要導入隱私權選項按鈕。

為了達到這個目的:

  1. 實作 UI 元素,例如應用程式設定頁面中的按鈕。 觸發隱私權選項表單
  2. 完成後 LoadAndShowConsentFormIfRequired() 請查看 getPrivacyOptionsRequirementStatus() 會決定是否要顯示 可顯示隱私權選項表單的 UI 元素。
  3. 當使用者與 UI 元素互動時, showPrivacyOptionsForm() 顯示表單,方便使用者 隨時更新自己的隱私權選項。

測試

如要在開發過程中測試應用程式內整合功能,請按照下列步驟操作: 這些步驟以程式輔助方式註冊測試裝置。請務必移除 程式碼,在發布應用程式前設定測試裝置 ID。

  1. 呼叫 RequestConsentInfoUpdate()
  2. 查看記錄輸出中是否有類似以下範例的訊息, 顯示您的裝置 ID 以及如何將其新增為測試裝置:

    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. 將測試裝置 ID 複製到剪貼簿。

  4. 修改程式碼以 設定 ConsentRequestParameters.debug_settings.debug_device_ids 來電 測試裝置 ID 清單。

    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 可讓您測試應用程式行為,就像測試裝置 地址在歐洲經濟區或英國境內,並使用 ConsentRequestParameters.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();

GitHub 上的範例