Skip to content Skip to sidebar Skip to footer

How Can I Check Whether Chrome Supports Chrome Custom Tabs?

I have an activity that loads an external url into a webview within my app. I'd like to use Chrome Custom tabs when it's available but I support devices that might not have a versi

Solution 1:

Instead of binding and unbinding the service, you can use the PackageManager to check if Custom Tabs is supported.

privatestaticfinalStringSERVICE_ACTION="android.support.customtabs.action.CustomTabsService";
    privatestaticfinalStringCHROME_PACKAGE="com.android.chrome";

    privatestaticbooleanisChromeCustomTabsSupported(@NonNullfinal Context context) {
        IntentserviceIntent=newIntent(SERVICE_ACTION);
        serviceIntent.setPackage(CHROME_PACKAGE);
        List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentServices(serviceIntent, 0);
        return !(resolveInfos == null || resolveInfos.isEmpty());
    }

Be aware that other browsers may support Custom Tabs in the future, so you may want to modify that to support this case.

Solution 2:

You can try following code to figure out if you have a browser that supports custom tab:

privatestaticfinalStringTAG="CustomTabLauncher";
staticfinalStringSTABLE_PACKAGE="com.android.chrome";
staticfinalStringBETA_PACKAGE="com.chrome.beta";
staticfinalStringDEV_PACKAGE="com.chrome.dev";
staticfinalStringLOCAL_PACKAGE="com.google.android.apps.chrome";
String mPackageNameToUse;

private String getPackageName(Context context) {
    if (mPackageNameToUse != null) {
        return mPackageNameToUse;
    }

    // Get default VIEW intent handler that can view a web url.IntentactivityIntent=newIntent(Intent.ACTION_VIEW, Uri.parse("http://www.test-url.com"));

    // Get all apps that can handle VIEW intents.PackageManagerpm= context.getPackageManager();
    List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
    List<String> packagesSupportingCustomTabs = newArrayList<>();
    for (ResolveInfo info : resolvedActivityList) {
        IntentserviceIntent=newIntent();
        serviceIntent.setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
        serviceIntent.setPackage(info.activityInfo.packageName);
        if (pm.resolveService(serviceIntent, 0) != null) {
            packagesSupportingCustomTabs.add(info.activityInfo.packageName);
        }
    }

    // Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents// and service calls.if (packagesSupportingCustomTabs.isEmpty()) {
        mPackageNameToUse = null;
    } elseif (packagesSupportingCustomTabs.size() == 1) {
        mPackageNameToUse = packagesSupportingCustomTabs.get(0);
    } elseif (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
        mPackageNameToUse = STABLE_PACKAGE;
    } elseif (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
        mPackageNameToUse = BETA_PACKAGE;
    } elseif (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
        mPackageNameToUse = DEV_PACKAGE;
    } elseif (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
        mPackageNameToUse = LOCAL_PACKAGE;
    }
    return mPackageNameToUse;
}

When calling, you can do something like this:

publicvoidopenCustomTab(Uri uri, Activity activity) {
    //If we cant find a package name, it means there's no browser that supports//Chrome Custom Tabs installed. So, we fallback to the default browserif (getPackageName(activity) == null) {
        activity.startActivity(newIntent(Intent.ACTION_VIEW, uri));
    } else {
        CustomTabsIntent.BuilderintentBuilder=newCustomTabsIntent.Builder();
        intentBuilder.enableUrlBarHiding();
        intentBuilder.setToolbarColor(activity.getResources().getColor(R.color.purple_a_01));

        CustomTabsIntentcustomTabsIntent= intentBuilder.build();
        customTabsIntent.intent.setPackage(mPackageNameToUse);

        customTabsIntent.launchUrl(activity, uri);
    }
}

Solution 3:

I ended up writing a static method in my Utils class so I can check and handle the case where it isn't supported:

/**
     * Check if Chrome CustomTabs are supported. 
     * Some devices don't have Chrome or it may not be
     * updated to a version where custom tabs is supported.
     *
     * @param context the context
     * @return whether custom tabs are supported
     */publicstaticbooleanisChromeCustomTabsSupported(@NonNullfinal Context context) {
        IntentserviceIntent=newIntent("android.support.customtabs.action.CustomTabsService");
        serviceIntent.setPackage("com.android.chrome");

        CustomTabsServiceConnectionserviceConnection=newCustomTabsServiceConnection() {
            @OverridepublicvoidonCustomTabsServiceConnected(final ComponentName componentName, final CustomTabsClient customTabsClient) { }

            @OverridepublicvoidonServiceDisconnected(final ComponentName name) { }
        };

        booleancustomTabsSupported=
                context.bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);
        context.unbindService(serviceConnection);

        return customTabsSupported;
    }

Solution 4:

I solved this problem by handling ActivityNotFound exception in catch block.

The trick is to check if the browser activity of chrome can be started or not, if it can't be started or throws an exception then simply open the link through Intent.ACTION_VIEW.

Here is all the relevant code ....

privatevoidonBtnLinkClicked(View v, int pos) {
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            openCustomTab(url);
        } else {
            openBrowserActivity(url);
        }
    } catch (Exception e) {
        e.printStackTrace();
        openBrowserActivity(url);
    }
}

privatevoidopenBrowserActivity(String url) {
    Intent browserIntent = newIntent(Intent.ACTION_VIEW, Uri.parse(url));
    context.startActivity(browserIntent);
}

What is openCustomTab(url) you say : Here is the relevant code for it.

privatevoidopenCustomTab(String url) {
    CustomTabsIntent.BuilderintentBuilder=newCustomTabsIntent.Builder();

    intcolor= context.getResources().getColor(R.color.colorPrimary);
    intentBuilder.setToolbarColor(color);
    intentBuilder.setShowTitle(true);

    StringmenuItemTitle= context.getString(R.string.menu_title_share);
    PendingIntentmenuItemPendingIntent= createPendingShareIntent();
    intentBuilder.addMenuItem(menuItemTitle, menuItemPendingIntent);     

    intentBuilder.setStartAnimations(context,
            R.anim.slide_in_right, R.anim.slide_out_left);
    intentBuilder.setExitAnimations(context,
            android.R.anim.slide_in_left, android.R.anim.slide_out_right);

    CustomTabActivityHelper.openCustomTab(
            activity, intentBuilder.build(), Uri.parse(url), newWebviewFallback());
}

My style of answer may seem cocky but before clicking downvote let me know if you have run into any unexpected bug or any other problem that this approach may have cause. Do give your feedback, we are a community afterall.

Solution 5:

New issues may arise if you are targeting API level 30 and running on an Android 11 device.

You will need to add a section to your manifest, such as:

<queries><intent><actionandroid:name="android.intent.action.VIEW" /><categoryandroid:name="android.intent.category.BROWSABLE" /><dataandroid:scheme="https" /></intent></queries>

OR

<queries><intent><actionandroid:name="android.support.customtabs.action.CustomTabsService" /></intent></queries>

Without this, some of the calls to PackageManager mentioned in the above posts will not work as you expect.

https://developer.android.com/training/package-visibility/use-cases

Post a Comment for "How Can I Check Whether Chrome Supports Chrome Custom Tabs?"