Chapter 30 Browsing the Web and WebView
For the More Curious: Injecting JavaScript Objects
In this chapter, you have seen how to use WebViewClient and WebChromeClient to respond to
specific events that happen in your WebView. However, it is possible to do even more than that by
injecting arbitrary JavaScript objects into the document contained in the WebView itself. Check out
the documentation at developer.android.com/reference/android/webkit/WebView.html and
scroll down to the addJavascriptInterface(Object, String) method. Using this, you can inject an
arbitrary object into the document with a name you specify:
mWebView.addJavascriptInterface(new Object() {
@JavascriptInterface
public void send(String message) {
Log.i(TAG, "Received message: " + message);
}
}, "androidObject");
And then invoke it like so:
<input type="button" value="In WebView!"
onClick="sendToAndroid('In Android land')" />
There are a couple of tricky parts about this. The first is that when you call send(String), the Java
method is not called on the main thread. It is called on a thread owned by WebView instead. So if you
want to update the Android UI, you will need to use a Handler to pass control back over to the main
thread.
The other part is that not many data types are supported. You have String, the core primitive types,
and that is it. Anything more sophisticated must be marshalled through a String, usually by converting
it to JSON before sending and then parsing it out when receiving.
Starting with API 17 (Jelly Bean 4.2) and up, only public methods annotated @JavascriptInterface
are exported to JavaScript. Prior to that, all public methods in the object hierarchy were accessible.
Either way, this could be dangerous. You are letting some potentially strange web page fiddle with your
program. So to be safe, it is a good idea to make sure you own the HTML in question – either that, or
be extremely conservative with the interface you expose.