开始使用

根据 Google 欧盟地区用户意见征求 政策,您必须 向欧洲经济区 (EEA) 内的用户披露某些信息, 与英国用户签订协议,并就使用 Cookie 或其他本地存储方式征得用户同意; 以及使用个人数据(如 AdID)来投放广告。 此政策反映了欧盟《电子隐私指令》和 一般数据保护条例 (GDPR)。

为了帮助发布商履行此政策规定的职责,Google 提供了 User Messaging Platform (UMP) SDK。UMP SDK 已更新,可支持 最新 IAB 标准现在,所有这些配置 隐私权和 Ad Manager 消息。

前提条件

  • Android API 级别 21 或更高级别

创建消息类型

使用以下任一方式创建用户消息: 可用的用户消息类型 隐私权和消息功能标签页 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()。有两个 在征求用户意见时应检查以下事项:

  1. 在当前会话中收集用户意见后。
  2. 致电 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()
      }
      
    }
  }
}

隐私设置选项

有些用户意见征求表单会要求用户随时修改同意情况。遵守 按照以下步骤,根据需要实现隐私权选项按钮。

要实现这一目标,需要完成以下步骤:

  1. 实现界面元素,例如应用的设置页面中的按钮; 可触发隐私权选项表单的应用
  2. loadAndShowConsentFormIfRequired() 完成后,请检查 privacyOptionsRequirementStatus() 来确定是否展示 可显示隐私选项表单的界面元素。
  3. 当用户与界面元素交互时,调用 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。

  1. 致电 requestConsentInfoUpdate()
  2. 检查日志输出是否包含类似于以下示例的消息, 显示了您的设备 ID 以及如何将其添加为测试设备:

    Use new ConsentDebugSettings.Builder().addTestDeviceHashedId("33BE2250B43518CCDA7DE426D04EE231") to set this as a debug device.
    
  3. 将测试设备 ID 复制到剪贴板。

  4. 将代码修改为 致电 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()

GitHub 上的示例

UMP SDK 集成示例: Java | Kotlin