Customize WebView Using Kotlin With Example

This is 2nd part of our tutorial on WebView. In this post, we will learn about how to customize webView using Kotlin with Example. For example,

  • Enabling Javascript in WebView
  • Enable Built-in Zoom
  • Prevent Uploading Usage data to Google
  • Block Malicious URL
  • Using WebViewClient class
  • Using WebChromeClient class
  • Using WebSettings
  • Injecting Java Objects into WebView

Getting Started

As we have already seen, in previous post, how to use webView to –

  • load custom html into webView
  • load local file into webView
  • load webpage of given url into webView

We are assuming that you have checked out our previous post. So, moving ahead with next concepts in webView –

Note: We are assuming that we have loaded a webpage of given URL into webView. So, all concepts in this tutorial will be covered accordingly. However, similar concepts applies everywhere.

When you visit a webpage, webView automatically accumulates history of visited pages. However, webView has provided some methods using which we can navigate back and forth between visited pages. We can do so as shown below. Open MainActivity file and add below code into it –

override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {

	val webView = binding.webView

	// Check if the key event was the Back button and if there's history
	if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
		webView.goBack()
		return true
	}

	// Check if the key event was the forward button and if there's history
	if (keyCode == KeyEvent.KEYCODE_FORWARD && webView.canGoForward()) {
		webView.goForward()
		return true
	}

	// If it wasn't the Back key or there's no web page history, bubble up to the default
	// system behavior (probably exit the activity)
	return super.onKeyDown(keyCode, event)
}

Here,

  • canGoBack(): Returns true if there is back history. Otherwise, returns false.
  • goBack(): Redirects to previously visited page.
  • canGoForward(): Returns true if there is forward history. Otherwise, returns false.
  • goForward(): Redirects to previously visited page (but in forward direction).

Prevent Uploading Usage Data to Google

Whenever you use webView in application, it uploads some anonymous data to google. These data are used to improve this webView widget. If you do not want to let webView to upload data to google, you need to add meta-data in < application > element in manifest file.

<manifest>
     <application>
         ...
         <meta-data android:name="android.webkit.WebView.MetricsOptOut"
             android:value="true" />
     </application>
 </manifest>

Note – Data is uploaded to google only if user has given permission and app has not opted out.

Block Malicious URL

While using webView, if you want to block malicious url and show a warning UI to either navigate back or proceed to malicious url, you need to add below meta-data in < application > element in manifest file.

<manifest>
     <application>
         ...
         <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
             android:value="false" />
     </application>
</manifest>

Using WebViewClient class

Now, we will use WebViewClient class to customize WebView using Kotlin with example. we can use this class when you want to deal with content rendering in the page. For example, error or form submission in the page.

