شروع به کار

کیت توسعه نرم‌افزار «پلاتفرم پیام‌رسانی کاربر» (UMP) Google ابزاری برای حریم خصوصی و پیام‌رسانی است که به شما کمک می‌کند انتخاب‌های حریم خصوصی را مدیریت کنید. برای اطلاعات بیشتر، درباره «حریم‌خصوصی و پیام‌رسانی» را ببینید.

پیش‌نیازها

  • سطح میانای برنامه‌سازی کاربردی Android نسخه ۲۱ یا بالاتر (برای Android)

ایجاد نوع پیام

پیام‌های کاربر را با یکی از انواع پیام‌های کاربر دردسترس در برگه حریم خصوصی و پیام‌رسانی حساب AdMob خود ایجاد کنید. کیت توسعه نرم‌افزار UMP تلاش می‌کند پیام حریم خصوصی ایجادشده از شناسه برنامه AdMob تنظیم‌شده در پروژه‌تان را نمایش دهد.

برای جزئیات بیشتر، درباره حریم خصوصی و پیام‌رسانی را ببینید.

نصب کیت توسعه نرم‌افزار

  1. مراحل نصب Firebase C++‎ SDK را دنبال کنید. کیت توسعه نرم‌افزار UMP در ++C در کیت توسعه نرم‌افزار Firebase در ++C گنجانده شده است.

  2. پیش‌از ادامه دادن، مطمئن شوید که شناسه برنامه AdMob برنامه‌تان را در پروژه پیکربندی کرده‌اید.

  3. در کدتان، کیت توسعه نرم‌افزار UMP را با فراخوانی ConsentInfo::GetInstance() مقداردهی اولیه کنید.

    • در Android، باید JNIEnv و Activity ارائه‌شده توسط NDK را ارسال کنید. فقط اولین‌باری که با GetInstance() تماس می‌گیرید باید این کار را انجام دهید.
    • یا اگر ازقبل از کیت توسعه نرم‌افزار Firebase در ++C در برنامه‌تان استفاده می‌کنید، می‌توانید اولین‌باری که GetInstance() را فراخوانی می‌کنید، firebase::App را ارسال کنید.
    #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
    

فراخوانی‌های بعدی به ConsentInfo::GetInstance() همگی همان نمونه را برمی‌گردانند.

اگر کارتان با کیت توسعه نرم‌افزار «پلاتفرم پیام‌رسانی کاربر» تمام شده است، می‌توانید با حذف کردن نمونه 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. به‌طور دوره‌ای status() Future را بررسی کنید. وقتی وضعیت از kFutureStatusPending به kFutureStatusCompleted تغییر کند، عملیات تکمیل شده است.

پس‌از تکمیل عملیات ناهمگام، باید Future error() را بررسی کنید تا کد خطای عملیات را دریافت کنید. اگر کد خطا 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 و اسناد کیت توسعه نرم‌افزار GMA در ++C مراجعه کنید.

باید بااستفاده از RequestConsentInfoUpdate()، در هر بار راه‌اندازی برنامه، به‌روزرسانی اطلاعات رضایت کاربر را درخواست کنید. این درخواست موارد زیر را بررسی می‌کند:

  • آیا رضایت لازم است. برای مثال، برای اولین‌بار رضایت لازم است یا تصمیم رضایت قبلی منقضی شده است.
  • آیا نقطه ورودی گزینه‌های حریم خصوصی لازم است. برخی‌از پیام‌های حریم خصوصی برنامه‌ها را ملزم می‌کنند به کاربران اجازه دهند گزینه‌های حریم خصوصی‌شان را در هر زمانی تغییر دهند.
#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.
    });
}

بار کردن و ارائه فرم پیام حریم خصوصی

پس‌از دریافت به‌روزترین وضعیت رضایت، LoadAndShowConsentFormIfRequired() را فراخوانی کنید تا هر فرمی را که برای جمع‌آوری رضایت کاربر لازم است بار کند. پس‌از بار کردن، فرم‌ها بلافاصله ارائه می‌شوند.

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

