البدء

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

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

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

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

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

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

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

التثبيت باستخدام Gradle

أضِف التبعية لحزمة تطوير البرامج (SDK) لمنصة Google User Messaging Platform إلى ملف Gradle على مستوى التطبيق في الوحدة، وعادةً ما يكون app/build.gradle:

dependencies {
  implementation("com.google.android.ump:user-messaging-platform:2.1.0")
}

بعد إجراء التغييرات على build.gradle في تطبيقك، تأكَّد من مزامنة مشروعك مع ملفات Gradle.

يجب طلب تعديل معلومات موافقة المستخدم عند كل عملية إطلاق للتطبيق باستخدام requestConsentInfoUpdate(). يحدد هذا ما إذا كان المستخدم بحاجة إلى تقديم موافقته إذا لم يفعل ذلك بالفعل أو إذا انتهت صلاحية موافقته.

إليك مثال على طريقة التحقّق من الحالة من MainActivity في طريقة onCreate().

Java

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import com.google.android.ump.ConsentInformation;
import com.google.android.ump.ConsentRequestParameters;
import com.google.android.ump.FormError;
import com.google.android.ump.UserMessagingPlatform;

public class MainActivity extends AppCompatActivity {
  private ConsentInformation consentInformation;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    ConsentRequestParameters params = new ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build();

    consentInformation = UserMessagingPlatform.getConsentInformation(this);
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        (OnConsentInfoUpdateSuccessListener) () -> {
          // TODO: Load and show the consent form.
        },
        (OnConsentInfoUpdateFailureListener) requestConsentError -> {
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.getErrorCode(),
              requestConsentError.getMessage()));
        });
  }
}

Kotlin

package com.example.myapplication

import com.google.android.ump.ConsentInformation
import com.google.android.ump.ConsentInformation.OnConsentInfoUpdateFailureListener
import com.google.android.ump.ConsentInformation.OnConsentInfoUpdateSuccessListener
import com.google.android.ump.ConsentRequestParameters
import com.google.android.ump.UserMessagingPlatform

class MainActivity : AppCompatActivity() {
  private lateinit var consentInformation: ConsentInformation

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    val params = ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build()

    consentInformation = UserMessagingPlatform.getConsentInformation(this)
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        ConsentInformation.OnConsentInfoUpdateSuccessListener {
          // TODO: Load and show the consent form.
        },
        ConsentInformation.OnConsentInfoUpdateFailureListener {
          requestConsentError ->
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.errorCode(),
              requestConsentError.message()))
        })
  }
}

تحميل نموذج موافقة وإظهاره إذا لزم الأمر

ملاحظة مهمة: تتوافق واجهات برمجة التطبيقات التالية مع الإصدار 2.1.0 أو الإصدارات الأحدث من حزمة تطوير البرامج (SDK) الخاصة بمنصة UMP.

بعد تلقّي أحدث حالة للموافقة، يمكنك الاتصال loadAndShowConsentFormIfRequired() بالصف ConsentForm لتحميل نموذج الموافقة. إذا كانت حالة الموافقة مطلوبة، تُحمِّل حزمة تطوير البرامج (SDK) نموذجًا وتقدمه على الفور من activityالمقدّمة. يتم callback تم تسمية بعد إغلاق النموذج. في حال لم تكن الموافقة مطلوبة، يتم callback طلب الاستلام على الفور.

Java

public class MainActivity extends AppCompatActivity {
  private ConsentInformation consentInformation;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    ConsentRequestParameters params = new ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build();

    consentInformation = UserMessagingPlatform.getConsentInformation(this);
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        (OnConsentInfoUpdateSuccessListener) () -> {
          UserMessagingPlatform.loadAndShowConsentFormIfRequired(
            this,
            (OnConsentFormDismissedListener) loadAndShowError -> {
              if (loadAndShowError != null) {
                // Consent gathering failed.
                Log.w(TAG, String.format("%s: %s",
                    loadAndShowError.getErrorCode(),
                    loadAndShowError.getMessage()));
              }

              // Consent has been gathered.
            }
          )
        },
        (OnConsentInfoUpdateFailureListener) requestConsentError -> {
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.getErrorCode(),
              requestConsentError.getMessage()));
        });
  }
}

Kotlin

class MainActivity : AppCompatActivity() {
  private lateinit var consentInformation: ConsentInformation

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    val params = ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build()

