שנתחיל?

בכפוף להסכמת משתמשים של Google באיחוד האירופי מדיניות, עליך להציג הודעות גילוי נאות מסוימות למשתמשים באזור הכלכלי האירופי (EEA) בנוסף עם בריטניה ולקבל את הסכמתם לשימוש בקובצי Cookie או באמצעים אחרים לאחסון מקומי, במקומות שבהם הדבר נדרש על פי חוק, וכן להשתמש במידע אישי (כגון מזהה פרסום) לצורך הצגת מודעות. המדיניות הזו משקפת את הדרישות שמפורטות ב-ePrivacy Directive (ההנחיה בנושא פרטיות ותקשורת אלקטרונית) של האיחוד האירופי General Data Protection Regulation (התקנות הכלליות להגנה על מידע, GDPR).

כדי לעזור לבעלי תוכן דיגיטלי למלא את החובות שלהם במסגרת המדיניות הזו, Google מציעה User Messaging Platform (UMP) SDK. UMP SDK עודכן כדי לתמוך בהתאם לתקנים העדכניים ביותר של IAB. כל ההגדרות האישיות האלה יכולות עכשיו מטופל AdMob בפרטיות העברת הודעות.

דרישות מוקדמות

  • Android API ברמה 21 ואילך (ל-Android)

איך יוצרים את סוג ההודעה

ליצור הודעות למשתמשים באמצעות אחד הסוגים הזמינים של הודעות למשתמשים בקטע פרטיות העברת הודעות AdMob חשבון. UMP SDK מנסה להציג הודעת המשתמש נוצרה מ- AdMob מזהה האפליקציה שמוגדרים בפרויקט. אם לא הוגדרה הודעה לאפליקציה, ה-SDK מחזירה שגיאה.

פרטים נוספים זמינים במאמר מידע על הכלי 'פרטיות והודעות'.

התקנת ה-SDK

  1. פועלים לפי השלבים להתקנת Google Mobile Ads (GMA) C++ SDK. UMP C++ SDK כלול ב-GMA C++ SDK.

  2. חשוב להגדיר את אפליקציית AdMob של האפליקציה ID בפרויקט לפני שממשיכים.

  3. בקוד שלך, מאתחלים את 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
    

הקריאות הבאות שיבוצעו אל 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 מהפעולה האחרונה.

יש שתי דרכים לקבל תוצאה מ-Future:

  1. קוראים לפונקציה OnCompletion(), להעביר פונקציית קריאה חוזרת (callback), שנקראת כאשר הפעולה שהושלמו.
  2. כדאי לבדוק מדי פעם את 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.
    }
  });
}

עדכון סקרים לולאה

בדוגמה הזו, אחרי שפעולה אסינכרונית התחילה בהשקת האפליקציה, התוצאות נבדקות במקום אחר, בפונקציית לולאת העדכון של המשחק (שרצה פעם אחת בכל מסגרת).

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.

מוסיפים את מזהה האפליקציה

ניתן למצוא את מזהה האפליקציה בקטע ממשק המשתמש של 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 הושלמה באופן מיידי.

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 קריאות חוזרות (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;
      }
    }
  }
}

אפשרויות פרטיות

חלק מטופסי ההסכמה מחייבים את המשתמשים לשנות את ההסכמה שלהם בכל שלב. לפעול בהתאם לבצע את השלבים הבאים כדי להטמיע לחצן של אפשרויות פרטיות, אם יש צורך.

לשם כך:

  1. מטמיעים רכיב בממשק המשתמש, כמו לחצן בדף ההגדרות של האפליקציה, שיכול להפעיל טופס של אפשרויות פרטיות.
  2. אחרי LoadAndShowConsentFormIfRequired() שמסיימים, בודקים getPrivacyOptionsRequirementStatus() כדי לקבוע אם להציג רכיב ממשק המשתמש שיכול להציג את הטופס של אפשרויות הפרטיות.
  3. כשמשתמש יוצר אינטראקציה עם רכיב בממשק המשתמש שלך, מתבצעת קריאה showPrivacyOptionsForm() כדי להציג את הטופס כך שהמשתמש יוכל לעדכן את אפשרויות הפרטיות שלהם בכל שלב.

בדיקה

כדי לבדוק את השילוב באפליקציה במהלך הפיתוח, צריך לפעול לפי השלבים הבאים: כדי לרשום את מכשיר הבדיקה באופן פרוגרמטי. חשוב להסיר את שמגדיר את מזהי מכשירי הבדיקה האלה לפני השקת האפליקציה.

  1. התקשרות אל RequestConsentInfoUpdate().
  2. בודקים את פלט היומן להודעה שדומה לדוגמה הבאה: מציג את מזהה המכשיר ואיך להוסיף אותו כמכשיר בדיקה:

    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. מעתיקים את מזהה מכשיר הבדיקה ללוח.

  4. יש לשנות את הקוד כדי להגדיר 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();

דוגמאות ב-GitHub