獲得用戶消息平台的同意

前提条件

阅读 IAB 要求对欧盟地区用户意见征求消息有何影响

简介

根据 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 的步骤如下:

  1. 请求最新的用户意见征求信息。
  2. 检查是否需要征得用户同意。
  3. 检查表单是否可用,如果可用,则加载表单。
  4. 呈现表单。
  5. 为用户提供更改同意声明的方式。

建议您在每次应用启动时请求更新用户意见征求信息。这将决定您的用户是否需要提供同意声明。

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 用户意见征求框架,但也允许您拥有自己的自定义用户意见征求解决方案。下面将详细介绍如何在每个选项下处理中介。 详细了解我们的用户意见征求解决方案

UMP SDK 和移动广告 SDK 都不会将用户意见征求信息转发给中介合作伙伴。相反,使用 IAB 解决方案时,UMP SDK 会将用户意见征求状态信息写入本地存储空间,并且每个中介合作伙伴的 SDK 均负责读取相应的密钥。请务必咨询每个第三方广告联盟,以确定其是否支持 IAB 解决方案。

如果使用自定义用户意见征求解决方案,您有责任通知第三方 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 的內部導入詳細資料,隨時可能變更。