优化自定义标签页(Beta 版)

适用于广告的 WebView API 可让 CustomTabSession 中的代码使用应用信号,从而帮助提供内容的网站发布商提升创收效果,并保护广告客户免受垃圾内容的侵扰。

运作方式

与 Google 移动广告 SDK 的通信仅在响应由以下任一因素触发的广告事件时发生:

Google 移动广告 SDK 通过使用 Android 框架提供的 CustomTabsSession 打开 postMessage 渠道来促进通信。

前提条件

  • Google 移动广告 SDK 23.0.0 或更高版本。
  • 移动应用中现有的 Chrome 自定义标签页实现。请参阅预热和预提取:使用自定义标签页服务
  • 使用 Digital Asset Links 将移动应用与网站相关联。
  • 将以下 <meta-data> 标记添加到 AndroidManifest.xml 文件中,以绕过 APPLICATION_ID 检查。如果您不执行此步骤,并且未提供 <meta-data> 标记,Google 移动广告 SDK 会在应用启动时抛出 IllegalStateException

    <!-- Bypass APPLICATION_ID check for web view APIs for ads -->
     <meta-data
         android:name="com.google.android.gms.ads.INTEGRATION_MANAGER"
         android:value="webview"/>
    

实现

在 Chrome 自定义标签页实现中,修改 onCustomTabsServiceConnected() 回调中的代码。将 newSession() 替换为 MobileAds.registerCustomTabsSession()。这会建立与 postMessage 渠道的连接,以使用 SDK 信号丰富广告代码。需要使用 Digital Asset Link 来连接 postMessage 渠道。您可以选择设置 CustomTabsCallback 参数,以监听 Chrome 自定义标签页事件。

您应该仍然能够发送来自 Google 移动广告 SDK 的 CustomTabsSession 接收到的消息,但当 SDK 请求覆盖现有通道的新通道时,端口可能会发生变化。

以下代码段展示了如何使用 Google 移动广告 SDK 注册 CustomTabsSession

Kotlin

import com.google.android.gms.ads.MobileAds

class MainActivity : ComponentActivity() {
  private var customTabsClient: CustomTabsClient? = null
  private var customTabsSession: CustomTabsSession? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // Get the default browser package name, this will be null if
    // the default browser does not provide a CustomTabsService.
    val packageName = CustomTabsClient.getPackageName(applicationContext, null);
    if (packageName == null) {
      // Do nothing as service connection is not supported.
      return
    }

    CustomTabsClient.bindCustomTabsService(
      applicationContext,
      packageName,
      object : CustomTabsServiceConnection() {
        override fun onCustomTabsServiceConnected(
          name: ComponentName, client: CustomTabsClient,
          ) {
            customTabsClient = client

            // Warm up the browser process.
            customTabsClient?.warmup(0L)
            // Create a new browser session using the Google Mobile Ads SDK.
            customTabsSession = MobileAds.registerCustomTabsSession(
              this@MainActivity.applicationContext,
              client,
              // Checks the "Digital Asset Link" to connect the postMessage channel.
              ORIGIN,
              // Optional parameter to receive the delegated callbacks.
              customTabsCallback
            )

            // Create a new browser session if the Google Mobile Ads SDK is
            // unable to create one.
            if (customTabsSession == null) {
              customTabsSession = client.newSession(customTabsCallback)
            }

            // Pass the custom tabs session into the intent.
            val customTabsIntent = CustomTabsIntent.Builder(customTabsSession).build()
            customTabsIntent.launchUrl(this@MainActivity,
                                      Uri.parse("YOUR_URL"))
          }

          override fun onServiceDisconnected(componentName: ComponentName) {
            // Remove the custom tabs client and custom tabs session.
            customTabsClient = null
            customTabsSession = null
          }
      })
  }

  // Listen for events from the CustomTabsSession delegated by the Google Mobile Ads SDK.
  private val customTabsCallback: CustomTabsCallback = object : CustomTabsCallback() {
    @Synchronized
    override fun onNavigationEvent(navigationEvent: Int, extras: Bundle?) {
      // Called when a navigation event happens.
    }

    @Synchronized
    override fun onMessageChannelReady(extras: Bundle?) {
      // Called when the channel is ready for sending and receiving messages on both
      // ends.
      // This frequently happens, such as each time the SDK requests a
      // new channel.
    }

    @Synchronized
    override fun onPostMessage(message: String, extras: Bundle?) {
      // Called when a tab controlled by this CustomTabsSession has sent a postMessage.
    }

    override fun onRelationshipValidationResult(
      relation: Int, requestedOrigin: Uri, result: Boolean, extras: Bundle?
    ) {
      // Called when a relationship validation result is available.
    }

    override fun onActivityResized(height: Int, width: Int, extras: Bundle) {
      // Called when the tab is resized.
    }

    override fun extraCallback(callbackName: String, args: Bundle?) {

    }

    override fun extraCallbackWithResult(callbackName: String, args: Bundle?): Bundle? {
      return null
    }
  }

  companion object {
    // Replace this URL with an associated website.
    const val ORIGIN = "https://www.google.com"
  }
}

