Google\'s security guidelines for Android app developers has the following:
WebViews do not use
addJavaScriptInterface()
with untrusted cont
Here's a solution using the compat lib: Download Full Solution in Android Studio format
This example uses an index.html and an index.js file stored in the assets folder.
Here is the JS:
const channel = new MessageChannel();
var nativeJsPortOne = channel.port1;
var nativeJsPortTwo = channel.port2;
window.addEventListener('message', function(event) {
if (event.data != 'capturePort') {
nativeJsPortOne.postMessage(event.data)
} else if (event.data == 'capturePort') {
/* The following three lines form Android class 'WebViewCallBackDemo' capture the port and assign it to nativeJsPortTwo
var destPort = arrayOf(nativeToJsPorts[1])
nativeToJsPorts[0].setWebMessageCallback(nativeToJs!!)
WebViewCompat.postWebMessage(webView, WebMessageCompat("capturePort", destPort), Uri.EMPTY) */
if (event.ports[0] != null) {
nativeJsPortTwo = event.ports[0]
}
}
}, false);
nativeJsPortOne.addEventListener('message', function(event) {
alert(event.data);
}, false);
nativeJsPortTwo.addEventListener('message', function(event) {
alert(event.data);
}, false);
nativeJsPortOne.start();
nativeJsPortTwo.start();
And here is the HTML:
WebView Callback Demo
And finally Here is the native Android code:
class PostMessageHandler(webView: WebView) {
private val nativeToJsPorts = WebViewCompat.createWebMessageChannel(webView)
private var nativeToJs: WebMessagePortCompat.WebMessageCallbackCompat? = null
init {
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_CALLBACK_ON_MESSAGE)) {
nativeToJs = object : WebMessagePortCompat.WebMessageCallbackCompat() {
override fun onMessage(port: WebMessagePortCompat, message: WebMessageCompat?) {
super.onMessage(port, message)
Toast.makeText(webView.context, message!!.data, Toast.LENGTH_SHORT).show()
}
}
}
var destPort = arrayOf(nativeToJsPorts[1])
nativeToJsPorts[0].setWebMessageCallback(nativeToJs!!)
WebViewCompat.postWebMessage(webView, WebMessageCompat("capturePort", destPort), Uri.EMPTY)
}
}
It is important the the native code be executed from the 'WebViewClient.onPageFinished(webView: WebView, url: String)' callback. See download link above for full details. This project shows postMessage working both ways (Native to JS and JS to Native) Hope this helps.