How I Almost Put an iframe into a WebView

Listening to JavaScript events on 3rd party webpages

Snap Click by Foundry is licenced under Creative Commons CC0

Here’s a situation. You need to load a third party URL into a view, and listen to events on the page. That shouldn’t be too hard, right? Android has WebViews we can use, and a way to interface with JavaScript events. We’ll assume we are already in an Activity with a WebView instantiated. Let’s start building it.

private fun loadWebView(webView: WebView, url: String) = with(webView) {
  loadUrl(url)
}

We already know we’ll need JavaScript enabled so we have something to listen to.

private fun loadWebView(webView: WebView, url: String) = with(webView) {
  settings.javaScriptEnabled = true
    
  loadUrl(url)
}

That was easy. Next, we need to listen to the JavaScript events on the WebView. We will include a method to our WebAppInterface that we can call from the JavaScript on the page. Here’s how the Android docs guide us to do that.

public class WebAppInterface {
  @JavascriptInterface
  fun handleMyEvent(jsonString: String) {
    val data: JSONObject = JSONObject(jsonString)
    // Do stuff with event data
  }
}
private fun loadWebView(webView: WebView, url: String) = with(webView) {
  settings.javaScriptEnabled = true
  addJavascriptInterface(WebAppInterface(), "MyJSInterface")
  
  loadUrl(url)
}

Then, on the webpage we’re loading, we add this script:

<script type="text/javascript">
  function HandleMyEvents(event) {
    MyJSInterface.handleMyEvent(JSON.stringify(event.data));
  }

  window.addEventListener("message", HandleMyEvents, false);
</script>

Not too difficult. But here’s where the issue comes in. In this example we don’t have access to the JavaScript on the webpage to make it call the Android web interface. How could we add our own JavaScript to listen to the events? This is how I almost used an iframe. By loading HTML into the WebView with an iframe, and some custom JavaScript, I could hook into those events and forward it to the interface.

private fun loadWebView(webView: WebView, url: String) = with(webView) {
  addJavascriptInterface(WebAppInterface(), "MyJSInterface")

  loadData(htmlString(url), "text/html", "utf-8")
}

htmlString() would look like:

private fun htmlString(url: String): String {
  return """
    <iframe src='$url'></iframe>
    $listenerScript
  """
}

And the listener script as described above:

private val listenerScript: String
  get() = """
    <script type='text/javascript'>
      function HandleMyEvents(event) { MyJSInterface.handleMyEvent(JSON.stringify(event.data)); }
      window.addEventListener('message', HandleMyEvents, false);
    </script>
  """
	

But do we really want to use an iframe? No, not usually.

Thankfully, I came across a better solution (of course I stumbled on this when I was looking for something else). So intead of using an iframe we can inject the JavaScript right into the WebView! Before we load in the URL we first set the WebChromeClient.

private fun loadWebView(webView: WebView, url: String) = with(webView) {
  settings.javaScriptEnabled = true
  addJavascriptInterface(WebAppInterface(), "MyJSInterface")
  
  setWebChromeClient(WebChromeClient())
  
  loadUrl(url)
}

Then, we also need to set the WebViewClient. We will override the onPageFinished() method of the WebViewClient to load our JavaScript. The JavaScript is the same as above.

private fun loadWebView(webView: WebView, url: String) = with(webView) {
  settings.javaScriptEnabled = true
  addJavascriptInterface(WebAppInterface(), "MyJSInterface")
  
  setWebChromeClient(WebChromeClient())
  setWebViewClient(object : WebViewClient() {
    override fun onPageFinished(view: WebView, url: String) {
      view.loadUrl(listenerScript)
    }
  })
  
  loadUrl(url)
}

And there we go! We can now listen to those events in our Android code. I don’t often use WebViews, and it would not have been fun to combine it with an iframe, so I’m glad I was able to find that solution.

Photo of Victoria Gonda

Victoria is a software developer working on mobile and full stack web applications. She enjoys exchanging knowledge through conference talks and writing.

Comments

  1. June 10, 2019 at 20:18 PM

    Free download the official Kodi TV App with step by step guide.

  2. cindyfitzgeraldrt08302@gmail.com
    vidmate1111
    June 20, 2019 at 4:08 AM

    This post is really helpful to know. Thank you very much!Movierulz

  3. Webview
    September 26, 2019 at 8:06 AM

    I see this too. I always thought that Chrome Assignment Writing Help | primeassignment.com would replace WebView, but in Q WebView is back.