برای دیدن نمونه‌ای از بررسی تکمیل بااستفاده از نظرسنجی حلقه به‌روزرسانی به‌جای فراخوانی تکمیل، به بالا مراجعه کنید.

اگر لازم است پس‌از اینکه کاربر انتخابی انجام داد یا فرم را رد کرد، اقدامی انجام دهید، آن منطق را در کدی قرار دهید که Future برگردانده‌شده توسط LoadAndShowConsentFormIfRequired() را مدیریت می‌کند.

گزینه‌های حریم‌خصوصی

برخی‌از فرم‌های پیام حریم خصوصی از نقطه ورودی گزینه‌های حریم خصوصی ارائه‌شده توسط ناشر ارائه می‌شوند و به کاربران اجازه می‌دهند گزینه‌های حریم خصوصی خود را در هر زمان مدیریت کنند. برای کسب اطلاعات بیشتر درباره اینکه کاربران شما کدام پیام را در نقطه ورودی گزینه‌های حریم خصوصی می‌بینند، انواع پیام کاربر دردسترس را ببینید.

درخواست آگهی با رضایت کاربر

قبل‌از درخواست آگهی، از ConsentInfo::GetInstance()‑> CanRequestAds() استفاده کنید تا بررسی کنید که آیا رضایت کاربر را دریافت کرده‌اید یا نه:

در زیر جاهایی که می‌توانید بررسی کنید آیا می‌توانید هنگام جمع‌آوری رضایت درخواست آگهی کنید یا نه فهرست شده است:

  • پس‌از اینکه کیت توسعه نرم‌افزار UMP در جلسه فعلی رضایت را جمع‌آوری کرد.
  • بلافاصله پس‌از تماس با RequestConsentInfoUpdate(). کیت توسعه نرم‌افزار UMP ممکن است در جلسه قبلی برنامه رضایت را کسب کرده باشد.

اگر درطول فرایند جمع‌آوری رضایت خطایی رخ داد، بررسی کنید که آیا می‌توانید درخواست آگهی کنید. کیت توسعه نرم‌افزار UMP از وضعیت رضایت جلسه قبلی برنامه استفاده می‌کند.

جلوگیری از کار درخواست آگهی تکراری

وقتی ConsentInfo::GetInstance()‑> CanRequestAds() را پس‌از جمع‌آوری رضایت و پس‌از فراخوانی RequestConsentInfoUpdate() بررسی می‌کنید، مطمئن شوید منطق شما از درخواست‌های آگهی زائد که ممکن است منجر به برگرداندن true توسط هر دو بررسی شود جلوگیری می‌کند. برای مثال، با متغیر بولی.

نمونه کامل زیر از نظرسنجی حلقه به‌روزرسانی استفاده می‌کند، اما می‌توانید از فراخوانی‌های برگشتی OnCompletion نیز برای نظارت بر عملیات ناهمگام استفاده کنید. از هر روشی که با ساختار کد شما سازگارتر است استفاده کنید.

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

آزمایش

اگر می‌خواهید ادغام را در برنامه‌تان درحین توسعه آزمایش کنید، این مراحل را برای ثبت دستگاه آزمایشی‌تان به‌صورت برنامه‌نویسی‌شده دنبال کنید. حتماً قبل‌از انتشار برنامه‌تان، کدی را که این شناسه‌های دستگاه آزمایشی را تنظیم می‌کند بردارید.

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

اجبار به مکان جغرافیایی

کیت توسعه نرم‌افزار پلاتفرم پیام‌رسانی کاربر راهی برای آزمایش رفتار برنامه‌تان ارائه می‌دهد، گویی دستگاه در مناطق مختلفی مثل منطقه اقتصادی اروپا (EEA)، پادشاهی متحد (UK)، و سوئیس بااستفاده از 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، ممکن است بازنشانی کردن وضعیت کیت توسعه نرم‌افزار برایتان مفید باشد تا بتوانید تجربه اولین نصب کاربر را شبیه‌سازی کنید. کیت توسعه نرم‌افزار روش Reset() را برای انجام این کار ارائه می‌دهد.

  ConsentInfo::GetInstance()->Reset();