根据 Google 欧盟地区用户意见征求 政策,您必须 向欧洲经济区 (EEA) 内的用户披露某些信息, 与英国用户签订协议,并就使用 Cookie 或其他本地存储方式征得用户同意; 以及使用个人数据(如 AdID)来投放广告。 此政策反映了欧盟《电子隐私指令》和 一般数据保护条例 (GDPR)。
为了帮助发布商履行此政策规定的职责,Google 提供了 User Messaging Platform (UMP) SDK。UMP SDK 已更新,可支持 最新 IAB 标准现在,所有这些配置 隐私权和 Ad Manager 消息。
前提条件
- 完成入门指南
- Android API 级别 21 或更高级别
- 如果您正在努力满足 GDPR 的相关要求,请阅读 IAB 要求对欧盟地区用户意见征求的影响 消息
创建消息类型
使用以下任一方式创建用户消息: 可用的用户消息类型 隐私权和消息功能标签页 Ad Manager 。UMP SDK 会尝试显示 根据 Ad Manager 应用 ID 创建用户消息 。如果没有为您的应用配置消息,SDK 返回一个错误。
有关详情,请参阅 隐私权和消息简介。
使用 Gradle 安装
将 Google User Messaging Platform SDK 的依赖项添加到模块的
应用级 Gradle 文件,通常为 app/build.gradle
:
dependencies {
implementation("com.google.android.ump:user-messaging-platform:2.2.0")
}
对应用的 build.gradle
进行更改后,请务必同步您的
包含 Gradle 文件的项目。
添加应用 ID
您可以在
Ad Manager 界面。
将此 ID 添加到您的
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 SDK 会使用之前的 会话。
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.
// loadInterstitialAd();
});
})
.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 {
MobileAds.initialize(this@MainActivity) {}
runOnUiThread {
// TODO: Request an ad.
// loadInterstitialAd()
}
}
}
}
隐私设置选项
有些用户意见征求表单会要求用户随时修改同意情况。遵守 按照以下步骤,根据需要实现隐私权选项按钮。
要实现这一目标,需要完成以下步骤:
- 实现界面元素,例如应用的设置页面中的按钮; 可触发隐私权选项表单的应用
-
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)
}
测试
如果您想在开发过程中测试应用中的集成情况,请按照 这些步骤以程序化方式注册测试设备。请务必移除 代码,在您发布应用之前设置这些测试设备 ID。
- 致电
requestConsentInfoUpdate()
。 检查日志输出是否包含类似于以下示例的消息, 显示了您的设备 ID 以及如何将其添加为测试设备:
Use new ConsentDebugSettings.Builder().addTestDeviceHashedId("33BE2250B43518CCDA7DE426D04EE231") to set this as a debug device.
将测试设备 ID 复制到剪贴板。
将代码修改为 致电
DebugGeography.TestDeviceHashedIds
并传入 您的测试设备 ID 列表。
强制指定地理位置
UMP SDK 提供了一种方法来测试应用行为,就好像设备被
位于欧洲经济区 (EEA) 或英国境内的用户使用 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,
...
)
重置同意情况
使用 UMP SDK 测试应用时,您可能会发现重置
状态,以便您可以模拟用户的首次安装体验。
为此,SDK 提供了 reset()
方法。
Java
consentInformation.reset();
Kotlin
consentInformation.reset()