البدء

حزمة تطوير البرامج لمنصة UMP هي أداة للخصوصية والمراسلة تساعدك في إدارة خيارات الخصوصية. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة لمحة عن أداة "الخصوصية والمراسلة".

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

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

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

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

لمزيد من التفاصيل، يُرجى الاطّلاع على مقالة لمحة عن أداة "الخصوصية والمراسلة".

تثبيت حزمة SDK

  1. اتّبِع الخطوات لتثبيت حزمة تطوير البرامج (SDK) لبرنامج Firebase C++‎. يتم تضمين حزمة تطوير البرامج (SDK) لمنصّة UMP C++‎ في حزمة تطوير البرامج (SDK) لمنصّة Firebase C++‎.

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

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

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

وتؤدي الطلبات اللاحقة إلى ConsentInfo::GetInstance() إلى عرض المثيل نفسه.

إذا انتهيت من استخدام حزمة تطوير البرامج لمنصة UMP، يمكنك إيقاف حزمة تطوير البرامج عن طريق حذف مثيل 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) لـ Firebase C++‎ ومستندات حزمة تطوير البرامج (SDK) لـ 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);
    }
    

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

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