    consentInformation = UserMessagingPlatform.getConsentInformation(this)
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        ConsentInformation.OnConsentInfoUpdateSuccessListener {
          UserMessagingPlatform.loadAndShowConsentFormIfRequired(
            this@MainActivity,
            ConsentForm.OnConsentFormDismissedListener {
              loadAndShowError ->
              // Consent gathering failed.
              Log.w(TAG, String.format("%s: %s",
                  loadAndShowError.errorCode(),
                  loadAndShowError.message()))

              // Consent has been gathered.
            }
          )
        },
        ConsentInformation.OnConsentInfoUpdateFailureListener {
          requestConsentError ->
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.errorCode(),
              requestConsentError.message()))
        })
  }
}

إذا كنت بحاجة إلى تنفيذ أي إجراءات بعد أن اختار المستخدم النموذج أو تجاهله، فأدرِج هذا المنطق في callback نموذجك.

طلب إدراج الإعلانات

قبل طلب الإعلانات في تطبيقك، تحقّق مما إذا كنت قد حصلت على الموافقة من المستخدِم الذي يستخدم canRequestAds(). هناك مكانان يجب التحقق منه أثناء جمع الموافقات:

  1. بعد الحصول على الموافقة في الجلسة الحالية
  2. مباشرةً بعد الاتصال بـ requestConsentInfoUpdate(). من المحتمل أن يكون قد حصل على موافقة في الجلسة السابقة. من بين أفضل الممارسات التي تتعلق بوقت الاستجابة، ننصح بعدم انتظار اكتمال معاودة الاتصال حتى تتمكن من البدء في تحميل الإعلانات في أقرب وقت ممكن بعد إطلاق تطبيقك.

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

Java

public class MainActivity extends AppCompatActivity {
  private ConsentInformation consentInformation;
  // Use an atomic boolean to initialize the Google Mobile Ads SDK and load ads once.
  private final AtomicBoolean isMobileAdsInitializeCalled = new AtomicBoolean(false);
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    ConsentRequestParameters params = new ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build();

    consentInformation = UserMessagingPlatform.getConsentInformation(this);
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        (OnConsentInfoUpdateSuccessListener) () -> {
          UserMessagingPlatform.loadAndShowConsentFormIfRequired(
            this,
            (OnConsentFormDismissedListener) loadAndShowError -> {
              if (loadAndShowError != null) {
                // Consent gathering failed.
                Log.w(TAG, String.format("%s: %s",
                    loadAndShowError.getErrorCode(),
                    loadAndShowError.getMessage()));
              }

              // Consent has been gathered.
              if (consentInformation.canRequestAds) {
                initializeMobileAdsSdk();
              }
            }
          )
        },
        (OnConsentInfoUpdateFailureListener) requestConsentError -> {
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.getErrorCode(),
              requestConsentError.getMessage()));
        });
    
    // Check if you can initialize the Google Mobile Ads SDK in parallel
    // while checking for new consent information. Consent obtained in
    // the previous session can be used to request ads.
    if (consentInformation.canRequestAds) {
      initializeMobileAdsSdk();
    }
  }
  
  private void initializeMobileAdsSdk() {
    if (isMobileAdsInitializeCalled.getAndSet(true)) {
      return;
    }

    // Initialize the Google Mobile Ads SDK.
    MobileAds.initialize(this);

    // TODO: Request an ad.
    // InterstitialAd.load(...);
  }
}

Kotlin

class MainActivity : AppCompatActivity() {
  private lateinit var consentInformation: ConsentInformation
  // Use an atomic boolean to initialize the Google Mobile Ads SDK and load ads once.
  private var isMobileAdsInitializeCalled = AtomicBoolean(false)
  
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Set tag for under age of consent. false means users are not under age
    // of consent.
    val params = ConsentRequestParameters
        .Builder()
        .setTagForUnderAgeOfConsent(false)
        .build()

    consentInformation = UserMessagingPlatform.getConsentInformation(this)
    consentInformation.requestConsentInfoUpdate(
        this,
        params,
        ConsentInformation.OnConsentInfoUpdateSuccessListener {
          UserMessagingPlatform.loadAndShowConsentFormIfRequired(
            this@MainActivity,
            ConsentForm.OnConsentFormDismissedListener {
              loadAndShowError ->
              // Consent gathering failed.
              Log.w(TAG, String.format("%s: %s",
                  loadAndShowError.errorCode(),
                  loadAndShowError.message()))

              // Consent has been gathered.
              if (consentInformation.canRequestAds) {
                initializeMobileAdsSdk()
              }
            }
          )
        },
        ConsentInformation.OnConsentInfoUpdateFailureListener {
          requestConsentError ->
          // Consent gathering failed.
          Log.w(TAG, String.format("%s: %s",
              requestConsentError.errorCode(),
              requestConsentError.message()))
        })
    
