Bắt đầu

SDK Nền tảng thông báo cho người dùng (UMP) của Google là một công cụ về quyền riêng tư và thông báo 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ề công cụ 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 (đối với 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ị một 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

  1. Làm theo các bước để cài đặt Firebase C++ SDK. UMP C++ SDK có trong Firebase C++ SDK.

  2. Đảm bảo rằng bạn định cấu hình mã nhận dạng ứng dụng AdMob của ứng dụng trong dự án trước khi tiếp tục.

  3. Trong mã của bạn, hãy khởi chạy UMP SDK bằng cách gọi ConsentInfo::GetInstance().

    • Trên Android, bạn cần truyền JNIEnvActivity do NDK cung cấp. Bạn chỉ cần thực hiện việc này vào lần đầu tiên gọi GetInstance().
    • Ngoài ra, nếu đã sử dụng Firebase C++ SDK trong ứng dụng, bạn có thể truyền firebase::App vào lần đầu tiên gọi 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
    

Các lệnh gọi tiếp theo đến ConsentInfo::GetInstance() đều trả về cùng một thực thể.

Nếu đã dùng xong UMP SDK, bạn có thể tắt SDK này 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 thành của các lệnh gọi phương thức không đồng bộ.

Tất cả các hàm và lệnh gọi phương thức UMP C++ hoạt động không đồng bộ đều trả về một Future, đồng thời cung cấp một hàm "kết quả gần đây nhất" để truy xuất Future từ thao tác gần đây nhất.

Có hai cách để nhận kết quả từ một Future:

  1. Gọi OnCompletion(), truyền vào hàm gọi lại của riêng bạn. Hàm này sẽ được gọi khi thao tác hoàn tất.
  2. Định kỳ kiểm tra status() của Future. Khi trạng thái thay đổi từ kFutureStatusPending thành kFutureStatusCompleted, tức là 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 Future của error() để lấy mã lỗi của thao tác. Nếu mã lỗi là 0 (kConsentRequestSuccess hoặc kConsentFormSuccess), thì 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 hoàn tất. Lệnh gọi lại này sẽ đượ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.
    }
  });
}

Thăm dò vòng lặp cập nhật

Trong ví dụ này, sau khi một thao tác không đồng bộ 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ề Firebase C++ SDKtài liệu về GMA C++ SDK.

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 điều sau:

  • Có cần có sự đồng ý hay không. Ví dụ: người dùng cần đồng ý lần đầu tiên hoặc quyết định đồng ý trước đó đã hết hạn.
  • 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ư của họ bất cứ lúc nào.
#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.
    });
}

Tải và trình bày biểu mẫu thông báo về quyền riêng tư

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

Hãy xem phía trên để biết ví dụ về cách kiểm tra xem quá trình có hoàn tất hay không bằng cách sử dụng tính năng 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 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ề.

Các lựa 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 các 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ề những loại thông báo mà người dùng của bạn nhìn thấy tại điểm truy cập lựa chọn về quyền riêng tư, hãy xem 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ần kiểm tra xem bạn có thể yêu cầu quảng cáo trong khi thu thập sự đồng ý hay không:

  • Sau khi UMP SDK thu thập sự đồng ý trong phiên hiện tại.
  • Ngay sau khi bạn gọi RequestConsentInfoUpdate(). UMP SDK có thể đã nhận được 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. UMP SDK sử dụng trạng thái đồng ý từ phiên ứng dụng trước đó.

Ví dụ hoàn chỉnh 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/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;
      }
    }
  }
}

Thử nghiệm

Nếu bạn muốn kiểm thử hoạt độ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.

  1. Gọi cho RequestConsentInfoUpdate().
  2. 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 này cho 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]
    
  3. Sao chép mã thiết bị thử nghiệm vào khay nhớ tạm.

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

Chỉ định một vị trí địa lý

UMP SDK giúp bạn thử nghiệm hành vi 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);
}

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