Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

A secure Android WebView wrapper starts by limiting what the WebView can load, keeping JavaScript and native bridges off unless the app genuinely needs them, and serving packaged files through AndroidX WebKit’s WebViewAssetLoader. Treat the page origin and every navigation as part of your app’s security boundary—not as ordinary UI configuration.

Choose what the WebView is allowed to trust

Before writing Kotlin, decide what content the wrapper will display. The safest design is app-owned content; if remote pages are necessary, use a short, explicit HTTPS host allowlist. Send other destinations to the user’s browser or block them. Android advises against allowing users to navigate a WebView beyond the app’s control, and recommends allowlists in its WebView security checklist.

Content and capabilities Recommended design
Packaged app content that does not need JavaScript Load it with WebViewAssetLoader; leave JavaScript disabled and do not add a native bridge.
App-owned content that requires JavaScript Enable JavaScript only for that WebView, keep its navigation restricted to app-owned content, and omit the bridge unless a specific native capability is essential.
Remote pages on a small set of controlled sites Require HTTPS and exact approved hosts. Decide deliberately whether subdomains are allowed; do not treat a hostname suffix check as an exact-host check.
Arbitrary or user-selected web pages Prefer the default browser. Do not load them in a WebView that has a JavaScript interface or other privileged app integration.

A WebView renders web content, so page scripts and frames can create web security risks inside the app. A JavaScript bridge can also expose host-app operations to that content. The boundary must therefore account for frames and redirects, not just the first URL the app loads.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep WebView settings minimal

JavaScript is disabled by default. Leave it off for static pages; enable it only when the content requires it. Android’s security checklist notes that JavaScript is off by default and advises against enabling it when unnecessary.

For a wrapper that does not intentionally expose local files to web content, configure file access and mixed content conservatively. Android’s in-app content guidance recommends setting file-URL access flags to false for the strongest security. Avoid MIXED_CONTENT_ALWAYS_ALLOW; keep content on HTTPS and choose the restrictive mixed-content mode appropriate to the app.

webView.settings.apply {
    javaScriptEnabled = false // Set true only if this content needs it.
    allowFileAccess = false
    allowContentAccess = false
    allowFileAccessFromFileURLs = false
    allowUniversalAccessFromFileURLs = false
    mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW
}

These settings are a starting point, not a substitute for testing the content your app actually loads. If a feature needs file selection or another local-content capability, implement that feature narrowly instead of broadly relaxing WebView access.

Serve packaged assets through WebViewAssetLoader

For HTML, CSS, JavaScript, and other files bundled with the app, AndroidX WebKit’s WebViewAssetLoader provides HTTP(S)-style URLs that work with same-origin behavior. Android calls it a flexible and performant way to load in-app content in its local-content guide. Prefer it to file:// URLs; when supplying HTML directly, use an appropriate base URL with loadDataWithBaseURL() rather than relying on a data: URL.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
val assetLoader = WebViewAssetLoader.Builder()
    .addPathHandler(
        "/assets/",
        WebViewAssetLoader.AssetsPathHandler(this)
    )
    .build()

webView.webViewClient = object : WebViewClient() {
    override fun shouldInterceptRequest(
        view: WebView,
        request: WebResourceRequest
    ): WebResourceResponse? {
        return assetLoader.shouldInterceptRequest(request.url)
    }
}

webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")

Use the AndroidX WebKit dependency and imports that match the version selected for your project; verify the API against that version. The asset loader is intended to be used through shouldInterceptRequest. That callback runs on a thread other than the app’s main thread, so do not access or modify views there, and do not use it to expose private app data.

Validate every WebView navigation

Allow only the HTTPS scheme and exact hosts the app intends to display. A trusted starting URL is not enough: redirects and later page navigations can lead elsewhere. Keep foreign HTTPS destinations in the external browser, and reject other schemes unless the app has a specific, safely handled use for them. Do not assume that a navigation check also secures every resource or frame loaded by a page.

This example keeps the app-assets origin inside the WebView, allows one example remote host, sends other HTTPS destinations to the default browser, and blocks non-HTTPS destinations. Replace the example host with a host your app controls. If you have no remote content, remove that allowance.

private val inWebViewHosts = setOf(
    "appassets.androidplatform.net",
    "content.example.org"
)

private fun isAllowedInWebView(uri: Uri): Boolean {
    val host = uri.host?.lowercase(Locale.ROOT) ?: return false
    return uri.scheme.equals("https", ignoreCase = true) &&
        host in inWebViewHosts
}

webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView,
        request: WebResourceRequest
    ): Boolean {
        val uri = request.url
        if (isAllowedInWebView(uri)) return false

        // Do not hand unknown schemes to another app implicitly.
        if (!uri.scheme.equals("https", ignoreCase = true)) return true

        return try {
            view.context.startActivity(
                Intent(Intent.ACTION_VIEW, uri)
            )
            true
        } catch (_: ActivityNotFoundException) {
            true
        }
    }
}

The example uses exact host matching. If the app needs subdomains, enumerate the allowed hosts or define and test an explicit subdomain rule; a broad suffix match can mistakenly accept a different hostname. Also validate the URL the app loads initially. Navigation callbacks are not a reason to load an untrusted start URL and hope it will be caught later.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Block cleartext traffic at the app level as well as checking URLs in code. Configure the manifest or a network security configuration for the app’s supported Android versions, then test the effective behavior on those versions. URL checks in the WebView do not replace a cleartext policy.

Omit the JavaScript bridge unless it is essential

If page content does not need native app functions, do not install a bridge. Android warns that addJavascriptInterface() exposes the supplied object to every frame, including iframes, and provides no way to verify the calling frame’s origin. Its WebView guide puts the rule plainly: “Therefore, don’t use addJavascriptInterface() unless you wrote all of the HTML and JavaScript that appears in your WebView.”

If a bridge is unavoidable, keep it narrow: expose only the specific, low-risk operations needed by app-owned content. Do not use it to hand page code secrets or shortcuts to sensitive, permissioned actions. Keep untrusted pages out of that WebView, and remove the interface before loading any untrusted content. Where relevant, explain the native action to the user and keep the sensitive decision in app code.

Message channels are not automatically safe alternatives. Set an expected target origin instead of *, validate incoming messages and their allowed operations, and do not accept messages from unexpected senders.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Handle file selection without widening access

A file picker does not make the selected source trustworthy. If the app supports WebView file selection, keep the feature limited to the files the page needs, validate how the app handles returned URIs, and avoid making app-private files available to page scripts. Android’s unsafe file inclusion guidance explains the risks of broad file access and untrusted local content. Do not turn on broad file-origin permissions to make a picker or local page work.

Test the wrapper’s trust boundaries

WebView behavior depends on the Android version, target SDK, AndroidX WebKit version, and WebView provider installed on a device. Test the actual combinations relevant to your app rather than assuming one device proves the wrapper is secure.

  • Verify the minimum supported Android version and the target SDK configurations you ship.
  • Test the WebView provider versions present in your deployment population.
  • Check that approved HTTPS pages stay in the WebView and unapproved hosts do not.
  • Test redirects, links clicked after load, iframe content, and non-HTTPS or custom-scheme links.
  • If using a bridge or message channel, test calls from every frame and reject unexpected origins, senders, and message shapes.
  • Confirm packaged assets load through the asset-loader URL and that the interception callback does not touch UI state or expose private data.
  • Check that cleartext requests fail under the app’s manifest or network security configuration.

Android’s guidance describes the security principles and APIs, but does not establish a universal version-by-version test matrix. The app’s own content, navigation paths, and supported devices determine what must be exercised.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.