ภายใต้ความยินยอมของผู้ใช้ EU ของ Google คุณต้อง เปิดเผยข้อมูลบางอย่างแก่ผู้ใช้ในเขตเศรษฐกิจยุโรป (EEA) กับสหราชอาณาจักร และได้รับความยินยอมในการใช้คุกกี้หรือพื้นที่เก็บข้อมูลอื่นๆ ในเครื่อง ในกรณีที่กฎหมายกำหนด และใช้ข้อมูลส่วนตัว (เช่น AdID) ในการแสดงโฆษณา นโยบายนี้เป็นผลมาจากข้อกำหนดด้าน ePrivacy ของสหภาพยุโรปและ กฎระเบียบให้ความคุ้มครองข้อมูลส่วนบุคคลของผู้บริโภค (GDPR)
เพื่อสนับสนุนผู้เผยแพร่โฆษณาให้ปฏิบัติตามหน้าที่ของตนภายใต้นโยบายนี้ Google ได้นำเสนอ SDK สำหรับ User Messaging Platform (UMP) UMP SDK ได้รับการอัปเดตให้รองรับ มาตรฐานล่าสุดของ IAB การกำหนดค่าทั้งหมดนี้สามารถ จัดการใน AdMob ความเป็นส่วนตัวและ การรับส่งข้อความ
ข้อกำหนดเบื้องต้น
- ทำตามคู่มือเริ่มต้นใช้งานจนจบ
- API ของ Android ระดับ 21 ขึ้นไป (สำหรับ Android)
- หากคุณกำลังปฏิบัติตามข้อกำหนดที่เกี่ยวข้องกับ GDPR โปรดอ่าน ข้อกำหนดของ IAB ส่งผลต่อสหภาพยุโรปอย่างไร ข้อความขอความยินยอม
สร้างประเภทข้อความ
สร้างข้อความสำหรับผู้ใช้ด้วย ประเภทข้อความสำหรับผู้ใช้ที่ใช้ได้ ภายใต้ความเป็นส่วนตัวและ แท็บการรับส่งข้อความ AdMob ของคุณได้ UMP SDK พยายามแสดง ข้อความสำหรับผู้ใช้ที่สร้างจาก AdMob รหัสแอปพลิเคชัน ที่ตั้งไว้ในโปรเจ็กต์ หากไม่มีการกำหนดค่าข้อความสำหรับแอปพลิเคชันของคุณ SDK แสดงผลข้อผิดพลาด
ดูรายละเอียดเพิ่มเติมได้ที่ เกี่ยวกับความเป็นส่วนตัวและการรับส่งข้อความ
ติดตั้ง SDK
ทำตามขั้นตอนเพื่อติดตั้ง Google Mobile Ads (GMA) C++ SDK UMP C++ SDK รวมอยู่ใน GMA C++ SDK
ตรวจสอบว่าคุณกำหนดค่าแอป AdMob ของแอปแล้ว รหัสในโปรเจ็กต์ ก่อนดำเนินการต่อ
ในโค้ด ให้เริ่มต้น UMP SDK โดยการเรียกใช้
ConsentInfo::GetInstance()
- บน Android คุณจะต้องส่ง
JNIEnv
และActivity
ซึ่งจัดเตรียมไว้โดย NDK คุณต้องดำเนินการนี้ในครั้งแรกที่โทรหาGetInstance()
เท่านั้น - หรือหากคุณใช้ Firebase C++ อยู่แล้ว
SDK ในแอปของคุณ คุณสามารถส่ง
ใน
firebase::App
ครั้งแรกที่คุณโทรหา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
- บน Android คุณจะต้องส่ง
การเรียก ConsentInfo::GetInstance()
ครั้งต่อๆ ไปทั้งหมดจะแสดงผลอินสแตนซ์เดียวกัน
หากใช้ UMP SDK เสร็จแล้ว คุณสามารถปิด SDK ดังกล่าวได้โดยลบ
อินสแตนซ์ ConsentInfo
รายการ:
void ShutdownUserMessagingPlatform() {
ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance();
delete consent_info;
}
ใช้ Future
เพื่อตรวจสอบการดำเนินการที่ไม่พร้อมกัน
ต
firebase::Future
แสดงวิธีการพิจารณาสถานะเสร็จสมบูรณ์ของเมธอดอะซิงโครนัส
ฟังก์ชัน UMP C++ และการเรียกเมธอดทั้งหมดที่ดำเนินการแบบไม่พร้อมกันจะแสดงผล
Future
และระบุ "ผลลัพธ์ล่าสุด" ด้วย เพื่อเรียกข้อมูล Future
จากการดำเนินการล่าสุด
มี 2 วิธีในการรับผลลัพธ์จาก Future
ได้แก่
- โทร
OnCompletion()
ในฟังก์ชัน Callback ของคุณเอง ซึ่งจะเรียกใช้เมื่อการดำเนินการ เสร็จสมบูรณ์ - ตรวจสอบ
status()
ของFuture
เป็นระยะ เมื่อ สถานะ เปลี่ยนจากkFutureStatusPending
เป็นkFutureStatusCompleted
การดำเนินการเสร็จสมบูรณ์แล้ว
หลังจากการทำงานแบบอะซิงโครนัสเสร็จสิ้น คุณควรตรวจสอบ
error()
ของ Future
เพื่อรับข้อผิดพลาดของการดำเนินการ
โค้ด หากรหัสข้อผิดพลาดคือ 0
(kConsentRequestSuccess
หรือ kConsentFormSuccess
)
การดำเนินการเสร็จสมบูรณ์ ไม่เช่นนั้น ให้ตรวจสอบรหัสข้อผิดพลาดและ
error_message()
เพื่อตรวจสอบว่าเกิดข้อผิดพลาดใด
การติดต่อกลับเพื่อเสร็จสิ้น
ต่อไปนี้คือตัวอย่างวิธีใช้ OnCompletion
เพื่อตั้งค่า Callback ที่เสร็จสมบูรณ์
ซึ่งจะถูกเรียกเมื่อการทำงานแบบอะซิงโครนัสเสร็จสิ้น
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.
}
});
}
อัปเดตการสำรวจแบบวนซ้ำ
ในตัวอย่างนี้ หลังจากที่การดำเนินการแบบไม่พร้อมกันเริ่มต้นเมื่อเปิดแอป ที่อื่น ในฟังก์ชันการวนการอัปเดตของเกม (ซึ่งเรียกใช้ 1 ครั้งต่อเฟรม)
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
โปรดดูที่ SDK ของ Firebase C++
เอกสารประกอบ
และเอกสารประกอบเกี่ยวกับ SDK ของ GMA C++
เพิ่มรหัสแอปพลิเคชัน
คุณดูรหัสแอปพลิเคชันได้ใน UI ของ AdMob เพิ่มบัตรประจำตัวลงใน ด้วยข้อมูลโค้ดต่อไปนี้
คำขอข้อมูลความยินยอม
คุณควรขออัปเดตข้อมูลความยินยอมของผู้ใช้ในทุกแอป
เปิดโดยใช้ 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.
}
});
}
โปรดดูตัวอย่างการตรวจสอบการทำงานเสร็จสมบูรณ์โดยใช้ด้านบน อัปเดตการสำรวจแบบวนซ้ำ แทนที่จะเป็น Callback ที่เสร็จสมบูรณ์
โหลดและแสดงแบบฟอร์มความยินยอมหากจำเป็น
หลังจากได้รับสถานะความยินยอมล่าสุดแล้ว โปรดโทร
LoadAndShowConsentFormIfRequired()
ใน
ConsentInfo
เพื่อโหลดแบบฟอร์มความยินยอม หาก
ต้องระบุสถานะความยินยอม SDK จะโหลดแบบฟอร์มและแสดงทันที
จาก FormParent
ที่ระบุ Future
ระบบจะเรียกว่าเสร็จสิ้น หลังจากส่งแบบฟอร์มแล้ว หากไม่จำเป็นต้องได้รับความยินยอม Future
ระบบจะเรียกใช้เสร็จสิ้น ทันที
Activity
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()
มี 2 แบบ
สิ่งที่ต้องตรวจสอบขณะรวบรวมความยินยอม:
- เมื่อรวบรวมความยินยอมในเซสชันปัจจุบันแล้ว
- ทันทีที่คุณโทรหา
RequestConsentInfoUpdate()
เป็นไปได้ว่าอาจได้รับความยินยอมแล้วในเซสชันก่อนหน้านี้ แบบเวลาในการตอบสนอง แนวทางปฏิบัติแนะนำคืออย่ารอให้การติดต่อกลับเสร็จสิ้นเพื่อให้คุณสามารถ ให้เริ่มโหลดโฆษณาโดยเร็วที่สุดเท่าที่จะเป็นไปได้หลังจากที่คุณเปิดตัวแอป
หากเกิดข้อผิดพลาดขึ้นในระหว่างกระบวนการรวบรวมความยินยอม คุณควร ในการขอโฆษณา UMP SDK ใช้สถานะความยินยอมจาก เซสชัน
ตัวอย่างที่สมบูรณ์ต่อไปนี้ใช้การสำรวจแบบวนซ้ำสำหรับอัปเดต แต่คุณสามารถใช้
OnCompletion
Callback เพื่อตรวจสอบการดำเนินการแบบไม่พร้อมกัน ใช้
ไม่ว่าเทคนิคใดจะเหมาะกับโครงสร้างโค้ดของคุณมากกว่า
#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;
}
}
}
}
ตัวเลือกความเป็นส่วนตัว
แบบฟอร์มความยินยอมบางแบบฟอร์มกำหนดให้ผู้ใช้แก้ไขความยินยอมได้ทุกเมื่อ ปฏิบัติตาม ตามขั้นตอนต่อไปนี้เพื่อใช้ปุ่มตัวเลือกความเป็นส่วนตัว หากจำเป็น
ทั้งสองสามารถทำได้โดยดำเนินการดังนี้
- ใช้องค์ประกอบ UI เช่น ปุ่มในหน้าการตั้งค่าของแอป ที่สามารถเรียกใช้แบบฟอร์มตัวเลือกความเป็นส่วนตัว
- เมื่อทำเสร็จแล้ว
LoadAndShowConsentFormIfRequired()
ให้ตรวจสอบgetPrivacyOptionsRequirementStatus()
เพื่อพิจารณาว่าจะแสดง องค์ประกอบ UI ที่แสดงแบบฟอร์มตัวเลือกความเป็นส่วนตัวได้ - เมื่อผู้ใช้โต้ตอบกับองค์ประกอบ UI ของคุณ ให้เรียกใช้
showPrivacyOptionsForm()
เพื่อแสดงแบบฟอร์มเพื่อให้ผู้ใช้ อัปเดตตัวเลือกความเป็นส่วนตัวได้ทุกเมื่อ
การทดสอบ
หากต้องการทดสอบการผสานรวมในแอประหว่างการพัฒนา ให้ทำตาม ขั้นตอนเหล่านี้เพื่อลงทะเบียนอุปกรณ์ทดสอบแบบเป็นโปรแกรม อย่าลืมนำ ที่ตั้งค่ารหัสอุปกรณ์ทดสอบเหล่านี้ก่อนที่คุณจะเผยแพร่แอป
- โทร
RequestConsentInfoUpdate()
ตรวจสอบเอาต์พุตของบันทึกสำหรับข้อความที่คล้ายกับตัวอย่างต่อไปนี้ ซึ่ง แสดงรหัสอุปกรณ์และวิธีเพิ่มรหัสเป็นอุปกรณ์ทดสอบ
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]
คัดลอกรหัสอุปกรณ์ทดสอบไปยังคลิปบอร์ด
แก้ไขโค้ด เป็นการตั้งค่า
ConsentRequestParameters.debug_settings.debug_device_ids
เพื่อ รายการรหัสอุปกรณ์ทดสอบ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 ให้คุณทดสอบลักษณะการทำงานของแอปได้เสมือนว่าอุปกรณ์
ที่อยู่ใน EEA หรือสหราชอาณาจักรโดยใช้ 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();