شروع کنید

تحت خط‌مشی رضایت کاربر اتحادیه اروپا Google، شما باید اطلاعات مشخصی را برای کاربران خود در منطقه اقتصادی اروپا (EEA) همراه با بریتانیا انجام دهید و رضایت آنها را برای استفاده از کوکی‌ها یا سایر فضای ذخیره‌سازی محلی، در صورت نیاز قانونی، و استفاده از داده‌های شخصی کسب کنید ( مانند AdID) برای ارائه تبلیغات. این سیاست منعکس کننده الزامات دستورالعمل حریم خصوصی الکترونیک اتحادیه اروپا و مقررات عمومی حفاظت از داده ها (GDPR) است.

برای حمایت از ناشران در انجام وظایف خود تحت این خط‌مشی، Google پلتفرم پیام‌رسانی کاربر (UMP) SDK را ارائه می‌دهد. UMP SDK برای پشتیبانی از آخرین استانداردهای IAB به روز شده است. همه این پیکربندی‌ها اکنون می‌توانند به راحتی در حریم خصوصی و پیام‌رسانی AdMob مدیریت شوند.

پیش نیازها

  • Android API سطح 21 یا بالاتر(برای Android)
  • اگر روی الزامات مربوط به GDPR کار می‌کنید،

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

پیام‌های کاربری را با یکی از انواع پیام کاربرموجوددر برگه حریم خصوصی و پیام‌رسانیAdMobAd Manager ایجاد کنید. UMP SDK سعی می کند یک پیام کاربر ایجاد شده از شناسه برنامه AdMob را در پروژه شما نمایش دهد. اگر هیچ پیامی برای برنامه شما پیکربندی نشده باشد، SDK یک خطا برمی‌گرداند.

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

SDK را نصب کنید

  1. مراحل نصب Google Mobile Ads (GMA) C++ SDK را دنبال کنید. UMP C++ SDK در GMA C++ SDK گنجانده شده است.

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

  3. در کد خود، UMP SDK را با فراخوانی ConsentInfo::GetInstance() مقداردهی اولیه کنید.

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

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 برای تنظیم یک فراخوان تکمیلی آورده شده است که پس از اتمام عملیات ناهمزمان فراخوانی می شود.

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

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

در صورت نیاز فرم رضایت را بارگیری و نمایش دهید

پس از دریافت به روزترین وضعیت رضایت، با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 برای نظارت بر عملیات ناهمزمان نیز استفاده کنید . از هر تکنیکی که با ساختار کد شما سازگارتر است استفاده کنید.

#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() را بررسی کنید تا مشخص شود که آیا عنصر UI که می تواند فرم گزینه های حریم خصوصی را ارائه دهد، نمایش داده شود یا خیر.
  3. هنگامی که کاربر با عنصر UI شما تعامل می کند، باshowPrivacyOptionsForm() تماس بگیرید تا فرم را نشان دهد تا کاربر بتواند گزینه های حریم خصوصی خود را در هر زمانی به روز کند.

آزمایش کردن

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

  1. با RequestConsentInfoUpdate()تماس بگیرید.
  2. خروجی گزارش را برای پیامی شبیه به مثال زیر بررسی کنید، که شناسه دستگاه شما و نحوه افزودن آن را به عنوان یک دستگاه آزمایشی نشان می دهد:

    اندروید

    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 را به 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 راهی برای آزمایش رفتار برنامه شما ارائه می‌کند که گویی دستگاه در منطقه اقتصادی اروپا یا بریتانیا با استفاده از 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();