맞춤 탭 최적화 (베타)

광고 수익 창출을 위한 WebView API를 사용하면 CustomTabSession의 태그에서 앱 신호를 사용할 수 있으므로 콘텐츠를 제공한 웹 게시자의 수익 창출을 개선하고 광고주를 스팸으로부터 보호하는 데 도움이 됩니다.

작동 방식

Google 모바일 광고 SDK와의 통신은 다음 중 하나에 의해 트리거된 광고 이벤트에 대한 응답으로만 이루어집니다.

Google 모바일 광고 SDK는 Android 프레임워크에서 제공하는 CustomTabsSession로 postMessage 채널을 열어 통신을 용이하게 합니다.

기본 요건

  • Google 모바일 광고 SDK 23.0.0 이상
  • 모바일 앱의 기존 Chrome 맞춤 탭 구현입니다. 예열 및 미리 가져오기: 맞춤 탭 서비스 사용을 참고하세요.
  • 디지털 애셋 링크를 사용하여 모바일 앱을 웹사이트에 연결합니다.
  • 다음 <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 신호로 광고 태그를 보강할 수 있습니다. postMessage 채널을 연결하려면 디지털 애셋 링크가 필요합니다. 원하는 경우 CustomTabsCallback 매개변수를 설정하여 Chrome 맞춤 탭 이벤트를 수신할 수 있습니다.

Google 모바일 광고 SDK에서 수신한 CustomTabsSession에서 메시지를 계속 전송할 수 있지만 SDK가 기존 채널을 재정의하는 새 채널을 요청하면 포트가 변경될 수 있습니다.

다음 코드 스니펫은 Google 모바일 광고 SDK를 사용하여 CustomTabsSession를 등록하는 방법을 보여줍니다.

KotlinJava
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"
  }
}
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);
    }
  };
}