البدء

بموجب موافقة المستخدم في الاتحاد الأوروبي التي تتّبعها Google للسياسة، يجب الإفصاح عن معلومات محدّدة للمستخدمين في المنطقة الاقتصادية الأوروبية في المملكة المتحدة والحصول على موافقتها على استخدام ملفات تعريف الارتباط أو غيرها من مساحات التخزين المحلية حيثما يكون ذلك مطلوبًا بموجب القانون، واستخدام البيانات الشخصية (مثل AdID) لعرض الإعلانات تعكس هذه السياسة شروط "التوجيه الأوروبي بشأن الخصوصية الإلكترونية" اللائحة العامة لحماية البيانات (GDPR).

لمساعدة الناشرين في الوفاء بواجباتهم بموجب هذه السياسة، توفّر Google حزمة تطوير البرامج (SDK) لمنصّة User Messaging Platform (UMP). تم تحديث حزمة تطوير البرامج لمنصة UMP لدعم وأحدث معايير IAB. يمكن الآن تحويل جميع هذه التهيئات يتم التعامل معه في AdMob سياسة الخصوصية المراسلة.

المتطلبات الأساسية

  • المستوى 21 من واجهة برمجة تطبيقات Android أو المستويات الأعلى (لنظام التشغيل Android)

إنشاء نوع رسالة

يمكنك إنشاء رسائل المستخدمين باستخدام إحدى أنواع رسائل المستخدمين المتوفرة بموجب الخصوصية "المراسلة" في AdMob الحساب. تحاول حزمة تطوير البرامج لمنصّة UMP عرض رسالة مستخدم تم إنشاؤها من AdMob معرّف التطبيق التي تم تعيينها في مشروعك. وفي حال عدم ضبط أي رسالة لتطبيقك، ستتم إضافة حزمة تطوير البرامج (SDK) بإرجاع خطأ.

لمزيد من التفاصيل، يُرجى مراجعة لمحة عن الخصوصية والمراسلة

تثبيت حزمة تطوير البرامج (SDK)

  1. اتبع الخطوات لتثبيت إعلانات Google للأجهزة الجوّالة (GMA) C++ SDK. UMP C++ يتم تضمين حزمة SDK في حزمة تطوير البرامج (SDK) لإعلانات Google على الأجهزة الجوّالة (GMA C++).

  2. تأكَّد من ضبط تطبيق AdMob لتطبيقك. رقم التعريف في المشروع قبل المتابعة.

  3. في الرمز البرمجي، عليك إعداد حزمة تطوير البرامج (SDK) لمنصّة UMP من خلال استدعاء ConsentInfo::GetInstance()

    • على نظام التشغيل Android، يجب اجتياز الاختبار في JNIEnv وActivity المقدَّمَين من خلال NDK. عليك إجراء ذلك فقط في المرة الأولى التي تتصل فيها بـ GetInstance().
    • أما إذا كنت تستخدم الإصدار C++ من Firebase حاليًا 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() المثيل نفسه.

إذا انتهيت من استخدام حزمة تطوير البرامج (SDK) لمنصّة UMP، يمكنك إيقاف حزمة SDK من خلال حذف مثال واحد (ConsentInfo):

void ShutdownUserMessagingPlatform() {
  ump::ConsentInfo* consent_info = ump::ConsentInfo::GetInstance();
  delete consent_info;
}

استخدام Future لمراقبة العمليات غير المتزامنة

حاسمة firebase::Future طريقة لتحديد حالة الإكمال للطريقة غير المتزامنة الاتصالات.

تعرض جميع دوال UMP C++ وطلبات الطرق التي تعمل بشكل غير متزامن Future، وتقدِّم أيضًا "نتيجة أخيرة" لاسترداد Future من أحدث عملية.

هناك طريقتان للحصول على نتيجة من Future:

  1. يمكنك الاتصال على الرقم OnCompletion()، تمرير دالة الاستدعاء الخاصة بك، وهو ما يسمى عند إجراء العملية تكتمل.
  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، يُرجى الاطّلاع على حزمة تطوير البرامج (SDK) بلغة C++ من Firebase المستندات ومستندات حزمة تطوير البرامج (SDK) لإعلانات Google على الأجهزة الجوّالة (GMA C++).

إضافة معرّف التطبيق

يمكنك العثور على رقم تعريف طلبك في واجهة مستخدم 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 حالة الموافقة من الحزمة السابقة جلسة المراجعة.

يستخدم المثال الكامل التالي الاستطلاع المتكرر، ولكن يمكنك أيضًا استخدام 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() لتحديد ما إذا كان سيتم عرض عنصر واجهة المستخدم الذي يمكنه تقديم نموذج خيارات الخصوصية.
  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);
    }
    

فرض موقع جغرافي

توفِّر حزمة تطوير البرامج (SDK) لمنصّة UMP طريقة لاختبار سلوك تطبيقك كما لو كان الجهاز في المنطقة الاقتصادية الأوروبية أو المملكة المتحدة باستخدام 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) الطريقة Reset() لإجراء ذلك.

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

أمثلة على GitHub