بموجب سياسة موافقة المستخدم في الاتحاد الأوروبي التي تتّبعها Google، يجب الإفصاح عن معلومات معيّنة للمستخدمين في المنطقة الاقتصادية الأوروبية (EEA) والمملكة المتحدة والحصول على موافقتهم على استخدام ملفات تعريف الارتباط أو غير ذلك من البيانات المحفوظة على أجهزتهم المحلية حسب ما يقتضيه القانون، وعلى استخدام البيانات الشخصية (مثل AdID) لعرض الإعلانات. تعكس هذه السياسة شروط "التوجيه الأوروبي بشأن الخصوصية الإلكترونية" و"اللائحة العامة لحماية البيانات" (GDPR).
لدعم الناشرين في الوفاء بالتزاماتهم بموجب هذه السياسة، تقدّم Google حزمة تطوير البرامج (SDK) لمنصّة User Messaging Platform (UMP). تم تحديث حزمة تطوير البرامج لمنصة UMP لتتوافق مع أحدث معايير IAB. يمكن الآن التعامل مع كل هذه الإعدادات بسهولة في AdMob الخصوصية والمراسلة.
المتطلّبات الأساسية
- أكمِل دليل البدء.
- المستوى 21 من واجهة برمجة تطبيقات Android أو المستويات الأعلى
- إذا كنت تعمل على استيفاء المتطلبات المتعلّقة باللائحة العامة لحماية البيانات، يُرجى قراءة تأثير متطلّبات مكتب IAB على رسائل طلب موافقة المستخدمين في الاتحاد الأوروبي
إنشاء نوع رسالة
يمكنك إنشاء رسائل المستخدمين باستخدام أحد أنواع رسائل المستخدمين المتوفرة ضمن علامة تبويب الخصوصية والمراسلة في حساب AdMob . تحاول حزمة تطوير البرامج لمنصة UMP عرض رسالة مستخدم تم إنشاؤها من AdMob معرّف التطبيق المحدّد في مشروعك. وفي حال عدم إعداد أي رسالة لتطبيقك، ستعرض حزمة تطوير البرامج (SDK) رسالة خطأ.
لمزيد من التفاصيل، يُرجى الاطّلاع على لمحة عن الخصوصية والمراسلة.
التثبيت باستخدام Gradle
أضف التبعية لحزمة SDK لمنصة Google User Messaging Platform إلى ملف Gradle على مستوى التطبيق في وحدتك، عادةً app/build.gradle
:
dependencies {
implementation("com.google.android.ump:user-messaging-platform:2.2.0")
}
بعد إجراء التغييرات على build.gradle
لتطبيقك، تأكَّد من مزامنة مشروعك مع ملفات Gradle.
إضافة معرّف التطبيق
يمكنك العثور على رقم تعريف تطبيقك في
واجهة مستخدم AdMob.
إضافة المعرّف إلى
AndroidManifest.xml
مع مقتطف الرمز التالي:
<manifest>
<application>
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
</application>
</manifest>
طلب الحصول على معلومات الموافقة
يجب طلب تعديل لمعلومات موافقة المستخدم في كل مرة يتم فيها تشغيل التطبيق، وذلك باستخدام 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);
// Create a ConsentRequestParameters object.
ConsentRequestParameters params = new ConsentRequestParameters
.Builder()
.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)
// Create a ConsentRequestParameters object.
val params = ConsentRequestParameters
.Builder()
.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, "${requestConsentError.errorCode}: ${requestConsentError.message}")
})
}
}
تحميل نموذج موافقة وعرضه إذا لزم الأمر
بعد تلقّي أحدث حالة للموافقة، يمكنك الاتصال
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);
// Create a ConsentRequestParameters object.
ConsentRequestParameters params = new ConsentRequestParameters
.Builder()
.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)
// Create a ConsentRequestParameters object.
val params = ConsentRequestParameters
.Builder()
.build()
consentInformation = UserMessagingPlatform.getConsentInformation(this)
consentInformation.requestConsentInfoUpdate(
this,
params,
ConsentInformation.OnConsentInfoUpdateSuccessListener {
UserMessagingPlatform.loadAndShowConsentFormIfRequired(
this@MainActivity,
ConsentForm.OnConsentFormDismissedListener {
loadAndShowError ->
if (loadAndShowError != null) {
// Consent gathering failed.
Log.w(TAG, "${loadAndShowError.errorCode}: ${loadAndShowError.message}")
}
// Consent has been gathered.
}
)
},
ConsentInformation.OnConsentInfoUpdateFailureListener {
requestConsentError ->
// Consent gathering failed.
Log.w(TAG, "${requestConsentError.errorCode}: ${requestConsentError.message}")
})
}
}
إذا احتجت إلى تنفيذ أيّ إجراءات بعد أن يتّخذ المستخدم خيارًا أو يرفض النموذج، يُرجى إدراج هذا المنطق في callback للنموذج.
طلب إدراج الإعلانات
قبل طلب إعلانات في تطبيقك، يُرجى التحقّق مما إذا كنت قد حصلت على موافقة
من المستخدم من خلال استخدام " canRequestAds()
". هناك مكانان للتحقق
منهما أثناء جمع الموافقات:
- بعد الحصول على الموافقة في الجلسة الحالية
- فور اتصالك بـ
requestConsentInfoUpdate()
. من المحتمل أن تكون قد حصلت على موافقة في الجلسة السابقة. ومن أفضل ممارسات وقت الاستجابة، عدم انتظار اكتمال معاودة الاتصال حتى تتمكن من البدء في تحميل الإعلانات في أقرب وقت ممكن بعد إطلاق تطبيقك.
إذا حدث خطأ أثناء عملية الحصول على الموافقات، يجب أن تحاول طلب الإعلانات. تستخدم حزمة تطوير البرامج لمنصّة 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);
// Create a ConsentRequestParameters object.
ConsentRequestParameters params = new ConsentRequestParameters
.Builder()
.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;
}
new Thread(
() -> {
// Initialize the Google Mobile Ads SDK on a background thread.
MobileAds.initialize(this, initializationStatus -> {});
runOnUiThread(
() -> {
// TODO: Request an ad.
// InterstitialAd.load(...);
});
})
.start();
}
}
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)
// Create a ConsentRequestParameters object.
val params = ConsentRequestParameters
.Builder()
.build()
consentInformation = UserMessagingPlatform.getConsentInformation(this)
consentInformation.requestConsentInfoUpdate(
this,
params,
ConsentInformation.OnConsentInfoUpdateSuccessListener {
UserMessagingPlatform.loadAndShowConsentFormIfRequired(
this@MainActivity,
ConsentForm.OnConsentFormDismissedListener {
loadAndShowError ->
if (loadAndShowError != null) {
// Consent gathering failed.
Log.w(TAG, "${loadAndShowError.errorCode}: ${loadAndShowError.message}")
}
// Consent has been gathered.
if (consentInformation.canRequestAds()) {
initializeMobileAdsSdk()
}
}
)
},
ConsentInformation.OnConsentInfoUpdateFailureListener {
requestConsentError ->
// Consent gathering failed.
Log.w(TAG, "${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
}
val backgroundScope = CoroutineScope(Dispatchers.IO)
backgroundScope.launch {
// Initialize the Google Mobile Ads SDK on a background thread.
MobileAds.initialize(this@MainActivity) {}
// TODO: Request an ad.
// InterstitialAd.load(...)
}
}
}
خيارات الخصوصية
تتطلّب بعض نماذج الموافقة من المستخدِم تعديل موافقته في أي وقت. التزم بالخطوات التالية لتفعيل زر خيارات الخصوصية إذا لزم الأمر.
ولإجراء ذلك:
- تنفيذ عنصر في واجهة المستخدم، مثل زر في صفحة إعدادات التطبيق، يمكن أن يؤدي إلى ظهور نموذج خيارات الخصوصية
- بعد
loadAndShowConsentFormIfRequired()
اكتمال البحث، ضَع علامة في المربّعprivacyOptionsRequirementStatus()
لتحديد ما إذا كان سيتم عرض عنصر واجهة المستخدم الذي يمكنه تقديم نموذج خيارات الخصوصية. - عندما يتفاعل أحد المستخدمين مع عنصر واجهة المستخدم، يمكنك طلب
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)
}
الاختبار
إذا أردت اختبار التكامل في تطبيقك أثناء تطويره، اتّبِع هذه الخطوات لتسجيل جهاز الاختبار آليًا. واحرص على إزالة الرمز الذي يضبط أرقام تعريف الأجهزة الاختبارية قبل إصدار تطبيقك.
- اتصل على
requestConsentInfoUpdate()
. تحقَّق من إخراج السجلّ لرسالة مشابهة للمثال التالي، والذي يُظهر رقم تعريف جهازك وكيفية إضافته كجهاز اختبار:
Use new ConsentDebugSettings.Builder().addTestDeviceHashedId("33BE2250B43518CCDA7DE426D04EE231") to set this as a debug device.
انسخ رقم تعريف جهاز الاختبار إلى الحافظة.
عليك تعديل الرمز من أجل الاتصال
ConsentDebugSettings.Builder().addTestDeviceHashedId()
واجتياز قائمة بأرقام تعريف أجهزة الاختبار.
فرض موقع جغرافي
توفّر حزمة تطوير البرامج (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
أمثلة على دمج حزمة تطوير البرامج لمنصّة UMP: Java | Kotlin