blob: 3af72306e99b6f8494301587309aecd24f09b0a7 [file] [log] [blame]
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.browser.customtabs;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.util.SparseArray;
import android.view.View;
import android.widget.RemoteViews;
import androidx.annotation.AnimRes;
import androidx.annotation.ColorInt;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.app.BundleCompat;
import androidx.core.content.ContextCompat;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
/**
* Class holding the {@link Intent} and start bundle for a Custom Tabs Activity.
*
* <p>
* <strong>Note:</strong> The constants below are public for the browser implementation's benefit.
* You are strongly encouraged to use {@link CustomTabsIntent.Builder}.</p>
*/
public final class CustomTabsIntent {
/**
* Indicates that the user explicitly opted out of Custom Tabs in the calling application.
* <p>
* If an application provides a mechanism for users to opt out of Custom Tabs, this extra should
* be provided with {@link Intent#FLAG_ACTIVITY_NEW_TASK} to ensure the browser does not attempt
* to trigger any Custom Tab-like experiences as a result of the VIEW intent.
* <p>
* If this extra is present with {@link Intent#FLAG_ACTIVITY_NEW_TASK}, all Custom Tabs
* customizations will be ignored.
*/
private static final String EXTRA_USER_OPT_OUT_FROM_CUSTOM_TABS =
"android.support.customtabs.extra.user_opt_out";
/**
* Extra used to match the session. This has to be included in the intent to open in
* a custom tab. This is the same IBinder that gets passed to ICustomTabsService#newSession.
* Null if there is no need to match any service side sessions with the intent.
*/
public static final String EXTRA_SESSION = "android.support.customtabs.extra.SESSION";
/**
* Extra used to match the session ID. This is PendingIntent which is created with
* {@link CustomTabsClient#createSessionId}.
*
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
public static final String EXTRA_SESSION_ID = "android.support.customtabs.extra.SESSION_ID";
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
@IntDef({COLOR_SCHEME_SYSTEM, COLOR_SCHEME_LIGHT, COLOR_SCHEME_DARK})
@Retention(RetentionPolicy.SOURCE)
public @interface ColorScheme {
}
/**
* Applies either a light or dark color scheme to the user interface in the custom tab depending
* on the user's system settings.
*/
public static final int COLOR_SCHEME_SYSTEM = 0;
/**
* Applies a light color scheme to the user interface in the custom tab.
*/
public static final int COLOR_SCHEME_LIGHT = 1;
/**
* Applies a dark color scheme to the user interface in the custom tab. Colors set through
* {@link #EXTRA_TOOLBAR_COLOR} may be darkened to match user expectations.
*/
public static final int COLOR_SCHEME_DARK = 2;
/**
* Maximum value for the COLOR_SCHEME_* configuration options. For validation purposes only.
*/
private static final int COLOR_SCHEME_MAX = 2;
/**
* Extra (int) that specifies which color scheme should be applied to the custom tab. Default is
* {@link #COLOR_SCHEME_SYSTEM}.
*/
public static final String EXTRA_COLOR_SCHEME =
"androidx.browser.customtabs.extra.COLOR_SCHEME";
/**
* Extra that changes the background color for the toolbar. colorRes is an int that specifies a
* {@link Color}, not a resource id.
*/
public static final String EXTRA_TOOLBAR_COLOR =
"android.support.customtabs.extra.TOOLBAR_COLOR";
/**
* Boolean extra that enables the url bar to hide as the user scrolls down the page
*/
public static final String EXTRA_ENABLE_URLBAR_HIDING =
"android.support.customtabs.extra.ENABLE_URLBAR_HIDING";
/**
* Extra bitmap that specifies the icon of the back button on the toolbar. If the client chooses
* not to customize it, a default close button will be used.
*/
public static final String EXTRA_CLOSE_BUTTON_ICON =
"android.support.customtabs.extra.CLOSE_BUTTON_ICON";
/**
* Extra (int) that specifies state for showing the page title. Default is {@link #NO_TITLE}.
*/
public static final String EXTRA_TITLE_VISIBILITY_STATE =
"android.support.customtabs.extra.TITLE_VISIBILITY";
/**
* Don't show any title. Shows only the domain.
*/
public static final int NO_TITLE = 0;
/**
* Shows the page title and the domain.
*/
public static final int SHOW_PAGE_TITLE = 1;
/**
* Bundle used for adding a custom action button to the custom tab toolbar. The client should
* provide a description, an icon {@link Bitmap} and a {@link PendingIntent} for the button.
* All three keys must be present.
*/
public static final String EXTRA_ACTION_BUTTON_BUNDLE =
"android.support.customtabs.extra.ACTION_BUTTON_BUNDLE";
/**
* List<Bundle> used for adding items to the top and bottom toolbars. The client should
* provide an ID, a description, an icon {@link Bitmap} for each item. They may also provide a
* {@link PendingIntent} if the item is a button.
*/
public static final String EXTRA_TOOLBAR_ITEMS =
"android.support.customtabs.extra.TOOLBAR_ITEMS";
/**
* Extra that changes the background color for the secondary toolbar. The value should be an
* int that specifies a {@link Color}, not a resource id.
*/
public static final String EXTRA_SECONDARY_TOOLBAR_COLOR =
"android.support.customtabs.extra.SECONDARY_TOOLBAR_COLOR";
/**
* Key that specifies the {@link Bitmap} to be used as the image source for the action button.
* The icon should't be more than 24dp in height (No padding needed. The button itself will be
* 48dp in height) and have a width/height ratio of less than 2.
*/
public static final String KEY_ICON = "android.support.customtabs.customaction.ICON";
/**
* Key that specifies the content description for the custom action button.
*/
public static final String KEY_DESCRIPTION =
"android.support.customtabs.customaction.DESCRIPTION";
/**
* Key that specifies the PendingIntent to launch when the action button or menu item was
* clicked. The custom tab will be calling {@link PendingIntent#send()} on clicks after adding
* the url as data. The client app can call {@link Intent#getDataString()} to get the url.
*/
public static final String KEY_PENDING_INTENT =
"android.support.customtabs.customaction.PENDING_INTENT";
/**
* Extra boolean that specifies whether the custom action button should be tinted. Default is
* false and the action button will not be tinted.
*/
public static final String EXTRA_TINT_ACTION_BUTTON =
"android.support.customtabs.extra.TINT_ACTION_BUTTON";
/**
* Use an {@code ArrayList<Bundle>} for specifying menu related params. There should be a
* separate {@link Bundle} for each custom menu item.
*/
public static final String EXTRA_MENU_ITEMS = "android.support.customtabs.extra.MENU_ITEMS";
/**
* Key for specifying the title of a menu item.
*/
public static final String KEY_MENU_ITEM_TITLE =
"android.support.customtabs.customaction.MENU_ITEM_TITLE";
/**
* Bundle constructed out of {@link ActivityOptionsCompat} that will be running when the
* {@link Activity} that holds the custom tab gets finished. A similar ActivityOptions
* for creation should be constructed and given to the startActivity() call that
* launches the custom tab.
*/
public static final String EXTRA_EXIT_ANIMATION_BUNDLE =
"android.support.customtabs.extra.EXIT_ANIMATION_BUNDLE";
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
@IntDef({SHARE_STATE_DEFAULT, SHARE_STATE_ON, SHARE_STATE_OFF})
@Retention(RetentionPolicy.SOURCE)
public @interface ShareState {
}
/**
* Applies the default share settings depending on the browser.
*/
public static final int SHARE_STATE_DEFAULT = 0;
/**
* Shows a share option in the tab.
*/
public static final int SHARE_STATE_ON = 1;
/**
* Explicitly does not show a share option in the tab.
*/
public static final int SHARE_STATE_OFF = 2;
/**
* Maximum value for the SHARE_STATE_* configuration options. For validation purposes only.
*/
private static final int SHARE_STATE_MAX = 2;
/**
* Extra (int) that specifies which share state should be applied to the custom tab. Default is
* {@link CustomTabsIntent#SHARE_STATE_DEFAULT}.
*/
public static final String EXTRA_SHARE_STATE = "androidx.browser.customtabs.extra.SHARE_STATE";
/**
* Boolean extra that specifies whether a default share button will be shown in the menu.
*
* @deprecated Use {@link CustomTabsIntent#EXTRA_SHARE_STATE} instead.
*/
@Deprecated
public static final String EXTRA_DEFAULT_SHARE_MENU_ITEM =
"android.support.customtabs.extra.SHARE_MENU_ITEM";
/**
* Extra that specifies the {@link RemoteViews} showing on the secondary toolbar. If this extra
* is set, the other secondary toolbar configurations will be overriden. The height of the
* {@link RemoteViews} should not exceed 56dp.
* @see CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
*/
public static final String EXTRA_REMOTEVIEWS =
"android.support.customtabs.extra.EXTRA_REMOTEVIEWS";
/**
* Extra that specifies an array of {@link View} ids. When these {@link View}s are clicked, a
* {@link PendingIntent} will be sent, carrying the current url of the custom tab as data.
* <p>
* Note that Custom Tabs will override the default onClick behavior of the listed {@link View}s.
* If you do not care about the current url, you can safely ignore this extra and use
* {@link RemoteViews#setOnClickPendingIntent(int, PendingIntent)} instead.
* @see CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
*/
public static final String EXTRA_REMOTEVIEWS_VIEW_IDS =
"android.support.customtabs.extra.EXTRA_REMOTEVIEWS_VIEW_IDS";
/**
* Extra that specifies the {@link PendingIntent} to be sent when the user clicks on the
* {@link View}s that is listed by {@link #EXTRA_REMOTEVIEWS_VIEW_IDS}.
* <p>
* Note when this {@link PendingIntent} is triggered, it will have the current url as data
* field, also the id of the clicked {@link View}, specified by
* {@link #EXTRA_REMOTEVIEWS_CLICKED_ID}.
* @see CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
*/
public static final String EXTRA_REMOTEVIEWS_PENDINGINTENT =
"android.support.customtabs.extra.EXTRA_REMOTEVIEWS_PENDINGINTENT";
/**
* Extra that specifies which {@link View} has been clicked. This extra will be put to the
* {@link PendingIntent} sent from Custom Tabs when a view in the {@link RemoteViews} is clicked
* @see CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
*/
public static final String EXTRA_REMOTEVIEWS_CLICKED_ID =
"android.support.customtabs.extra.EXTRA_REMOTEVIEWS_CLICKED_ID";
/**
* Extra that specifies whether Instant Apps is enabled.
*/
public static final String EXTRA_ENABLE_INSTANT_APPS =
"android.support.customtabs.extra.EXTRA_ENABLE_INSTANT_APPS";
/**
* Extra that contains a SparseArray, mapping color schemes (except
* {@link CustomTabsIntent#COLOR_SCHEME_SYSTEM}) to {@link Bundle} representing
* {@link CustomTabColorSchemeParams}.
*/
public static final String EXTRA_COLOR_SCHEME_PARAMS =
"androidx.browser.customtabs.extra.COLOR_SCHEME_PARAMS";
/**
* Extra that contains the color of the navigation bar.
* See {@link Builder#setNavigationBarColor}.
*/
public static final String EXTRA_NAVIGATION_BAR_COLOR =
"androidx.browser.customtabs.extra.NAVIGATION_BAR_COLOR";
/**
* Extra that contains the color of the navigation bar divider.
* See {@link Builder#setNavigationBarDividerColor}.
*/
public static final String EXTRA_NAVIGATION_BAR_DIVIDER_COLOR =
"androidx.browser.customtabs.extra.NAVIGATION_BAR_DIVIDER_COLOR";
/**
* Key that specifies the unique ID for an action button. To make a button to show on the
* toolbar, use {@link #TOOLBAR_ACTION_BUTTON_ID} as its ID.
*/
public static final String KEY_ID = "android.support.customtabs.customaction.ID";
/**
* The ID allocated to the custom action button that is shown on the toolbar.
*/
public static final int TOOLBAR_ACTION_BUTTON_ID = 0;
/**
* The maximum allowed number of toolbar items.
*/
private static final int MAX_TOOLBAR_ITEMS = 5;
/**
* An {@link Intent} used to start the Custom Tabs Activity.
*/
@NonNull public final Intent intent;
/**
* A {@link Bundle} containing the start animation for the Custom Tabs Activity.
*/
@Nullable public final Bundle startAnimationBundle;
/**
* Convenience method to launch a Custom Tabs Activity.
* @param context The source Context.
* @param url The URL to load in the Custom Tab.
*/
public void launchUrl(@NonNull Context context, @NonNull Uri url) {
intent.setData(url);
ContextCompat.startActivity(context, intent, startAnimationBundle);
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
CustomTabsIntent(@NonNull Intent intent, @Nullable Bundle startAnimationBundle) {
this.intent = intent;
this.startAnimationBundle = startAnimationBundle;
}
/**
* Builder class for {@link CustomTabsIntent} objects.
*/
public static final class Builder {
private final Intent mIntent = new Intent(Intent.ACTION_VIEW);
private final CustomTabColorSchemeParams.Builder mDefaultColorSchemeBuilder =
new CustomTabColorSchemeParams.Builder();
@Nullable private ArrayList<Bundle> mMenuItems;
@Nullable private Bundle mStartAnimationBundle;
@Nullable private ArrayList<Bundle> mActionButtons;
@Nullable private SparseArray<Bundle> mColorSchemeParamBundles;
@Nullable private Bundle mDefaultColorSchemeBundle;
@ShareState private int mShareState = SHARE_STATE_DEFAULT;
private boolean mInstantAppsEnabled = true;
/**
* Creates a {@link CustomTabsIntent.Builder} object associated with no
* {@link CustomTabsSession}.
*/
public Builder() {}
/**
* Creates a {@link CustomTabsIntent.Builder} object associated with a given
* {@link CustomTabsSession}.
*
* Guarantees that the {@link Intent} will be sent to the same component as the one the
* session is associated with.
*
* @param session The session to associate this Builder with.
*/
public Builder(@Nullable CustomTabsSession session) {
if (session != null) {
setSession(session);
}
}
/**
* Associates the {@link Intent} with the given {@link CustomTabsSession}.
*
* Guarantees that the {@link Intent} will be sent to the same component as the one the
* session is associated with.
*/
@NonNull
public Builder setSession(@NonNull CustomTabsSession session) {
mIntent.setPackage(session.getComponentName().getPackageName());
setSessionParameters(session.getBinder(), session.getId());
return this;
}
/**
* Associates the {@link Intent} with the given {@link CustomTabsSession.PendingSession}.
* Overrides the effect of {@link #setSession}.
*
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
@NonNull
public Builder setPendingSession(@NonNull CustomTabsSession.PendingSession session) {
setSessionParameters(null, session.getId());
return this;
}
private void setSessionParameters(@Nullable IBinder binder,
@Nullable PendingIntent sessionId) {
Bundle bundle = new Bundle();
BundleCompat.putBinder(bundle, EXTRA_SESSION, binder);
if (sessionId != null) {
bundle.putParcelable(EXTRA_SESSION_ID, sessionId);
}
mIntent.putExtras(bundle);
}
/**
* Sets the toolbar color.
*
* On Android L and above, this color is also applied to the status bar. To ensure good
* contrast between status bar icons and the background, Custom Tab implementations may use
* {@link View#SYSTEM_UI_FLAG_LIGHT_STATUS_BAR} on Android M and above, and use a darkened
* color for the status bar on Android L.
*
* Can be overridden for particular color schemes, see {@link #setColorSchemeParams}.
*
* @param color {@link Color}
*
* @deprecated Use {@link #setDefaultColorSchemeParams} instead.
*/
@Deprecated
@NonNull
public Builder setToolbarColor(@ColorInt int color) {
mDefaultColorSchemeBuilder.setToolbarColor(color);
return this;
}
/**
* Enables the url bar to hide as the user scrolls down on the page.
* @deprecated Use {@link #setUrlBarHidingEnabled(boolean)} instead.
*/
@Deprecated
@NonNull
public Builder enableUrlBarHiding() {
mIntent.putExtra(EXTRA_ENABLE_URLBAR_HIDING, true);
return this;
}
/**
* Set whether the url bar should hide as the user scrolls down on the page.
*
* @param enabled Whether url bar hiding is enabled.
*/
@NonNull
public Builder setUrlBarHidingEnabled(boolean enabled) {
mIntent.putExtra(EXTRA_ENABLE_URLBAR_HIDING, enabled);
return this;
}
/**
* Sets the Close button icon for the custom tab.
*
* @param icon The icon {@link Bitmap}
*/
@NonNull
public Builder setCloseButtonIcon(@NonNull Bitmap icon) {
mIntent.putExtra(EXTRA_CLOSE_BUTTON_ICON, icon);
return this;
}
/**
* Sets whether the title should be shown in the custom tab.
*
* @param showTitle Whether the title should be shown.
*/
@NonNull
public Builder setShowTitle(boolean showTitle) {
mIntent.putExtra(EXTRA_TITLE_VISIBILITY_STATE,
showTitle ? SHOW_PAGE_TITLE : NO_TITLE);
return this;
}
/**
* Adds a menu item.
*
* @param label Menu label.
* @param pendingIntent Pending intent delivered when the menu item is clicked.
*/
@NonNull
public Builder addMenuItem(@NonNull String label, @NonNull PendingIntent pendingIntent) {
if (mMenuItems == null) mMenuItems = new ArrayList<>();
Bundle bundle = new Bundle();
bundle.putString(KEY_MENU_ITEM_TITLE, label);
bundle.putParcelable(KEY_PENDING_INTENT, pendingIntent);
mMenuItems.add(bundle);
return this;
}
/**
* Adds a default share item to the menu.
* @deprecated Use {@link #setShareState(int)} instead. This will set the share state to
* {@link CustomTabsIntent#SHARE_STATE_ON}.
*/
@Deprecated
@NonNull
public Builder addDefaultShareMenuItem() {
setShareState(SHARE_STATE_ON);
return this;
}
/**
* Set whether a default share item is added to the menu.
*
* @param enabled Whether default share item is added.
* @deprecated Use {@link #setShareState(int)} instead. This will set the share state to
* {@link CustomTabsIntent#SHARE_STATE_ON} or {@link CustomTabsIntent#SHARE_STATE_OFF}
* based on {@code enabled}.
*/
@Deprecated
@NonNull
public Builder setDefaultShareMenuItemEnabled(boolean enabled) {
if (enabled) {
setShareState(SHARE_STATE_ON);
} else {
setShareState(SHARE_STATE_OFF);
}
return this;
}
/**
* Sets the share state that should be applied to the custom tab.
*
* @param shareState Desired share state.
*
* @see CustomTabsIntent#SHARE_STATE_DEFAULT
* @see CustomTabsIntent#SHARE_STATE_ON
* @see CustomTabsIntent#SHARE_STATE_OFF
*/
@NonNull
public Builder setShareState(@ShareState int shareState) {
if (shareState < 0 || shareState > SHARE_STATE_MAX) {
throw new IllegalArgumentException("Invalid value for the shareState argument");
}
mShareState = shareState;
// Add share menu item extra for backwards compatibility with {@link
// #addDefaultShareMenuItem} and {@link #setDefaultShareMenuItemEnabled}.
if (shareState == SHARE_STATE_ON) {
mIntent.putExtra(EXTRA_DEFAULT_SHARE_MENU_ITEM, true);
} else if (shareState == SHARE_STATE_OFF) {
mIntent.putExtra(EXTRA_DEFAULT_SHARE_MENU_ITEM, false);
} else {
mIntent.removeExtra(EXTRA_DEFAULT_SHARE_MENU_ITEM);
}
return this;
}
/**
* Sets the action button that is displayed in the Toolbar.
* <p>
* This is equivalent to calling
* {@link CustomTabsIntent.Builder#addToolbarItem(int, Bitmap, String, PendingIntent)}
* with {@link #TOOLBAR_ACTION_BUTTON_ID} as id.
*
* @param icon The icon.
* @param description The description for the button. To be used for accessibility.
* @param pendingIntent pending intent delivered when the button is clicked.
* @param shouldTint Whether the action button should be tinted..
*
* @see CustomTabsIntent.Builder#addToolbarItem(int, Bitmap, String, PendingIntent)
*/
@NonNull
public Builder setActionButton(@NonNull Bitmap icon, @NonNull String description,
@NonNull PendingIntent pendingIntent, boolean shouldTint) {
Bundle bundle = new Bundle();
bundle.putInt(KEY_ID, TOOLBAR_ACTION_BUTTON_ID);
bundle.putParcelable(KEY_ICON, icon);
bundle.putString(KEY_DESCRIPTION, description);
bundle.putParcelable(KEY_PENDING_INTENT, pendingIntent);
mIntent.putExtra(EXTRA_ACTION_BUTTON_BUNDLE, bundle);
mIntent.putExtra(EXTRA_TINT_ACTION_BUTTON, shouldTint);
return this;
}
/**
* Sets the action button that is displayed in the Toolbar with default tinting behavior.
*
* @see CustomTabsIntent.Builder#setActionButton(
* Bitmap, String, PendingIntent, boolean)
*/
@NonNull
public Builder setActionButton(@NonNull Bitmap icon, @NonNull String description,
@NonNull PendingIntent pendingIntent) {
return setActionButton(icon, description, pendingIntent, false);
}
/**
* Adds an action button to the custom tab. Multiple buttons can be added via this method.
* If the given id equals {@link #TOOLBAR_ACTION_BUTTON_ID}, the button will be placed on
* the toolbar; if the bitmap is too wide, it will be put to the bottom bar instead. If
* the id is not {@link #TOOLBAR_ACTION_BUTTON_ID}, it will be directly put on secondary
* toolbar. The maximum number of allowed toolbar items in a single intent is
* {@link CustomTabsIntent#getMaxToolbarItems()}. Throws an
* {@link IllegalStateException} when that number is exceeded per intent.
*
* @param id The unique id of the action button. This should be non-negative.
* @param icon The icon.
* @param description The description for the button. To be used for accessibility.
* @param pendingIntent The pending intent delivered when the button is clicked.
*
* @see CustomTabsIntent#getMaxToolbarItems()
* @deprecated Use
* CustomTabsIntent.Builder#setSecondaryToolbarViews(RemoteViews, int[], PendingIntent).
*/
@Deprecated
@NonNull
public Builder addToolbarItem(int id, @NonNull Bitmap icon, @NonNull String description,
@NonNull PendingIntent pendingIntent) throws IllegalStateException {
if (mActionButtons == null) {
mActionButtons = new ArrayList<>();
}
if (mActionButtons.size() >= MAX_TOOLBAR_ITEMS) {
throw new IllegalStateException(
"Exceeded maximum toolbar item count of " + MAX_TOOLBAR_ITEMS);
}
Bundle bundle = new Bundle();
bundle.putInt(KEY_ID, id);
bundle.putParcelable(KEY_ICON, icon);
bundle.putString(KEY_DESCRIPTION, description);
bundle.putParcelable(KEY_PENDING_INTENT, pendingIntent);
mActionButtons.add(bundle);
return this;
}
/**
* Sets the color of the secondary toolbar.
* Can be overridden for particular color schemes, see {@link #setColorSchemeParams}.
*
* @param color The color for the secondary toolbar.
*
* @deprecated Use {@link #setDefaultColorSchemeParams} instead.
*/
@Deprecated
@NonNull
public Builder setSecondaryToolbarColor(@ColorInt int color) {
mDefaultColorSchemeBuilder.setSecondaryToolbarColor(color);
return this;
}
/**
* Sets the navigation bar color. Has no effect on API versions below L.
*
* To ensure good contrast between navigation bar icons and the background, Custom Tab
* implementations may use {@link View#SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR} on Android O and
* above, and darken the provided color on Android L-N.
*
* Can be overridden for particular color schemes, see {@link #setColorSchemeParams}.
*
* @param color The color for the navigation bar.
*
* @deprecated Use {@link #setDefaultColorSchemeParams} instead.
*/
@Deprecated
@NonNull
public Builder setNavigationBarColor(@ColorInt int color) {
mDefaultColorSchemeBuilder.setNavigationBarColor(color);
return this;
}
/**
* Sets the navigation bar divider color. Has no effect on API versions below P.
*
* Can be overridden for particular color schemes, see {@link #setColorSchemeParams}.
*
* @param color The color for the navigation bar divider.
*
* @deprecated Use {@link #setDefaultColorSchemeParams} instead.
*/
@Deprecated
@NonNull
public Builder setNavigationBarDividerColor(@ColorInt int color) {
mDefaultColorSchemeBuilder.setNavigationBarDividerColor(color);
return this;
}
/**
* Sets the remote views displayed in the secondary toolbar in a custom tab.
*
* @param remoteViews The {@link RemoteViews} that will be shown on the secondary toolbar.
* @param clickableIDs The IDs of clickable views. The onClick event of these views will be
* handled by custom tabs.
* @param pendingIntent The {@link PendingIntent} that will be sent when the user clicks on
* one of the {@link View}s in clickableIDs. When the
* {@link PendingIntent} is sent, it will have the current URL as its
* intent data.
* @see CustomTabsIntent#EXTRA_REMOTEVIEWS
* @see CustomTabsIntent#EXTRA_REMOTEVIEWS_VIEW_IDS
* @see CustomTabsIntent#EXTRA_REMOTEVIEWS_PENDINGINTENT
* @see CustomTabsIntent#EXTRA_REMOTEVIEWS_CLICKED_ID
*/
@NonNull
public Builder setSecondaryToolbarViews(@NonNull RemoteViews remoteViews,
@Nullable int[] clickableIDs, @Nullable PendingIntent pendingIntent) {
mIntent.putExtra(EXTRA_REMOTEVIEWS, remoteViews);
mIntent.putExtra(EXTRA_REMOTEVIEWS_VIEW_IDS, clickableIDs);
mIntent.putExtra(EXTRA_REMOTEVIEWS_PENDINGINTENT, pendingIntent);
return this;
}
/**
* Sets whether Instant Apps is enabled for this Custom Tab.
* @param enabled Whether Instant Apps should be enabled.
*/
@NonNull
public Builder setInstantAppsEnabled(boolean enabled) {
mInstantAppsEnabled = enabled;
return this;
}
/**
* Sets the start animations.
*
* @param context Application context.
* @param enterResId Resource ID of the "enter" animation for the browser.
* @param exitResId Resource ID of the "exit" animation for the application.
*/
@NonNull
@SuppressWarnings("NullAway") // TODO: b/141869399
public Builder setStartAnimations(
@NonNull Context context, @AnimRes int enterResId, @AnimRes int exitResId) {
mStartAnimationBundle = ActivityOptionsCompat.makeCustomAnimation(
context, enterResId, exitResId).toBundle();
return this;
}
/**
* Sets the exit animations.
*
* @param context Application context.
* @param enterResId Resource ID of the "enter" animation for the application.
* @param exitResId Resource ID of the "exit" animation for the browser.
*/
@NonNull
public Builder setExitAnimations(
@NonNull Context context, @AnimRes int enterResId, @AnimRes int exitResId) {
Bundle bundle = ActivityOptionsCompat.makeCustomAnimation(
context, enterResId, exitResId).toBundle();
mIntent.putExtra(EXTRA_EXIT_ANIMATION_BUNDLE, bundle);
return this;
}
/**
* Sets the color scheme that should be applied to the user interface in the custom tab.
*
* @param colorScheme Desired color scheme.
* @see CustomTabsIntent#COLOR_SCHEME_SYSTEM
* @see CustomTabsIntent#COLOR_SCHEME_LIGHT
* @see CustomTabsIntent#COLOR_SCHEME_DARK
*/
@NonNull
public Builder setColorScheme(@ColorScheme int colorScheme) {
if (colorScheme < 0 || colorScheme > COLOR_SCHEME_MAX) {
throw new IllegalArgumentException("Invalid value for the colorScheme argument");
}
mIntent.putExtra(EXTRA_COLOR_SCHEME, colorScheme);
return this;
}
/**
* Sets {@link CustomTabColorSchemeParams} for the given color scheme.
*
* This allows specifying two different toolbar colors for light and dark schemes.
* It can be useful if {@link CustomTabsIntent#COLOR_SCHEME_SYSTEM} is set: Custom Tabs
* will follow the system settings and apply the corresponding
* {@link CustomTabColorSchemeParams} "on the fly" when the settings change.
*
* If there is no {@link CustomTabColorSchemeParams} for the current scheme, or a particular
* field of it is null, Custom Tabs will fall back to the defaults provided via
* {@link #setDefaultColorSchemeParams}.
*
* Example:
* <pre><code>
* CustomTabColorSchemeParams darkParams = new CustomTabColorSchemeParams.Builder()
* .setToolbarColor(darkColor)
* .build();
* CustomTabColorSchemeParams otherParams = new CustomTabColorSchemeParams.Builder()
* .setNavigationBarColor(otherColor)
* .build();
* CustomTabIntent intent = new CustomTabIntent.Builder()
* .setColorScheme(COLOR_SCHEME_SYSTEM)
* .setColorSchemeParams(COLOR_SCHEME_DARK, darkParams)
* .setDefaultColorSchemeParams(otherParams)
* .build();
* </code></pre>
*
* @param colorScheme A constant representing a color scheme (see {@link #setColorScheme}).
* It should not be {@link #COLOR_SCHEME_SYSTEM}, because that represents
* a behavior rather than a particular color scheme.
* @param params An instance of {@link CustomTabColorSchemeParams}.
*/
@NonNull
public Builder setColorSchemeParams(@ColorScheme int colorScheme,
@NonNull CustomTabColorSchemeParams params) {
if (colorScheme < 0 || colorScheme > COLOR_SCHEME_MAX
|| colorScheme == COLOR_SCHEME_SYSTEM) {
throw new IllegalArgumentException("Invalid colorScheme: " + colorScheme);
}
if (mColorSchemeParamBundles == null) {
mColorSchemeParamBundles = new SparseArray<>();
}
mColorSchemeParamBundles.put(colorScheme, params.toBundle());
return this;
}
/**
* Sets the default {@link CustomTabColorSchemeParams}.
*
* This will set a default color scheme that applies when no CustomTabColorSchemeParams
* specified for current color scheme via {@link #setColorSchemeParams}.
*
* @param params An instance of {@link CustomTabColorSchemeParams}.
*/
@NonNull
public Builder setDefaultColorSchemeParams(@NonNull CustomTabColorSchemeParams params) {
mDefaultColorSchemeBundle = params.toBundle();
return this;
}
/**
* Combines all the options that have been set and returns a new {@link CustomTabsIntent}
* object.
*/
@NonNull
public CustomTabsIntent build() {
if (!mIntent.hasExtra(EXTRA_SESSION)) {
// The intent must have EXTRA_SESSION, even if it is null.
setSessionParameters(null, null);
}
if (mMenuItems != null) {
mIntent.putParcelableArrayListExtra(CustomTabsIntent.EXTRA_MENU_ITEMS, mMenuItems);
}
if (mActionButtons != null) {
mIntent.putParcelableArrayListExtra(EXTRA_TOOLBAR_ITEMS, mActionButtons);
}
mIntent.putExtra(EXTRA_ENABLE_INSTANT_APPS, mInstantAppsEnabled);
mIntent.putExtras(mDefaultColorSchemeBuilder.build().toBundle());
if (mDefaultColorSchemeBundle != null) {
mIntent.putExtras(mDefaultColorSchemeBundle);
}
if (mColorSchemeParamBundles != null) {
Bundle bundle = new Bundle();
bundle.putSparseParcelableArray(EXTRA_COLOR_SCHEME_PARAMS,
mColorSchemeParamBundles);
mIntent.putExtras(bundle);
}
mIntent.putExtra(EXTRA_SHARE_STATE, mShareState);
return new CustomTabsIntent(mIntent, mStartAnimationBundle);
}
}
/**
* @return The maximum number of allowed toolbar items for
* {@link CustomTabsIntent.Builder#addToolbarItem(int, Bitmap, String, PendingIntent)} and
* {@link CustomTabsIntent#EXTRA_TOOLBAR_ITEMS}.
*/
public static int getMaxToolbarItems() {
return MAX_TOOLBAR_ITEMS;
}
/**
* Adds the necessary flags and extras to signal any browser supporting custom tabs to use the
* browser UI at all times and avoid showing custom tab like UI. Calling this with an intent
* will override any custom tabs related customizations.
* @param intent The intent to modify for always showing browser UI.
* @return The same intent with the necessary flags and extras added.
*/
@NonNull
public static Intent setAlwaysUseBrowserUI(@Nullable Intent intent) {
if (intent == null) intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(EXTRA_USER_OPT_OUT_FROM_CUSTOM_TABS, true);
return intent;
}
/**
* Whether a browser receiving the given intent should always use browser UI and avoid using any
* custom tabs UI.
*
* @param intent The intent to check for the required flags and extras.
* @return Whether the browser UI should be used exclusively.
*/
public static boolean shouldAlwaysUseBrowserUI(@NonNull Intent intent) {
return intent.getBooleanExtra(EXTRA_USER_OPT_OUT_FROM_CUSTOM_TABS, false)
&& (intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0;
}
/**
* Retrieves the instance of {@link CustomTabColorSchemeParams} from an Intent for a given
* color scheme. Uses values passed directly into {@link CustomTabsIntent.Builder} (e.g. via
* {@link Builder#setToolbarColor}) as defaults.
*
* @param intent Intent to retrieve the color scheme parameters from.
* @param colorScheme A constant representing a color scheme. Should not be
* {@link #COLOR_SCHEME_SYSTEM}.
* @return An instance of {@link CustomTabColorSchemeParams} with retrieved parameters.
*/
@NonNull
public static CustomTabColorSchemeParams getColorSchemeParams(@NonNull Intent intent,
@ColorScheme int colorScheme) {
if (colorScheme < 0 || colorScheme > COLOR_SCHEME_MAX
|| colorScheme == COLOR_SCHEME_SYSTEM) {
throw new IllegalArgumentException("Invalid colorScheme: " + colorScheme);
}
Bundle extras = intent.getExtras();
if (extras == null) {
return CustomTabColorSchemeParams.fromBundle(null);
}
CustomTabColorSchemeParams defaults = CustomTabColorSchemeParams.fromBundle(extras);
SparseArray<Bundle> paramBundles = extras.getSparseParcelableArray(
EXTRA_COLOR_SCHEME_PARAMS);
if (paramBundles != null) {
Bundle bundleForScheme = paramBundles.get(colorScheme);
if (bundleForScheme != null) {
return CustomTabColorSchemeParams.fromBundle(bundleForScheme)
.withDefaults(defaults);
}
}
return defaults;
}
}