    // Check if you can initialize the Google Mobile Ads SDK in parallel
    // while checking for new consent information. Consent obtained in
    // the previous session can be used to request ads.
    if (consentInformation.canRequestAds) {
      initializeMobileAdsSdk()
    }
  }
  
  private fun initializeMobileAdsSdk() {
    if (isMobileAdsInitializeCalled.getAndSet(true)) {
      return
    }

    // Initialize the Google Mobile Ads SDK.
    MobileAds.initialize(this)

    // TODO: Request an ad.
    // InterstitialAd.load(...)
  }
}

خيارات الخصوصية

تتطلّب بعض نماذج الموافقة من المستخدِم تعديل موافقته في أي وقت. التزم بالخطوات التالية لتطبيق زر خيارات الخصوصية إذا لزم الأمر.

ولإجراء ذلك:

  1. نفِّذ عنصر واجهة مستخدم، مثل زر في صفحة إعدادات التطبيق، يمكن أن يؤدي إلى تشغيل نموذج خيارات الخصوصية.
  2. بعد loadAndShowConsentFormIfRequired() الاكتمال، تحقَّق من privacyOptionsRequirementStatus() لتحديد ما إذا كان سيتم عرض عنصر واجهة المستخدم الذي يمكنه تقديم نموذج خيارات الخصوصية.
  3. عندما يتفاعل مستخدم مع عنصر في واجهة المستخدم، يمكنك استدعاء showPrivacyOptionsForm() لعرض النموذج حتى يتمكّن المستخدم من تعديل خيارات الخصوصية في أي وقت.

يوضّح المثال التالي كيفية مشاركة عرض نموذج خيارات الخصوصية من MenuItem.

Java

private final ConsentInformation consentInformation;

// Show a privacy options button if required.
public boolean isPrivacyOptionsRequired() {
  return consentInformation.getPrivacyOptionsRequirementStatus()
      == PrivacyOptionsRequirementStatus.REQUIRED;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
  // ...

  consentInformation = UserMessagingPlatform.getConsentInformation(this);
  consentInformation.requestConsentInfoUpdate(
      this,
      params,
      (OnConsentInfoUpdateSuccessListener) () -> {
        UserMessagingPlatform.loadAndShowConsentFormIfRequired(
          this,
          (OnConsentFormDismissedListener) loadAndShowError -> {
            // ...

            // Consent has been gathered.

            if (isPrivacyOptionsRequired()) {
              // Regenerate the options menu to include a privacy setting.
              invalidateOptionsMenu();
            }
          }
        )
      }
      // ...
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.action_menu, menu);
  MenuItem moreMenu = menu.findItem(R.id.action_more);
  moreMenu.setVisible(isPrivacyOptionsRequired());
  return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
  // ...

  popup.setOnMenuItemClickListener(
      popupMenuItem -> {
        if (popupMenuItem.getItemId() == R.id.privacy_settings) {
          // Present the privacy options form when a user interacts with
          // the privacy settings button.
          UserMessagingPlatform.showPrivacyOptionsForm(
              this,
              formError -> {
                if (formError != null) {
                  // Handle the error.
                }
              }
          );
          return true;
        }
        return false;
      });
  return super.onOptionsItemSelected(item);
}

Kotlin

private val consentInformation: ConsentInformation =
  UserMessagingPlatform.getConsentInformation(context)

// Show a privacy options button if required.
val isPrivacyOptionsRequired: Boolean
  get() =
    consentInformation.privacyOptionsRequirementStatus ==
      ConsentInformation.PrivacyOptionsRequirementStatus.REQUIRED

