前提条件
简介
根据 Google 欧盟地区用户意见征求政策,您必须向位于欧洲经济区 (EEA) 和英国境内的用户披露相关信息,并在法律要求的情况下,就使用 Cookie 或其他本地存储方式征得用户同意,以及使用个人数据(例如 AdID)来投放广告。此政策反映了欧盟《电子隐私指令》和《一般数据保护条例》(GDPR) 的要求。
为了帮助发布商履行此政策规定的职责,Google 提供了 User Messaging Platform (UMP) SDK,该 SDK 取代了之前的开源 Consent SDK。UMP SDK 已更新,可支持最新的 IAB 标准。此外,我们还简化了设置用户意见征求表单和列出广告合作伙伴的流程。所有这些配置现在都可以方便地在AdMob 的“隐私权和消息”中进行处理。
最佳做法是每次用户启动您的应用时都加载表单,即使您确定不需要征求用户同意,也可以让表单在用户想要更改用户意见征求设置时显示。
本指南将向您介绍如何安装 SDK、实现 IAB 解决方案以及启用测试功能。
使用 Gradle 进行安装
将该库添加到您的应用的 build.gradle 中:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.google.android.ump:user-messaging-platform:2.0.0'
}
完成后,别忘了同步 Gradle。
将应用 ID 添加到“ AndroidManifest.xml”
按照帮助中心的说明获取应用 ID。
将应用 ID 添加到您的 AndroidManifest.xml中:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rewardedinterstitialexample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="YOUR-APP-ID"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
使用 SDK
SDK 以线性方式使用。使用 SDK 的步骤如下:
- 请求最新的用户意见征求信息。
- 检查是否需要征得用户同意。
- 检查表单是否可用,如果可用,则加载表单。
- 呈现表单。
- 为用户提供更改同意声明的方式。
请求最新的用户意见征求信息
建议您在每次应用启动时请求更新用户意见征求信息。这将决定您的用户是否需要提供同意声明。
Java
import android.os.Bundle; import com.google.android.ump.ConsentForm; 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; private ConsentForm consentForm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Set tag for underage of consent. Here false means users are not underage. ConsentRequestParameters params = new ConsentRequestParameters .Builder() .setTagForUnderAgeOfConsent(false) .build(); consentInformation = UserMessagingPlatform.getConsentInformation(this); consentInformation.requestConsentInfoUpdate( this, params, new ConsentInformation.OnConsentInfoUpdateSuccessListener() { @Override public void onConsentInfoUpdateSuccess() { // The consent information state was updated. // You are now ready to check if a form is available. } }, new ConsentInformation.OnConsentInfoUpdateFailureListener() { @Override public void onConsentInfoUpdateFailure(FormError formError) { // Handle the error. } }); } }
Kotlin
import android.os.Bundle import com.google.android.ump.* class MainActivity : AppCompactActivity() { private lateinit var consentInformation: ConsentInformation private var consentForm: ConsentForm? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Set tag for underage of consent. Here false means users are not underage. val params = ConsentRequestParameters.Builder() .setTagForUnderAgeOfConsent(false) .build() consentInformation = UserMessagingPlatform.getConsentInformation(this) consentInformation.requestConsentInfoUpdate( this, params, { // The consent information state was updated. // You are now ready to check if a form is available. }, { formError -> // Handle the error. } ) } }
加载表单(如有)
确定您要征求用户同意后,下一步是确定是否有表单可供使用。
有很多原因会导致表单无法使用,例如:
- 用户启用了受限的广告跟踪。
- 您已将用户标记为未达到同意年龄。
如需检查表单是否可用,请对 ConsentInformation
实例使用 isConsentFormAvailable()
方法。添加用于加载表单的封装容器方法:
Java
... consentInformation.requestConsentInfoUpdate( this, params, new ConsentInformation.OnConsentInfoUpdateSuccessListener() { @Override public void onConsentInfoUpdateSuccess() { // The consent information state was updated. // You are now ready to check if a form is available. if (consentInformation.isConsentFormAvailable()) { loadForm(); } } }, new ConsentInformation.OnConsentInfoUpdateFailureListener() { @Override public void onConsentInfoUpdateFailure(FormError formError) { // Handle the error. } }); } public void loadForm() { }
Kotlin
... consentInformation.requestConsentInfoUpdate( this, params, { // The consent information state was updated. // You are now ready to check if a form is available. if (consentInformation.isConsentFormAvailable) { loadForm() } }, { formError -> // Handle the error. } ) } private fun loadForm() { }
如需加载表单,请对 UserMessagingPlatform
类使用静态 loadConsentForm()
方法。只能从主线程调用此方法。按如下方式更改 loadForm()
方法:
Java
public void loadForm() { UserMessagingPlatform.loadConsentForm( this, new UserMessagingPlatform.OnConsentFormLoadSuccessListener() { @Override public void onConsentFormLoadSuccess(ConsentForm consentForm) { MainActivity.this.consentForm = consentForm; } }, new UserMessagingPlatform.OnConsentFormLoadFailureListener() { @Override public void onConsentFormLoadFailure(FormError formError) { // Handle the error. } }); }
Kotlin
private fun loadForm() { UserMessagingPlatform.loadConsentForm( this, { consentForm -> this.consentForm = consentForm }, { formError -> // Handle the error. } ) }
根据需要呈现表单
如需呈现表单,请在 ConsentForm
实例上使用 show()
方法。在提交表单之前,您应该确定是否需要用户同意。如需检查是否需要征得用户同意,请检查 ConsentInformation
对象的 getConsentStatus()
方法,该方法会返回 ConsentInformation.ConsentStatus
类型的枚举。有四种可能的值:
ConsentStatus.UNKNOWN
:意见征求状态未知。ConsentStatus.REQUIRED
:需要用户同意,但尚未获得。ConsentStatus.NOT_REQUIRED
:不需要用户同意。例如,用户不在欧洲经济区 (EEA) 或英国。ConsentStatus.OBTAINED
:已征得用户同意。未定义个性化设置。
按如下方式更改 loadForm()
方法:
Java
public void loadForm() { UserMessagingPlatform.loadConsentForm( this, new UserMessagingPlatform.OnConsentFormLoadSuccessListener() { @Override public void onConsentFormLoadSuccess(ConsentForm consentForm) { MainActivity.this.consentForm = consentForm; if (consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.REQUIRED) { consentForm.show( MainActivity.this, new ConsentForm.OnConsentFormDismissedListener() { @Override public void onConsentFormDismissed(@Nullable FormError formError) { // Handle dismissal by reloading form. loadForm(); } }); } } }, new UserMessagingPlatform.OnConsentFormLoadFailureListener() { @Override public void onConsentFormLoadFailure(FormError formError) { // Handle the error. } }); }
Kotlin
private fun loadForm() { UserMessagingPlatform.loadConsentForm( this, { consentForm -> this.consentForm = consentForm if (consentInformation.consentStatus == ConsentInformation.ConsentStatus.REQUIRED) { consentForm.show(this) { formError -> // Handle dismissal by reloading form. loadForm() } } }, { formError -> // Handle the error. } ) }
如果不需要征求用户同意,您可以保留对表单的引用,以便用户更改其同意状态。
测试
强制使用地理位置
UMP SDK 提供了一种方法来测试应用的行为,就好像设备位于 EEA 并使用 ConsentDebugSettings.Builder
上的 setDebugGeography()
方法。
您需要在应用的调试设置中提供测试设备的经过哈希处理的 ID,才能使用调试功能。如果您调用 requestConsentInfoUpdate()
而不设置此值,您的应用会在运行时记录所需的 ID 哈希。
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); consentInformation.requestConsentInfoUpdate( this, params, new ConsentInformation.OnConsentInfoUpdateSuccessListener() { @Override public void onConsentInfoUpdateSuccess() { // The consent information state was updated. // You are now ready to check if a form is available. } }, new ConsentInformation.OnConsentInfoUpdateFailureListener() { @Override public void onConsentInfoUpdateFailure(FormError formError) { // Handle the error. } });
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) consentInformation.requestConsentInfoUpdate( this, params, { // The consent information state was updated. // You are now ready to check if a form is available. }, { formError -> // Handle the error. } )
如需强制 SDK 将设备视为不在 EEA 或英国境内,请使用 DebugGeography.DEBUG_GEOGRAPHY_NOT_EEA
。请注意,调试设置仅适用于测试设备。模拟器无需添加到设备 ID 列表中,因为它们在默认情况下启用了测试。
重置用户意见征求状态
使用 UMP SDK 测试应用时,重置 SDK 的状态可能会有所帮助,以便您模拟用户的首次安装体验。SDK 提供了 reset
方法来执行此操作。
Java
consentInformation.reset();
Kotlin
consentInformation.reset()
延迟应用衡量(可选)
默认情况下,Google 移动广告 SDK 会初始化应用衡量并在应用启动时立即开始向 Google 发送用户级事件数据。 此初始化行为可确保您可以启用 AdMob 用户指标,而无需更改额外的代码。
但是,如果您的应用需要在征求用户意见后才能发送这些事件,则可以延迟应用衡量,直到显式初始化移动广告 SDK 或加载广告为止。
如需延迟应用衡量,请在 AndroidManifest.xml
中添加以下 <meta-data>
标记。
<manifest> <application> <!-- Delay app measurement until MobileAds.initialize() is called. --> <meta-data android:name="com.google.android.gms.ads.DELAY_APP_MEASUREMENT_INIT" android:value="true"/> </application> </manifest>
中介
如果您使用中介功能,则需要根据您选择在应用中使用的意见征求框架,为中介合作伙伴处理意见征求方式。Google 支持 IAB 用户意见征求框架,但也允许您拥有自己的自定义用户意见征求解决方案。下面将详细介绍如何在每个选项下处理中介。 详细了解我们的用户意见征求解决方案。
IAB 用户意见征求框架和中介
UMP SDK 和移动广告 SDK 都不会将用户意见征求信息转发给中介合作伙伴。相反,使用 IAB 解决方案时,UMP SDK 会将用户意见征求状态信息写入本地存储空间,并且每个中介合作伙伴的 SDK 均负责读取相应的密钥。请务必咨询每个第三方广告联盟,以确定其是否支持 IAB 解决方案。
自定义用户意见征求解决方案和中介
如果使用自定义用户意见征求解决方案,您有责任通知第三方 SDK 您的应用是否会征得用户同意。如需详细了解如何向相关第三方传递意见征求信息,请参阅每个中介合作伙伴的集成指南,了解实现详情。
将用户意见转发给 Google 移动广告 SDK
本節中的程式碼可與任何 Google Mobile Ads SDK 版本搭配使用。無論您是否使用 Consent SDK 收集同意聲明,也可以使用這個屬性。
Google Mobile Ads SDK 的預設行為是放送個人化廣告。
如果使用者同意只接收非個人化廣告,您可以設定 AdRequest
物件,指定只應請求非個人化廣告。下列程式碼用於請求非個人化廣告,無論使用者是否位於歐洲經濟區都一樣:
Java
Bundle extras = new Bundle(); extras.putString("npa", "1"); AdRequest request = new AdRequest.Builder() .addNetworkExtrasBundle(AdMobAdapter.class, extras) .build();
Kotlin
val extras = Bundle() extras.putString("npa", "1") val request = AdRequest.Builder() .addNetworkExtrasBundle(AdMobAdapter::class.java, extras) .build()
如果請求非個人化廣告,廣告請求目前包含 &npa=1
。不過請注意,這是 Google Mobile Ads SDK 的內部導入詳細資料,隨時可能變更。