While its still considered a “Developers Preview”, the first-party WebView plugin for Flutter is now quite usable for a range of tasks. One piece of very useful functionality is the ability to communicate with the content running inside a webview, specifically with its Javascript runtime, but as it was only added around Feb this year, I did not find many examples on how to use it, while the official documentation is stashed away in the not so easy to find inline doc comments on the WebView’s javascriptChannels property. Hence I thought others may find it useful if I documented my recent use of it here.

The first thing you need to do is of course make sure you have the latest version of the webview plugin added to your pubspec.yaml file, as of this writing it would be:

webview_flutter: ^0.3.9+1

Then you can make use of the webview widget as usual:

Often as a mobile developer, you want to expose some piece of your apps functionality to the JS inside the webview, while this needs to be done carefully due to security considerations, the actual implementation is quite straight forward. First on the Flutter side, you need to enable JS within the webview and create a communication channel:

WebView(

javascriptMode: JavascriptMode.unrestricted,

javascriptChannels: <JavascriptChannel>[

JavascriptChannel(name: 'Print', onMessageReceived: (JavascriptMessage msg) { print(msg); }),

].toSet(),

)

UPDATE (5/8/2020): note that since I originally wrote this article, the type of the msg parameter in the onMessageReceived callback has changed from a String to a JavascriptMessage .

Then in your html content, the JS is just:

Print.postMessage('Hello!');

Though you will likely want to be a bit defensive and ensure that the injected Flutter object is available:

if (Print !=== 'undefined') {

Print.postMessage('Hello!');

} else {

console.debug('not running inside a Flutter webview');

}

As the documentation in the commit message states, return values cannot be passed back from Dart to JS at this time, but the availability of the method for executing JS inside the webview from Flutter means you are able to DIY your own mechanism for sending values from Dart to JS.

One thing to also note is the regular expression used to enforce valid names for channels on the Dart side:

final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9]*\$');

which for example means you cannot have periods in your channel names.

And really that’s all there is to it. Once again, Flutter provides an even simplier than “native” way of handling a common need for mobile app development.