WebView component

WebView component allows you to display web content as part of your activity layout, but lack some of the features of fully-developed browsers.

permissions

If you want load content from internet your app must have internet permission. From API 28 by default only https connections are allowed. If you want also http connections, app must have option usesCleartextTraffic in AndroidManifest.xml.

<manifest ...>
   <uses-permission android:name="android.permission.INTERNET" />
   <application
     ...
     android:usesCleartextTraffic="true"
     ...>
         ...
   </application>
</manifest>

loading content

1. The loadUrl() method allows you to load content from a URL. Along with http/https URLs, you can use other. For example:

  • file:// for local files
  • file:///android_asset/ for files in assets
  • content:// for data provided by ContentProvider
  • javascript: to execute js code

2. The loadDataWithBaseURL() method allows you to assign string as content.

webView.loadUrl("https://socode4.com");

val data = "<html><body>Hello, world!</body></html>"

// first parameter base url can be null
// that means "about:blank"     
webView.loadDataWithBaseURL(
      null, data, "text/html", "UTF-8", null)            

// it’s buggy method and work one times, and
// next shows blank page
webView.loadData(data, "text/html", "UTF-8")

settings

WebSettings class manages settings state for a WebView. When a WebView is first created, it obtains a set of default settings. A WebSettings object obtained from WebView.getSettings() is tied to the life of the WebView.

The most useful case is enabling JavaScript.

fun setupWebView(){
    webView.settings.apply {
        javaScriptEnabled = true  
        userAgentString ="MyApp"
        // setSupportZoom(true)
        // builtInZoomControls = true
        // ...
    }
}

WebViewClient

WebViewClient allows you to handle errors and override the default behavior for some events.

For example, you want show pages of "example.com" inside your app, and other links open in external browser.

WebViewClient example
method description
shouldOverrideUrlLoading(webView, request) Return true if you want to cancel the current load, otherwise return false. Do not call WebView.loadUrl() within method, it will cancel the current load and starts a new load with the same URL.
shouldInterceptRequest (webView, request) Allows to return data for requested resource. This is not called for javascript: URLs, blob: URLs, or for assets accessed via file:///android_asset/ or file:///android_res/.
onReceivedError (webView, request, error) Report web resource loading error to the host application. These errors usually indicate inability to connect to the server.
onReceivedHttpAuthRequest (webView, authHandler, host, realm) Notifies the host application that the WebView received an HTTP authentication request. The host application can use the supplied HttpAuthHandler to set the WebView's response to the request. The default behavior is to cancel the request.
onPageStarted (webView, String url, favicon) Notify the host application that a page has started loading.
onPageFinished (webView, url) Notify the host application that a page has finished loading.

WebChromeClient

WebChromeClient allows you to handle Javascript dialogs, favicons, titles, and the progress.

webView.setWebChromeClient(object : WebChromeClient() {
    override fun onShowFileChooser(
            webView: WebView?,
            filePathCallback: ValueCallback<Array<Uri?>?>,
            fileChooserParams: FileChooserParams?
        ): Boolean {
        
        mFilePathCallback?.apply{
            onReceiveValue(null)
        }
        
        mFilePathCallback = filePathCallback       
        showChooserDialog()
        return true
        }
})

JavaScript-Java bridge

The addJavascriptInterface() method injects the supplied Java object into WebView. The object is injected into all frames of the web page, including all the iframes, using the supplied name. This allows the Java object's methods to be accessed from JavaScript.

Obviously, you must enbale js.

Inject JS example

On the other hand, you can execute js code from app. This is usually done after the page has loaded.

Execute js example

back navigation

User expects a history browsing on pressing back button, so you can override onKeyDown() method of activity as follows:

Code example
override fun onKeyDown(keyCode: Int, event: KeyEvent?)
        : Boolean {
    if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
        webView.goBack()
        return true
    }
    
    return super.onKeyDown(keyCode, event)
}