override fun onCreate(savedInstanceState: Bundle?) {
  ...
  consentInformation = UserMessagingPlatform.getConsentInformation(this)
  consentInformation.requestConsentInfoUpdate(
      this,
      params,
      ConsentInformation.OnConsentInfoUpdateSuccessListener {
        UserMessagingPlatform.loadAndShowConsentFormIfRequired(
          this@MainActivity,
          ConsentForm.OnConsentFormDismissedListener {
            // ...

            // Consent has been gathered.

            if (isPrivacyOptionsRequired) {
              // Regenerate the options menu to include a privacy setting.
              invalidateOptionsMenu();
            }
          }
        )
      }
      // ...
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
  menuInflater.inflate(R.menu.action_menu, menu)
  menu?.findItem(R.id.action_more)?.apply {
    isVisible = isPrivacyOptionsRequired
  }
  return super.onCreateOptionsMenu(menu)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
  // ...

  popup.setOnMenuItemClickListener { popupMenuItem ->
    when (popupMenuItem.itemId) {
      R.id.privacy_settings -> {
        // Present the privacy options form when a user interacts with
        // the privacy settings button.
        UserMessagingPlatform.showPrivacyOptionsForm(this) { formError ->
          formError?.let {
            // Handle the error.
          }
        }
        true
      }
      else -> false
    }
  }
  return super.onOptionsItemSelected(item)
}

الاختبار

إذا كنت تريد اختبار التكامل في تطبيقك أثناء تطويره، اتّبِع الخطوات التالية لتسجيل جهاز الاختبار آليًا.

  1. الاتصال بـ requestConsentInfoUpdate()
  2. تحقَّق من نتائج السجلّ بحثًا عن رسالة تشبه الرسالة الواردة أدناه والتي توضِّح لك رقم تعريف جهازك وكيفية إضافته كجهاز اختبار:

    Use new ConsentDebugSettings.Builder().addTestDeviceHashedId("33BE2250B43518CCDA7DE426D04EE231") to set this as a debug device.
    
  3. انسخ رقم تعريف جهاز الاختبار إلى الحافظة.

  4. يُرجى تعديل الرمز ليتم الاتصال ConsentDebugSettings.Builder().addTestDeviceHashedId() وإرسال قائمة بأرقام تعريف أجهزة الاختبار.

Java

ConsentDebugSettings debugSettings = new ConsentDebugSettings.Builder(this)
    .addTestDeviceHashedId("TEST-DEVICE-HASHED-ID")
    .build();

ConsentRequestParameters params = new ConsentRequestParameters
    .Builder()
    .setConsentDebugSettings(debugSettings)
    .build();

consentInformation = UserMessagingPlatform.getConsentInformation(this);
// Include the ConsentRequestParameters in your consent request.
consentInformation.requestConsentInfoUpdate(
    this,
    params,
    ...
);

Kotlin

val debugSettings = ConsentDebugSettings.Builder(this)
    .addTestDeviceHashedId("TEST-DEVICE-HASHED-ID")
    .build()

val params = ConsentRequestParameters
    .Builder()
    .setConsentDebugSettings(debugSettings)
    .build()

consentInformation = UserMessagingPlatform.getConsentInformation(this)
// Include the ConsentRequestParameters in your consent request.
consentInformation.requestConsentInfoUpdate(
    this,
    params,
    ...
)

فرض منطقة جغرافية

توفّر حزمة تطوير البرامج (SDK) الخاصة بمنصة UMP وسيلة لاختبار سلوك تطبيقك كما لو كان الجهاز يقع في المنطقة الاقتصادية الأوروبية أو المملكة المتحدة باستخدام the setDebugGeography() method which takes a DebugGeography on ConsentDebugSettings.Builder. تجدر الإشارة إلى أنّ إعدادات تصحيح الأخطاء لا تعمل إلا على أجهزة الاختبار.

Java

ConsentDebugSettings debugSettings = new ConsentDebugSettings.Builder(this)
    .setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA)
    .addTestDeviceHashedId("TEST-DEVICE-HASHED-ID")
    .build();

ConsentRequestParameters params = new ConsentRequestParameters
    .Builder()
    .setConsentDebugSettings(debugSettings)
    .build();

consentInformation = UserMessagingPlatform.getConsentInformation(this);
// Include the ConsentRequestParameters in your consent request.
consentInformation.requestConsentInfoUpdate(
    this,
    params,
    ...
);

Kotlin

val debugSettings = ConsentDebugSettings.Builder(this)
    .setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA)
    .addTestDeviceHashedId("TEST-DEVICE-HASHED-ID")
    .build()

val params = ConsentRequestParameters
    .Builder()
    .setConsentDebugSettings(debugSettings)
    .build()

consentInformation = UserMessagingPlatform.getConsentInformation(this)
// Include the ConsentRequestParameters in your consent request.
consentInformation.requestConsentInfoUpdate(
    this,
    params,
    ...
)

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

Java

consentInformation.reset();

Kotlin

consentInformation.reset()

أمثلة على GitHub

أمثلة على دمج حزمة تطوير البرامج (SDK) لمنصّة UMP: Java | Kotlin