Whenever you change something in webView that impacts content rendering, then, it is called. For Example, Showing Error message in Form Submission etc. Follow steps below –

  • Create a new class file (with name WebViewClt.kt), subclassed form WebViewClient, in main/java/com.tutorialwing.webview folder. Then, add below code into it.
    package com.tutorialwing.webview
    
    import android.app.Activity
    import android.content.Intent
    import android.graphics.Bitmap
    import android.net.Uri
    import android.webkit.WebResourceError
    import android.webkit.WebResourceRequest
    import android.webkit.WebView
    import android.webkit.WebViewClient
    import android.widget.Toast
    
    class WebViewClt(private val activity: Activity) : WebViewClient() {
    
    	// Give the host application a chance to take control
    	// when a URL is about to be loaded in the current WebView.
    	// If a WebViewClient is not provided, by default WebView will ask
    	// Activity Manager to choose the proper handler for the URL.
    	// If a WebViewClient is provided, returning true causes
    	// the current WebView to abort loading the URL,
    	// while returning false causes the WebView to continue loading the URL as usual.
    	override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
    		val url: String = request?.url.toString()
    
    		if (containsDefaultURL(url))
    			return false
    
    		// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
    		Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {
    			activity.startActivity(this)
    		}
    
    		return true
    	}
    
    	override fun onReceivedError(
    		view: WebView,
    		request: WebResourceRequest,
    		error: WebResourceError
    	) {
    		Toast.makeText(activity, "Got Error! $error", Toast.LENGTH_SHORT).show()
    	}
    
    	override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
    
    		// Do some activity which you want to do when page loading is started
    		Toast.makeText(activity, "Page loading is started", Toast.LENGTH_SHORT).show()
    
    		super.onPageStarted(view, url, favicon)
    	}
    
    	override fun onPageFinished(view: WebView?, url: String?) {
    
    		// Do some activity which you want to do when page loading is finished
    		Toast.makeText(activity, "Page loading is finished", Toast.LENGTH_SHORT).show()
    
    		super.onPageFinished(view, url)
    	}
    
    	private fun containsDefaultURL(
    		url: String,
    		defaultURL: String = "https://tutorialwing.com"
    	): Boolean {
    		return url.contains(defaultURL, false)
    	}
    }
    

    Here, we have used below methods –

    1. shouldOverrideUrlLoading() – Use this method when you want webBrowser to decide how a new url will be loaded. If this method returns false, it means current webView will handle the url. If this method returns true, it means host application will handle the url. If you have not used this method, webView will ask activity manager to provide proper handler for new url.
    2. onReceivedError() – This method reports web resource loading error to the host application.
    3. onPageStarted() – This method is called when page loading is started.
    4. onPageFinished() – This method is called when page loading is finished.
  • Till Now, we have created WebViewClient class. Now, we will use this class to setup webViewClient. So, com.tutorialwing.webview/MainActivity and add below code into it –
    private fun setupWebViewClient() {
    	val webView = binding.webView
    	val webViewClt = WebViewClt(this)
    	webView.webViewClient = webViewClt
    	webView.loadUrl(getString(R.string.site_url))
    }
    
  • When you run the app now, you will get Toast message when page loading is started or finished. Similarly, you can do any action you want.

Using WebChromeClient class

Now, we will use WebChromeClient class to customize WebView using Kotlin with example. Use this class when you want to deal with user interface. For example, progressBar or javascript alert.

Whenever you change something in webView that impact browser ui, then, this class is called. For example, Show progressBar while page is being loaded, Show javascript alert message etc.

Follow steps below –

  • So, create a class file (with name WebChromeClt.kt), subclassed form WebChromeClient, in main/java/com.tutorialwing.webview folder. Then, add below code into it.
    package com.tutorialwing.webview
    
    import android.app.Activity
    import android.webkit.WebChromeClient
    import android.webkit.WebView
    
    class WebChromeClt(private val activity: Activity) : WebChromeClient() {
    	override fun onProgressChanged(view: WebView, progress: Int) {
    		// Activities and WebViews measure progress with different scales.
    		// The progress meter will automatically disappear when we reach 100%
    		activity.setProgress(progress * 1000)
    	}
    }
    
  • Now, we will use this WebChromeClient class with our webView to set progressbar. So, open com.tutorialwing.webview/MainActivity file and write below code into it –
    private fun setupWebChromeClient() {
    	val webView = binding.webView
    	val webChromeClt = WebChromeClt(this)
    	webView.webChromeClient = webChromeClt
    	webView.loadUrl(getString(R.string.site_url))
    }
    
  • Now, run app. We can see progressBar at the top of the screen.

Using WebSettings Class

Whenever webView is created, a default settings is attached with it throughout it’s lifecycle. That’s destroyed only when webView is destroyed. If you webView is destroyed, any call using webSettings will return IllegalStateException.
So, you can manage settings of webView using webView.

You can perform below task using webSettings –

  1. Enabling Javascript in WebView

    If we want to enable javascript in webView, we can do so using settings.javaScriptEnabled as shown below –

    val webView = binding.webView
    webView.settings.javaScriptEnabled = true
    

    Precaution: Using setJavaScriptEnabled can introduce XSS vulnerabilities into your application, review carefully

  2. Enable built-in Zoom in WebView

    If we want to enable built-in zoom in webView, we can do so using settings.builtInZoomControls as shown below –

    val webView = binding.webView
    webView.settings.builtInZoomControls = true
    

Thus, we have seen how to Customize webView using Kotlin With Example. Visit official page to learn more about this widget.

Leave a Reply