Skip to content
webtoapkfree

How do I make external links open in the browser from a WebView app?

To make a WebView open external links in the browser, override shouldOverrideUrlLoading, keep your own domain inside and send other links to an Intent.

GuidesNookesh Karri

Light cover card with the title 'How do I make external links open in the browser from a WebView app?' in dark text and a green accent bar

To make a WebView open external links in the browser, give it a WebViewClient that overrides shouldOverrideUrlLoading. Return false for links on your own domain so they stay in the app, and send every other link to an Intent.ACTION_VIEW (or a Custom Tab), then return true. Handle mailto:, tel: and other non-web schemes in the same method.

A WebView app keeps all links inside because it registered a WebViewClient, and that one line changes the default. The Android WebView guide says that without a client, “Android launches an app that handles URLs”, which is usually the default browser.

Most wrappers set a client so their own pages don’t bounce out to Chrome. The catch is in the same guide: after setWebViewClient, “All links the user taps load in your WebView.” So your privacy policy page, a YouTube link and a payment page all open inside the app.

Outside sites inside your app have no address bar. Users can’t tell where they are.

Each link type needs its own rule, because WebView treats them differently.

Link type Example Where it should go What to return
Your own domain https://yoursite.com/pricing Stay in the WebView false
Another website https://youtube.com/... Browser or Custom Tab true
Email, phone, store mailto:, tel:, market:// Intent to the matching app true
New window target="_blank", window.open() Same rule as its URL depends
Third-party sign-in Google or Facebook login page Browser or Custom Tab true

The last row matters more than it looks. The AdMob WebView guide states that Google Sign-in and Facebook Sign-in aren’t supported in WebView. If your site uses them, see why Google sign-in fails in a WebView app.

Override shouldOverrideUrlLoading(WebView, WebResourceRequest) in your client and compare the link’s host with your own. The WebViewClient reference marks the older String version as deprecated, so use the WebResourceRequest one.

The return value does the work: true stops the WebView from loading the URL, false lets it load.

webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
        val uri = request.url
        val scheme = uri.scheme ?: return false
        if ((scheme == "https" || scheme == "http") && uri.host == "yoursite.com") {
            return false // own site: let the WebView load it
        }
        try {
            view.context.startActivity(Intent(Intent.ACTION_VIEW, uri))
        } catch (e: ActivityNotFoundException) {
            // no app on the phone can open this link
        }
        return true
    }
}

To add it:

  1. Replace yoursite.com with your host. Add www. or subdomains if your site uses them.
  2. Set the client before you call loadUrl for the first page.
  3. Keep the try/catch. A tablet with no phone app can’t open tel: links.
  4. Don’t call loadUrl inside the method. The guide says not to call loadUrl, reload or similar methods from shouldOverrideUrlLoading.

Per the reference, the method isn’t called for pages your app opens with loadUrl(), and it isn’t called for POST requests, such as a form submit.

A mailto: or tel: link fails inside a WebView because WebView only loads web addresses. The usual symptom is a blank page with net::ERR_UNKNOWN_URL_SCHEME, as in this Stack Overflow question about a mailto link.

The code above already handles it. Any scheme that isn’t your own https host goes to Intent.ACTION_VIEW, so the phone opens the mail app, the dialler or the Play Store. The AdMob guide uses the same pattern for market:// links and notes that WebView doesn’t support custom URL schemes.

A target="_blank" link in a WebView doesn’t open a new window by default. The WebView guide says requests to open new windows are ignored, whether from JavaScript or from a link’s target attribute.

According to the WebSettings reference, setSupportMultipleWindows defaults to false. In that state the request is treated as a top-level navigation in the same WebView, so the link still goes through your host check.

Turning multiple windows on means writing onCreateWindow yourself. Leave it off unless your site needs pop-ups, such as a payment window that talks back to its opener.

Browser Intent or Custom Tab?

Both send the user out of your WebView; the difference is how far. A plain ACTION_VIEW Intent switches to the user’s browser app. A Custom Tab opens the page over your app.

The Custom Tabs overview explains that Custom Tabs are powered by the user’s preferred browser and share its state, unlike WebViews. It calls them the better choice when your app sends people to URLs outside your domains. The AdMob guide swaps in a CustomTabsIntent for outside links, which needs the androidx.browser library.

I’d start with the plain Intent. It needs no new dependency, and you can switch to Custom Tabs later without touching your host check.

Test every link type from the table on a real phone, not only in a desktop browser. Check that:

  • your own pages, including redirects to www., stay in the app
  • a link to another site opens the browser, and Back returns to your app
  • mailto: and tel: open the right apps
  • sign-in buttons leave the WebView

The same habit catches other WebView gaps, such as file downloads that silently fail.

A limit of no-code WebView builders

Link handling lives in the app’s native code, so a no-code wrapper decides it for you. Web2Apk’s own guides say it doesn’t guarantee every website works in a WebView, and that external links can behave differently than in Chrome. If your links need custom rules, a no-code builder can’t give you them; a hand-written wrapper or a Trusted Web Activity gives you that control.

Clean link handling also helps at review time. Google Play looks at whether a wrapper adds anything over the website, as covered in why WebView apps get rejected for minimum functionality.

FAQ

Your app set a WebViewClient. Android’s documentation says that once you do, all links the user taps load in your WebView. Override shouldOverrideUrlLoading to send outside links to the browser.

Return true after you start the Intent or Custom Tab, which stops the WebView from loading that URL. Return false for links on your own site so the WebView keeps loading them.

WebView only loads web addresses, so it can’t open a mailto:, tel: or market: link itself. Catch those schemes in shouldOverrideUrlLoading and pass them to an ACTION_VIEW Intent, with a try/catch for ActivityNotFoundException.

WebView ignores new-window requests by default. With multiple-window support off, the link loads as a normal navigation in the same view, so your URL check in shouldOverrideUrlLoading still decides where it goes.

A Custom Tab keeps the user inside your app while using their real browser, including its sign-ins. A full browser Intent is simpler and needs no extra library. Both work for leaving your site.

Sources