3

I have a flutter code snippet which listens for postMessage from my iframe page. (flutter_webview_plugin: ^0.3.9+1)

flutterWebviewPlugin.onStateChanged.listen((viewState) async {
    String script = 'window.addEventListener("message", receiveMessage, false);' +
            'function receiveMessage(event) {console.log(\'receiving data from child , data as follows: \',event.data)}';
    flutterWebviewPlugin.evalJavascript(script);
}

I would like to trigger specific flutter functions if event.data returns a specific value , camera value would trigger my specific function that calls the camera plugin and so on. Meaning to say that my target iFrame will attempt to do a cross-origin communication via postMessage method.

For Cordova, I could do something like this:

window.addEventListener( "message" , function( event )
{
  else if( event.data.indexOf( "camera" ) >= 0 )
        {
           //Trigger Camera Function

How do I go about doing this for flutter?

3
  • How about flutterWebviewPlugin.evalJavascript(script).then((result) {/* Do job*/});? Commented Nov 25, 2019 at 1:26
  • @TrầnĐứcTâm This would be like a subscribing service, where the postMessage will send more than once, the code should not just run once but await for the right message being sent back. Commented Nov 25, 2019 at 2:29
  • I got you idea. Answered this question. I tested it on Android device but not iOS. Commented Nov 25, 2019 at 3:39

1 Answer 1

11
+50

2 solution for you:

Solution 1: Recommend

import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

final Set<JavascriptChannel> jsChannels = [
  JavascriptChannel(
      name: 'Print',
      onMessageReceived: (JavascriptMessage message) {
        print('message.message: ${message.message}');
      }),
].toSet();

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: {
        "/": (_) => WebviewScaffold(
              url: Uri.dataFromString(
                      '<html><button onclick="Print.postMessage(\'test\');">Click me</button></html>',
                      mimeType: 'text/html')
                  .toString(),
              appBar: new AppBar(title: new Text("Widget webview")),
              javascriptChannels: jsChannels,
            ),
      },
    );
  }
}

I/flutter (22119): message.message: test

Solution 2: If you want to keep your window.post. (Maybe you would like to use the iframe from another platform)

import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

final Set<JavascriptChannel> jsChannels = [
  JavascriptChannel(
      name: 'Print',
      onMessageReceived: (JavascriptMessage message) {
        print('message.message: ${message.message}');
      }),
].toSet();

void main() {
  final flutterWebviewPlugin = FlutterWebviewPlugin();
  flutterWebviewPlugin.onStateChanged.listen((state) async {
    if (state.type == WebViewState.finishLoad) {
      String script =
          'window.addEventListener("message", receiveMessage, false);' +
              'function receiveMessage(event) {Print.postMessage(event.data);}';
      flutterWebviewPlugin.evalJavascript(script);
    }
  });
  return runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: {
        "/": (_) => WebviewScaffold(
              url: Uri.dataFromString(
                      '<html><button onclick="window.postMessage(\'test\', \'*\');">Click me</button></html>',
                      mimeType: 'text/html')
                  .toString(),
              appBar: new AppBar(title: new Text("Widget webview")),
              javascriptChannels: jsChannels,
            ),
      },
    );
  }
}

I/flutter (22119): message.message: test

pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.2
  flutter_webview_plugin: 0.3.9+1

Reference:

Sign up to request clarification or add additional context in comments.

3 Comments

Ahh thanks, let me get back to you soon once I tried it out. Was about to try on Javascript channels, and looks like it was a right choice!
@Gene, Did you checked this code? I don't have iOS device so I cant check iOS code.
@Gene I checked it by iOS today. It's worked. If it also work for you. Please mark my answer as accepted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.