GDPR(General Data Protection Regulation)是欧盟针对数据保护和隐私权的一项法规。旨在加强个人数据保护,并为欧盟居民提供更多对其个人数据的控制权,该法规在2018年5月25日生效。
从2024年1月16日开始,使用AdManager或AdMob的发布者和开发者在向欧盟或英国的用户提供广告前,必须先使用由Google认证并集成了IAB's Transparency and Consent Framework的同意管理平台(CMP)获取用户授权。在获得授权后,才能使用用户信息进行个性化广告投放。
User Messaging Platform(UMP)
针对新的限制条例,Google提供了User Messaging Platform(UMP)SDK,便于开发者在App中集成,实现获取用户同意功能。
在AdMob管理后台创建GDPR消息
- 在AdMob管理后台的隐私权与消息中选择创建GDPR信息。
- 在GDPR消息创建页面中,首先需要选取使用该消息的App。需要注意的是,这里需要填入App使用的隐私政策对应的网址。
- 根据需求调整弹窗样式以及此消息弹窗面向的人群后就可以发布。
添加UMP SDK
在项目app module的build.gradle中的dependencies中添加依赖:
scss
dependencies {
implementation("com.google.android.ump:user-messaging-platform:2.1.0")
}
配置AndroidManifest
设置APPLICATION_ID
AndroidManifest
中的com.google.android.gms.ads.APPLICATION_ID
配置为关联了GDPR消息的APPLICATION_ID。代码如下:
xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
......
>
<!--此id为官方demo的id,可以测试UMP效果-->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713" />
</application>
</manifest>
延迟应用衡量
AdMob会在应用启动时初始化应用衡量并开始上报用户级事件,可以通过在AndroidManifest
中配置<meta-data>
延迟此行为。代码如下:
xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
......
>
<meta-data
android:name="com.google.android.gms.ads.DELAY_APP_MEASUREMENT_INIT"
android:value="true" />
</application>
</manifest>
实现获取用户同意功能
请求同意信息
创建ConsentInformation
对象然后通过requestConsentInfoUpdate()
方法请求同意信息,代码如下:
kotlin
class AdmobExampleActivity : AppCompatActivity() {
private lateinit var binding: LayoutAdmobExampleActivityBinding
private lateinit var consentInformation: ConsentInformation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = LayoutAdmobExampleActivityBinding.inflate(layoutInflater).also {
setContentView(it.root)
}
binding.includeTitle.tvTitle.text = "AdmobExample"
val consentRequestParameters = ConsentRequestParameters.Builder()
// 设置用户不会低于法定年龄
.setTagForUnderAgeOfConsent(false)
.build()
consentInformation = UserMessagingPlatform.getConsentInformation(this)
consentInformation.requestConsentInfoUpdate(
this,
consentRequestParameters,
object : ConsentInformation.OnConsentInfoUpdateSuccessListener {
override fun onConsentInfoUpdateSuccess() {
// 同意信息更新成功
if (consentInformation.isConsentFormAvailable) {
// 同意表单可用,加载并显示表单
} else {
// 同意表单不可用,验证一下是否可以使用广告
if (consentInformation.canRequestAds()) {
// 可以请求广告,开始初始化广告SDK
}
}
}
},
object : ConsentInformation.OnConsentInfoUpdateFailureListener {
override fun onConsentInfoUpdateFailure(formError: FormError) {
// 同意信息更新失败
// 获取错误码
val errorCode = formError.errorCode
// 获取错误信息
val errorMessage = formError.message
// 验证一下是否可以使用广告
if (consentInformation.canRequestAds()) {
// 可以请求广告,开始初始化广告SDK
}
}
})
}
}
获取同意信息可能出现几种情况,需要做出对应的处理,如下:
- 更新信息成功且同意表单可用,此时应该加载并显示表单。
- 更新信息成功但表单不可用,此时应该通过
canRequestAds()
检测是否可以请求广告。 - 更新信息失败,此时也应该通过
canRequestAds()
检测是否可以请求广告。
另外,需要注意的是,为了符合IAB TCF的标准,官方建议在每次运行App时都执行requestConsentInfoUpdate()
方法,避免用户上一次授权的同意信息已经超过13个月导致失效。
加载同意表单并显示。
在成功更新完同意信息后,如果同意表单可用,那么此时应该加载同意表单并显示。代码如下:
kotlin
class AdmobExampleActivity : AppCompatActivity() {
private lateinit var binding: LayoutAdmobExampleActivityBinding
private lateinit var consentInformation: ConsentInformation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = LayoutAdmobExampleActivityBinding.inflate(layoutInflater).also {
setContentView(it.root)
}
binding.includeTitle.tvTitle.text = "AdmobExample"
val consentRequestParameters = ConsentRequestParameters.Builder()
.setTagForUnderAgeOfConsent(false)
.build()
consentInformation = UserMessagingPlatform.getConsentInformation(this)
consentInformation.requestConsentInfoUpdate(
this,
consentRequestParameters,
object : ConsentInformation.OnConsentInfoUpdateSuccessListener {
override fun onConsentInfoUpdateSuccess() {
if (consentInformation.isConsentFormAvailable) {
loadAndShowConsentFormIfRequired()
}
......
}
},
object : ConsentInformation.OnConsentInfoUpdateFailureListener {
override fun onConsentInfoUpdateFailure(formError: FormError) {
......
}
})
}
fun loadAndShowConsentFormIfRequired() {
UserMessagingPlatform.loadAndShowConsentFormIfRequired(this, object : ConsentForm.OnConsentFormDismissedListener {
override fun onConsentFormDismissed(formError: FormError?) {
// 表单加载失败时回调此方法。
// 表单加载完并显示成功,用户操作完表单后回调此方法。
// 验证一下是否可以使用广告
if (consentInformation.canRequestAds()) {
// 可以请求广告,开始初始化广告SDK
}
}
})
}
}
onConsentFormDismissed()
会在表单加载失败或者表单被用户关闭之后(不论用户选择同意或不同意)回调。此时同样应该通过canRequestAds()
检测是否可以请求广告。
允许撤销授权
根据GDPR法规,用户可以随时撤销同意授权,因此需要在App中提供撤销授权功能。UMP为此提供了Privacy Options API,在requestConsentInfoUpdate()
回调成功后,可以通过ConsentInformation
的getPrivacyOptionsRequirementStatus()
方法获取是否需要使用Privacy Options。如果需要的话,通过UserMessagingPlatform
的showPrivacyOptionsForm()
方法显示Privacy Options。代码如下:
kotlin
class AdmobExampleActivity : AppCompatActivity() {
private lateinit var binding: LayoutAdmobExampleActivityBinding
private lateinit var consentInformation: ConsentInformation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = LayoutAdmobExampleActivityBinding.inflate(layoutInflater).also {
setContentView(it.root)
}
binding.includeTitle.tvTitle.text = "AdmobExample"
binding.btnShowPrivacyOptions.setOnClickListener { showPrivacyOptionsForm() }
val consentRequestParameters = ConsentRequestParameters.Builder()
.setTagForUnderAgeOfConsent(false)
.build()
consentInformation = UserMessagingPlatform.getConsentInformation(this)
consentInformation.requestConsentInfoUpdate(
this,
consentRequestParameters,
object : ConsentInformation.OnConsentInfoUpdateSuccessListener {
override fun onConsentInfoUpdateSuccess() {
if (consentInformation.privacyOptionsRequirementStatus == ConsentInformation.PrivacyOptionsRequirementStatus.REQUIRED) {
// 需要显示Privacy Options,显示对应的按钮
binding.btnShowPrivacyOptions.visibility = View.VISIBLE
}
......
}
},
object : ConsentInformation.OnConsentInfoUpdateFailureListener {
override fun onConsentInfoUpdateFailure(formError: FormError) {
......
}
})
}
private fun showPrivacyOptionsForm() {
UserMessagingPlatform.showPrivacyOptionsForm(this, object : ConsentForm.OnConsentFormDismissedListener {
override fun onConsentFormDismissed(formError: FormError?) {
// 表单加载失败时回调此方法。
// 表单加载完并显示成功,用户操作完表单后回调此方法。
}
})
}
}
测试
UMP提供了一些测试方法,可以模拟App在欧盟或英国区域时的情况和快速撤销同意授权,使用步骤如下:
- 获取设备的测试ID。
调用requestConsentInfoUpdate()
方法后,在Logcat中过滤tag为UserMessagingPlatform的日志,如下:
- 调整
ConsentRequestParameters
配置。
在创建ConsentRequestParameters
时设置获取到的TestDeviceHashedId以及地理位置信息,代码如下:
kotlin
class AdmobExampleActivity : AppCompatActivity() {
private lateinit var consentInformation: ConsentInformation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val consentRequestParameters = ConsentRequestParameters.Builder()
.setTagForUnderAgeOfConsent(false)
.setConsentDebugSettings(ConsentDebugSettings.Builder(this)
.setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA)
.addTestDeviceHashedId("9E190127A33E1387D56E000EEF479712")
.build())
.build()
consentInformation.requestConsentInfoUpdate(
this,
consentRequestParameters,
object : ConsentInformation.OnConsentInfoUpdateSuccessListener {
override fun onConsentInfoUpdateSuccess() {
......
}
},
object : ConsentInformation.OnConsentInfoUpdateFailureListener {
override fun onConsentInfoUpdateFailure(formError: FormError) {
......
}
})
}
}
- 在需要时撤销同意授权,代码如下:
kotlin
class AdmobExampleActivity : AppCompatActivity() {
private lateinit var consentInformation: ConsentInformation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
consentInformation = UserMessagingPlatform.getConsentInformation(this)
consentInformation.reset()
}
}
效果演示与示例代码
最终效果如下图:
演示代码已在示例Demo中添加。