Android AdMob(三) — GDPR相关处理

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中集成,实现获取用户同意功能。

UMP官方接入文档

在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()回调成功后,可以通过ConsentInformationgetPrivacyOptionsRequirementStatus()方法获取是否需要使用Privacy Options。如果需要的话,通过UserMessagingPlatformshowPrivacyOptionsForm()方法显示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在欧盟或英国区域时的情况和快速撤销同意授权,使用步骤如下:

  1. 获取设备的测试ID。

调用requestConsentInfoUpdate()方法后,在Logcat中过滤tag为UserMessagingPlatform的日志,如下:

  1. 调整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) {
                    ......
                }
            })
    }
}
  1. 在需要时撤销同意授权,代码如下:
kotlin 复制代码
class AdmobExampleActivity : AppCompatActivity() {

    private lateinit var consentInformation: ConsentInformation

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        consentInformation = UserMessagingPlatform.getConsentInformation(this)
        consentInformation.reset()
    }
}

效果演示与示例代码

最终效果如下图:

演示代码已在示例Demo中添加。

ExampleDemo github

ExampleDemo gitee

相关推荐
Devil枫2 小时前
Kotlin高级特性深度解析
android·开发语言·kotlin
ChinaDragonDreamer2 小时前
Kotlin:2.1.20 的新特性
android·开发语言·kotlin
雨白12 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹14 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空16 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭16 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日17 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安17 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑17 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟21 小时前
CTF Web的数组巧用
android