6

I have an Android/Kotlin application and I would like to configure deep links for certain pages to open inside my application (to look native).

At the moment, I have intent filters that redirect the user to an activity with WebView in which I open the desired url:

<activity android:name=".activity.WebViewActivity">
        <intent-filter android:label="Futurity">
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />

            <data
                android:host="api.example.com"
                android:pathPrefix="/auth/confirm"
                android:scheme="https" />
        </intent-filter>
</activity>

class WebViewActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_web_view)

        val data = intent.data

        // construct url
        val url = if (intent.data != null ) {
            "https://" + data.host + data.path + "?" + data.query
        }

        appWebView.webViewClient = WebViewClient()
        appWebView.loadUrl(url)
    }
}

This works fine, but I would like to use Chrome custom tabs instead for security reasons.

However, when I try to configure the custom tab instead of WebView, I am getting an infinite loop of redirects between the page (launched in the chrome tab) and the intent filter which immediately redirects user back to the activity:

CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(this, Uri.parse(url));

How can I achieve the same behavior as with webviews but without modifying the url? Is it even doable?

Smajl
  • 7,555
  • 29
  • 108
  • 179
  • I'm curious about something similar. If I have Instagram or Twitter installed on the device and try to have Chrome Tabs load a Instagram or Twitter url it opens the Native app instead of inside the Chrome Tab. It seems like once you hand off the url to Chrome Tabs it still sends an Intent with ACTION_VIEW will allows other apps a chance to open it. It would really be nice if there was an option to force a url to open in Chrome Tab only. – blinkmacalahan Apr 25 '18 at 21:46
  • I tried that and it looks like the behavior is not well defined. Some browsers (like Chrome) send a new intent, some browsers (like Firefox) stay within custom tabs. – friedger Aug 30 '18 at 09:16
  • How did you solve it? – paulokhouri Jul 09 '20 at 17:54
  • If you can seek an alternative domain that routes to the same point, I would suggest to use that. Specifying a package name isn't reliable as it will trigger the infinite loop again if the default browser is changed – 6rchid Sep 10 '22 at 07:59

1 Answers1

1

I did some digging and found out that you should search for packages that support the "warming services". If a package is returned then you can assign the package name to the Intent. Google has a GitHub repo with some helper classes. The one in question is CustomTabHelper#getPackageNameToUse().

So in your case:

CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
String packageName = CustomTabsHelper.getPackageNameToUse(getContext());

if (packageName != null) {
    customTabsIntent.intent.setPackage(packageName);
}
customTabsIntent.launchUrl(this, Uri.parse(url));

If a package is not found then you'll want to have some fallback code else the infinite loop will keep happening.

blinkmacalahan
  • 499
  • 5
  • 18