В соответствии с Политикой согласия пользователей Google из ЕС вы должны раскрыть определенную информацию своим пользователям в Европейской экономической зоне (ЕЭЗ), а также в Великобритании, и получить их согласие на использование файлов cookie или другого локального хранилища, если это требуется по закону, а также на использование личных данных ( например AdID) для показа рекламы. Эта политика отражает требования Директивы ЕС об электронной конфиденциальности и Общего регламента защиты данных (GDPR).
Чтобы помочь издателям выполнять свои обязанности в соответствии с этой политикой, Google предлагает SDK User Messaging Platform (UMP). UMP SDK был обновлен для поддержки новейших стандартов IAB. Всеми этими конфигурациями теперь можно удобно управлять в разделе конфиденциальности и обмена сообщениями AdMob .
Предварительные условия
- Завершить руководство по началу работы
- Android API уровня 21 или выше
- Если вы работаете над требованиями, связанными с GDPR, прочитайтеКак требования IAB влияют на сообщения о согласии в ЕС
Создайте тип сообщения
Создавайте пользовательские сообщения с одним из доступных типов сообщенийна вкладке Конфиденциальность и сообщения вашей учетной записиAdMob. UMP SDK пытается отобразить сообщение пользователя, созданное на основе идентификатора приложения 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()
.
Джава
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()));
});
}
}
Котлин
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()))
})
}
}
Загрузите и покажите форму согласия, если требуется.
Важно. Следующие API-интерфейсы совместимы с UMP SDK версии 2.1.0 или выше. После получения последней версии статуса согласия вызовитеloadAndShowConsentFormIfRequired()
в классеConsentForm
, чтобы загрузить форму согласия. Если требуется статус согласия, SDK загружает форму и немедленно представляет ее из предоставленного activity. callbackвызывается после закрытия формы. Если согласие не требуется, callbackнемедленно вызывается .
Джава
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()));
});
}
}
Котлин
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()
. При получении согласия необходимо проверить два места:
- После того, как согласие было получено в текущем сеансе.
- Сразу после того, как вы вызвали
requestConsentInfoUpdate()
. Возможно, согласие было получено на предыдущем сеансе. В целях снижения задержки мы рекомендуем не дожидаться завершения обратного вызова, чтобы вы могли начать загрузку рекламы как можно скорее после запуска приложения.
Если в процессе сбора согласия возникает ошибка, вам все равно следует попытаться запросить рекламу. UMP SDK использует статус согласия из предыдущего сеанса.
Джава
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(...);
}
}
Котлин
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(...)
}
}
Параметры конфиденциальности
Некоторые формы согласия требуют от пользователя изменить свое согласие в любое время. При необходимости выполните следующие действия, чтобы добавить кнопку параметров конфиденциальности.
Для этого:
- Реализуйте элемент пользовательского интерфейса, например кнопку на странице настроек вашего приложения, который может запускать форму параметров конфиденциальности.
- После завершения работы
loadAndShowConsentFormIfRequired()
проверьтеprivacyOptionsRequirementStatus()
чтобы определить, отображать ли элемент пользовательского интерфейса, который может отображать форму параметров конфиденциальности. - Когда пользователь взаимодействует с вашим элементом пользовательского интерфейса, вызовите
showPrivacyOptionsForm()
чтобы отобразить форму, чтобы пользователь мог обновить свои параметры конфиденциальности в любое время.
В следующем примере показано, как представить форму параметров конфиденциальности из MenuItem
.
Джава
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);
}
Котлин
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()
и передайте всписок идентификаторов тестовых устройств.
Джава
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,
...
);
Котлин
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,
...
)
Принудительно использовать географию
UMP SDK предоставляет возможность протестировать поведение вашего приложения, как если бы устройство находилось в ЕЭЗ или Великобритании, с помощью the setDebugGeography()
method which takes a DebugGeography
on ConsentDebugSettings.Builder
. Обратите внимание, что настройки отладки работают только на тестовых устройствах.
Джава
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,
...
);
Котлин
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,
...
)
Сбросить статус согласия
При тестировании приложения с помощью UMP SDK вам может оказаться полезным сбросить состояние SDK, чтобы можно было имитировать первый опыт установки пользователя. Для этого в SDK предусмотрен метод reset()
.
Джава
consentInformation.reset();
Котлин
consentInformation.reset()
Примеры на GitHub
Примеры интеграции UMP SDK: Java | Kotlin