SDK Nền tảng thông báo cho người dùng (UMP) của Google là một công cụ thông báo và quyền riêng tư giúp bạn quản lý các lựa chọn về quyền riêng tư. Để biết thêm thông tin, hãy xem bài viết Giới thiệu về Quyền riêng tư và thông báo.
Điều kiện tiên quyết
- API Android cấp 21 trở lên (dành cho Android)
Tạo loại thông báo
Tạo thông báo cho người dùng bằng một trong các Loại thông báo cho người dùng hiện có trong thẻ Quyền riêng tư và thông báo của tài khoản AdMob. SDK UMP cố gắng hiển thị thông báo về quyền riêng tư được tạo từ mã ứng dụng AdMob được đặt trong dự án của bạn.
Để biết thêm thông tin, hãy xem bài viết Giới thiệu về quyền riêng tư và thông báo.
Cài đặt SDK
Làm theo các bước để cài đặt SDK C++ cho Google Mobile Ads (GMA). SDK UMP C++ nằm trong SDK GMA C++.
Hãy nhớ định cấu hình mã ứng dụng AdMob của ứng dụng trong dự án trước khi tiếp tục.
Trong mã, hãy khởi chạy SDK UMP bằng cách gọi
ConsentInfo::GetInstance()
.- Trên Android, bạn cần truyền vào
JNIEnv
vàActivity
do NDK cung cấp. Bạn chỉ cần thực hiện việc này trong lần đầu tiên gọiGetInstance()
. - Ngoài ra, nếu đang sử dụng SDK Firebase C++ trong ứng dụng, bạn có thể truyền vào
firebase::App
trong lần đầu tiên gọiGetInstance()
.
#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
- Trên Android, bạn cần truyền vào
Các lệnh gọi tiếp theo đến ConsentInfo::GetInstance()
đều trả về cùng một thực thể.
Nếu đã sử dụng xong SDK UMP, bạn có thể tắt SDK bằng cách xoá thực thể ConsentInfo
:
void ShutdownUserMessagingPlatform() {
ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance();
delete consent_info;
}
Sử dụng Future
để theo dõi các thao tác không đồng bộ
firebase::Future
cung cấp cho bạn một cách để xác định trạng thái hoàn tất của các lệnh gọi phương thức không đồng bộ.
Tất cả các hàm C++ và lệnh gọi phương thức UMP hoạt động không đồng bộ đều trả về một Future
, đồng thời cung cấp hàm "kết quả cuối cùng" để truy xuất Future
từ thao tác gần đây nhất.
Có hai cách để lấy kết quả từ Future
:
- Gọi
OnCompletion()
, truyền vào hàm gọi lại của riêng bạn. Hàm này được gọi khi thao tác hoàn tất. - Định kỳ kiểm tra
status()
củaFuture
. Khi trạng thái thay đổi từkFutureStatusPending
thànhkFutureStatusCompleted
, thao tác đã hoàn tất.
Sau khi hoàn tất thao tác không đồng bộ, bạn nên kiểm tra error()
của Future
để lấy mã lỗi của thao tác. Nếu mã lỗi là 0
(kConsentRequestSuccess
hoặc kConsentFormSuccess
), thao tác đã hoàn tất thành công; nếu không, hãy kiểm tra mã lỗi và error_message()
để xác định vấn đề.
Lệnh gọi lại khi hoàn tất
Dưới đây là ví dụ về cách sử dụng OnCompletion
để đặt lệnh gọi lại khi hoàn tất. Lệnh gọi lại này được gọi khi thao tác không đồng bộ hoàn tất.
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.
}
});
}
Cập nhật vòng lặp thăm dò
Trong ví dụ này, sau khi một thao tác không đồng bộ được bắt đầu khi khởi chạy ứng dụng, kết quả sẽ được kiểm tra ở nơi khác, trong hàm vòng lặp cập nhật của trò chơi (chạy một lần cho mỗi khung hình).
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.
}
}
}
}
Để biết thêm thông tin về firebase::Future
, hãy xem tài liệu về SDK C++ của Firebase và tài liệu về SDK C++ của GMA.
Lấy thông tin về sự đồng ý của người dùng
Bạn nên yêu cầu cập nhật thông tin về trạng thái đồng ý của người dùng mỗi lần chạy ứng dụng bằng cách sử dụng
RequestConsentInfoUpdate()
. Yêu cầu này kiểm tra những thông tin sau:
- Liệu có bắt buộc phải có sự đồng ý hay không. Ví dụ: cần có sự đồng ý lần đầu tiên hoặc quyết định đồng ý trước đó đã hết hạn.
- Liệu có bắt buộc phải có điểm truy cập các lựa chọn về quyền riêng tư hay không. Một số thông báo về quyền riêng tư yêu cầu ứng dụng cho phép người dùng sửa đổi các lựa chọn về quyền riêng tư bất cứ lúc nào.
#include "firebase/gma/ump.h"
namespace ump = ::firebase::gma::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.
});
}
Tải và hiển thị biểu mẫu thông báo về quyền riêng tư
Sau khi bạn nhận được trạng thái đồng ý mới nhất, hãy gọi
LoadAndShowConsentFormIfRequired()
để tải mọi biểu mẫu cần thiết để thu thập sự đồng ý của người dùng. Sau khi tải, các biểu mẫu sẽ xuất hiện ngay lập tức.
#include "firebase/gma/ump.h"
namespace ump = ::firebase::gma::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.
}
});
}
});
}
Hãy xem phần trên để biết ví dụ về cách kiểm tra trạng thái hoàn tất bằng cách thăm dò vòng lặp cập nhật thay vì lệnh gọi lại hoàn tất.
Nếu bạn cần thực hiện bất kỳ hành động nào sau khi người dùng đã đưa ra sự lựa chọn hoặc đóng biểu mẫu, hãy đặt logic đó vào mã xử lý Future
do LoadAndShowConsentFormIfRequired()
trả về.
Tuỳ chọn về quyền riêng tư
Một số biểu mẫu thông báo về quyền riêng tư được trình bày từ điểm truy cập lựa chọn về quyền riêng tư do nhà xuất bản hiển thị, cho phép người dùng quản lý các lựa chọn về quyền riêng tư của họ bất cứ lúc nào. Để tìm hiểu thêm về thông báo mà người dùng nhìn thấy tại điểm truy cập vào các tuỳ chọn về quyền riêng tư, hãy xem nội dung Các loại thông báo hiện có cho người dùng.
Yêu cầu quảng cáo có sự đồng ý của người dùng
Trước khi yêu cầu quảng cáo, hãy sử dụng
ConsentInfo::GetInstance()‑>
CanRequestAds()
để kiểm tra xem bạn đã nhận được sự đồng ý của người dùng hay chưa:
Sau đây là những nơi bạn có thể kiểm tra xem mình có thể yêu cầu quảng cáo trong khi thu thập sự đồng ý hay không:
- Sau khi SDK UMP thu thập sự đồng ý trong phiên hiện tại.
- Ngay sau khi bạn gọi
RequestConsentInfoUpdate()
. SDK UMP có thể đã thu thập sự đồng ý trong phiên ứng dụng trước.
Nếu xảy ra lỗi trong quá trình thu thập sự đồng ý, hãy kiểm tra xem bạn có thể yêu cầu quảng cáo hay không. SDK UMP sử dụng trạng thái đồng ý từ phiên ứng dụng trước đó.
Ví dụ đầy đủ sau đây sử dụng tính năng thăm dò vòng lặp cập nhật, nhưng bạn cũng có thể sử dụng lệnh gọi lại OnCompletion
để theo dõi các thao tác không đồng bộ. Sử dụng kỹ thuật phù hợp hơn với cấu trúc mã của bạn.
#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 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;
}
}
}
}
Thử nghiệm
Nếu bạn muốn thử nghiệm tính năng tích hợp trong ứng dụng khi đang phát triển, hãy làm theo các bước sau để đăng ký thiết bị thử nghiệm theo phương thức lập trình. Hãy nhớ xoá mã dùng để đặt các mã thiết bị thử nghiệm này trước khi bạn phát hành ứng dụng.
- Gọi cho
RequestConsentInfoUpdate()
. Kiểm tra đầu ra nhật ký để tìm thông báo tương tự như ví dụ sau. Thông báo đó sẽ cho bạn biết mã thiết bị của bạn và cách thêm thiết bị đó làm thiết bị thử nghiệm:
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]
Sao chép mã thiết bị thử nghiệm vào bảng nhớ tạm.
Sửa đổi mã của bạn để đặt
ConsentRequestParameters.debug_settings.debug_device_ids
thành danh sách mã thiết bị thử nghiệm.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); }
Buộc một vị trí địa lý
SDK UMP giúp bạn thử nghiệm hoạt động của ứng dụng như thể thiết bị được dùng ở nhiều khu vực, chẳng hạn như Khu vực kinh tế Châu Âu (EEA) hoặc Vương quốc Anh, bằng cách sử dụng debug_settings.debug_geography
. Xin lưu ý rằng chế độ cài đặt gỡ lỗi chỉ hoạt động trên thiết bị thử nghiệm.
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);
}
Đặt lại trạng thái đồng ý
Khi thử nghiệm ứng dụng bằng SDK UMP, bạn nên đặt lại trạng thái của SDK để có thể mô phỏng trải nghiệm cài đặt lần đầu của người dùng.
SDK cung cấp phương thức Reset()
để làm việc này.
ConsentInfo::GetInstance()->Reset();