1

I am trying to add CustomTabIntent on my application to open url of my website. The problem is that I have implemented AppLinking into my application due to which Chrome Tab doesn't appear and it is redirected to my deeplink handler class which redirects my url to chrome.

I have used following code for CustomTabIntent,

CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder()
            .setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary))
            .setSecondaryToolbarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark))
            .setShowTitle(true)
            .addDefaultShareMenuItem()
            .setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left)
            .setExitAnimations(this, android.R.anim.slide_in_left,
                    android.R.anim.slide_out_right);
    CustomTabsIntent customTabsIntent = builder.build();
    customTabsIntent.launchUrl(this, Uri.parse(url));

Is their a way I can bypass applink to open CustomTabIntent?

Kislay Kumar
  • 243
  • 1
  • 2
  • 10

2 Answers2

4

Yes, you can set the package name of the application you want to open by accessing the internal Intent inside the CustomTabsIntent and calling setPackageName.

String packageName = "...";
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder()
        .setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary))
        .setSecondaryToolbarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark))
        .setShowTitle(true)
        .addDefaultShareMenuItem()
        .setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left)
        .setExitAnimations(this, android.R.anim.slide_in_left,
                android.R.anim.slide_out_right);
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.intent.setPackage(packageName);
customTabsIntent.launchUrl(this, Uri.parse(url));

From this point on, you must be wondering how to find out which package name to set when opening the Custom Tab. Even though you could hard-code a package name for a specific browser eg:

customTabsIntent.intent.setPackageName("com.android.chrome");

But, since other browsers such as Firefox and Samsung also support CustomTabs, you will ideally want to find out which ones are installed and use one of those.

The following code can help with that:

public static ArrayList getCustomTabsPackages(Context context) {
    PackageManager pm = context.getPackageManager();
    // Get default VIEW intent handler.
    Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));

    // Get all apps that can handle VIEW intents.
    List resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
    ArrayList packagesSupportingCustomTabs = new ArrayList<>();
    for (ResolveInfo info : resolvedActivityList) {
        Intent serviceIntent = new Intent();
        serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION);
        serviceIntent.setPackage(info.activityInfo.packageName);
        // Check if this package also resolves the Custom Tabs service.
        if (pm.resolveService(serviceIntent, 0) != null) {
            packagesSupportingCustomTabs.add(info);
        }
    }
    return packagesSupportingCustomTabs;
}

It's possible to use this in combination with CustomTabsClient.getPackageName to select a package.

andreban
  • 4,621
  • 1
  • 20
  • 49
0

Thanks to andreban here and there, I wrote the same in Kotlin. Updated thanks to Arghadip.

private fun getCustomTabsPackages(context: Context, url: String): List<ResolveInfo> {
    val pm: PackageManager = context.packageManager
    // Get default VIEW intent handler.
    val activityIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
    // Get all apps that can handle VIEW intents.
    val resolvedActivityList: List<ResolveInfo> = pm.queryIntentActivities(activityIntent, 0)
    return resolvedActivityList.filter {
        val serviceIntent = Intent()
        serviceIntent.action = ACTION_CUSTOM_TABS_CONNECTION
        serviceIntent.setPackage(it.activityInfo.packageName)
        // Check if this package also resolves the Custom Tabs service.
        pm.resolveService(serviceIntent, 0) != null
    }
}

private fun showBrowser(url: String) {
    val customTabsPackages = getCustomTabsPackages(context!!, url)
    if (customTabsPackages.isNullOrEmpty()) {
        openAnyBrowser(url)
    } else {
        // Get the first Chrome-compatible browser from the list.
        val packageName = customTabsPackages.first().activityInfo.packageName
        openChromeTabs(packageName, url)
    }
}

private fun openAnyBrowser(url: String) {
    val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
    if (intent.resolveActivity(context!!.packageManager) != null) {
        startActivity(intent)
    } else {
        showError("Cannot open web browser")
    }
}

private fun openChromeTabs(packageName: String, url: String) {
    val params = CustomTabColorSchemeParams.Builder()
        .setToolbarColor(ContextCompat.getColor(context, R.color.colorPrimary))
        .setSecondaryToolbarColor(ContextCompat.getColor(context, R.color.colorPrimaryDark))
        .setNavigationBarColor(ContextCompat.getColor(context, R.color.colorPrimary))
        .build()
    val builder = CustomTabsIntent.Builder()
        .setColorScheme(CustomTabsIntent.COLOR_SCHEME_DARK)
        .setColorSchemeParams(CustomTabsIntent.COLOR_SCHEME_DARK, params)
        //.setDefaultColorSchemeParams(params)
        .setShowTitle(true)
        .setShareState(SHARE_STATE_DEFAULT)
        .setStartAnimations(context, R.anim.slide_in_right, R.anim.slide_out_left)
        .setExitAnimations(context, android.R.anim.slide_in_left,
            android.R.anim.slide_out_right)
    val customTabsIntent = builder.build()
    customTabsIntent.intent.setPackage(packageName)
    customTabsIntent.launchUrl(context!!, Uri.parse(url))
}

In build.gradle:

// Chrome Custom Tabs.
implementation 'androidx.browser:browser:1.3.0'

In API 30 intent.resolveActivity(context!!.packageManager) returns null, so, in AndroidManifest add these lines, if you want to show other browsers:

<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="http" />
    </intent>
</queries>
CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • 1
    `setToolbarColor` and `setSecondaryToolbarColor` is deprecated, what now? –  Dec 13 '20 at 13:02
  • 1
    @Arghadip, thanks, I saw your topic: https://stackoverflow.com/questions/65275742/android-settoolbarcolorint-and-setsecondarytoolbarcolorint-is-deprecat. – CoolMind Dec 13 '20 at 20:23