This presents a few example applications using Custom Tabs, and a possible usage of the APIs, both intent-based and the the background service. It covers UI customization, setting up callbacks, pre-warming, pre-fetching, and lifecycle management. Here we assume that Chrome's implementation of Custom Tabs is used. Note that this feature is in no way specific to Chrome, but slight differences may exist with other implementations.
In particular, this covers:
These features are enabled through two mechanisms:
ACTION_VIEW
intent sent to the browser.To get full benefits of the Custom Tabs APIs, it is recommended to use the Android Support Library.
The code in this repository is organised in four parts:
demos/
: This module contains sample implementations for Chrome Custom Tabs using the Android Support Library. Feel free to re-use the classes withing this module.shared/
: Shared code between the Application
and demos
modules. Feel free to re-use the classes within this directory, which are only provided as a convenience. In particular,CustomTabsHelper
can be re-used. This code is not required to use Custom Tabs.customtabs/
: Code within this directory is in the package android.support.customtabs
. This contains code analog to the Android Support library, but with the latest version of Chrome Custom Tabs, enabling features that may still not be available on the Android Support Library. API is subject to changes and this code should only be used if you want to test the latest features. It is recommended to copy the code as-is to your project and remove the Android Support Library for Chrome Custom Tabs from the build.gradle
file.Application/
: Example application code, in the package org.chromium.customtabsclient
. This code uses the latest version of the Chrome Custom Tabs, contained in the module customtabs
.UI customization is done through the methods exposed by CustomTabsIntent.Builder
.
Example:
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); builder.setSession(session); builder.setToolbarColor(Color.BLUE); // Application exit animation, Chrome enter animation. builder.setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left); // vice versa builder.setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right); CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.launchUrl(this, packageName, url);
In this example, no UI customization is done, aside from the animations and the toolbar color. The general usage is:
CustomTabsIntent.Builder
CustomTabsIntent.Builder
CustomTabsIntent.Builder.build()
CustomTabsIntent.launchUrl()
The communication between the custom tab activity and the application is done via pending intents. For each interaction leading back to the application (menu items and action button), a PendingIntent
must be provided, and will be delivered upon activation of the corresponding UI element.
The hosting application can elect to get notifications about navigations in a Custom Tab. This is done using a callback extending android.support.customtabs.CustomTabsCallback
, that is:
void onNavigationEvent(int navigationEvent, Bundle extras);
This callback is set when a CustomTabsSession
object is created, through CustomTabsSession.newSession()
. It thus has to be set:
The two events are analogous to WebViewClient.onPageStarted()
and WebViewClient.onPageFinished()
, respectively (see WebViewClient).
WARNING: The browser treats the calls described in this section only as advice. Actual behavior may depend on connectivity, available memory and other resources.
The application can communicate its intention to the browser, that is:
In both cases, communication with the browser is done through a bound background service. This binding is done by CustomTabClient.bindCustomTabsService()
. After the service is connected, the client has access to a CustomTabsClient
object, valid until the service gets disconnected. This client can be used in these two cases:
CustomTabsClient.warmup()
.CustomTabsClient.warmup()
first. This is triggered by CustomTabsSession.mayLaunchUrl()
.Example:
// Binds to the service. CustomTabsClient.bindCustomTabsService(context, packageName, new CustomTabsServiceConnection() { @Override public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) { // mClient is now valid. mClient = client; } @Override public void onServiceDisconnected(ComponentName name) { // mClient is no longer valid. This also invalidates sessions. mClient = null; } }); // With a valid mClient. mClient.warmup(0); // With a valid mClient. CustomTabsSession session = mClient.newSession(new CustomTabsCallback()); session.mayLaunchUrl(Uri.parse("https://www.google.com"), null, null); // Shows the Custom Tab builder.build().launchUrl(context, packageName, Uri.parse("https://www.google.com"));
Tips
warmup
call in advance to reduce waiting when the custom tab activity is started.