Java

import com.google.android.gms.ads.MobileAds;

class MainActivity extends ComponentActivity {
  // Replace this URL with an associated website.
  private static final String ORIGIN = "https://www.google.com";
  private CustomTabsClient customTabsClient;
  private CustomTabsSession customTabsSession;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Get the default browser package name, this will be null if
    // the default browser does not provide a CustomTabsService.
    String packageName = CustomTabsClient.getPackageName(getApplicationContext(), null);
    if (packageName == null) {
      // Do nothing as service connection is not supported.
      return;
    }

    CustomTabsClient.bindCustomTabsService(
        getApplicationContext(),
        packageName,
        new CustomTabsServiceConnection() {
          @Override
          public void onCustomTabsServiceConnected(@NonNull ComponentName name,
              @NonNull CustomTabsClient client) {
            customTabsClient = client;

            // Warm up the browser process.
            customTabsClient.warmup(0);
            // Create a new browser session using the Google Mobile Ads SDK.
            customTabsSession = MobileAds.registerCustomTabsSession(
                MainActivity.this.getApplicationContext(),
                client,
                // Checks the "Digital Asset Link" to connect the postMessage channel.
                ORIGIN,
                // Optional parameter to receive the delegated callbacks.
                customTabsCallback);

            // Create a new browser session if the Google Mobile Ads SDK is
            // unable to create one.
            if (customTabsSession == null) {
              customTabsSession = client.newSession(customTabsCallback);
            }

            // Pass the custom tabs session into the intent.
            CustomTabsIntent intent = new CustomTabsIntent.Builder(customTabsSession).build();
            intent.launchUrl(MainActivity.this, Uri.parse("YOUR_URL"));
          }

          @Override
          public void onServiceDisconnected(ComponentName componentName) {
            // Remove the custom tabs client and custom tabs session.
            customTabsClient = null;
            customTabsSession = null;
          }
        }

    );
  }

  // Listen for events from the CustomTabsSession delegated by the Google Mobile Ads SDK.
  private final CustomTabsCallback customTabsCallback = new CustomTabsCallback() {
    @Override
    public void onNavigationEvent(int navigationEvent, @Nullable Bundle extras) {
      // Called when a navigation event happens.
      super.onNavigationEvent(navigationEvent, extras);
    }

    @Override
    public void onMessageChannelReady(@Nullable Bundle extras) {
      // Called when the channel is ready for sending and receiving messages on both
      // ends.
      // This frequently happens, such as each time the SDK requests a
      // new channel.
      super.onMessageChannelReady(extras);
    }

    @Override
    public void onPostMessage(@NonNull String message, @Nullable Bundle extras) {
      // Called when a tab controlled by this CustomTabsSession has sent a postMessage.
      super.onPostMessage(message, extras);
    }

    @Override
    public void onRelationshipValidationResult(int relation, @NonNull Uri requestedOrigin,
        boolean result, @Nullable Bundle extras) {
      // Called when a relationship validation result is available.
      super.onRelationshipValidationResult(relation, requestedOrigin, result, extras);
    }

    @Override
    public void onActivityResized(int height, int width, @NonNull Bundle extras) {
      // Called when the tab is resized.
      super.onActivityResized(height, width, extras);
    }

    @Override
    public void extraCallback(@NonNull String callbackName, @Nullable Bundle args) {
      super.extraCallback(callbackName, args);
    }

    @Nullable
    @Override
    public Bundle extraCallbackWithResult(@NonNull String callbackName, @Nullable Bundle args) {
      return super.extraCallbackWithResult(callbackName, args);
    }
  };
}