The web view APIs for ads makes app signals available to the tags in your CustomTabSession
,
helping to improve monetization for the web publishers that provided the content
and to protect advertisers from spam.
How it works
Communication with the Google Mobile Ads SDK only happens in response to ad events triggered by any of the following:
The Google Mobile Ads SDK facilitates communication by opening a postMessage
channel with the CustomTabsSession
provided by the Android framework.
Prerequisites
- Google Mobile Ads SDK 23.0.0 or higher.
- An existing Chrome Custom Tabs implementation in your mobile app. See Warm-up and pre-fetch: using the Custom Tabs Service .
- Associate your mobile app to a website with Digital Asset Links .
-
Add the following
<meta-data>
tag in yourAndroidManifest.xml
file to bypass the check for theAPPLICATION_ID
. If you miss this step and don't provide the<meta-data>
tag, the Google Mobile Ads SDK throws anIllegalStateException
on app start.<!-- Bypass APPLICATION_ID check for web view APIs for ads --> <meta-data android:name="com.google.android.gms.ads.INTEGRATION_MANAGER" android:value="webview"/>
Implementation
Within your Chrome Custom Tabs implementation, modify the code in the onCustomTabsServiceConnected()
callback. Replace newSession()
with MobileAds.registerCustomTabsSession()
. This establishes a connection with the
postMessage channel to enrich the ad tags with SDK signals. A Digital Asset Link
is needed to connect the postMessage channel. Optionally, you can set the CustomTabsCallback
parameter to listen for Chrome Custom Tab events.
You should still be able to send messages from the CustomTabsSession
received
from the Google Mobile Ads SDK but the port could change when the SDK requests
a new channel that overrides the existing one.
The following code snippet shows how to register a CustomTabsSession
using the
Google Mobile Ads SDK:
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
);
}
};
}