Flutter two way communication js to dart and callback result from dart to js

4,594

You can use webViewctrl.evaluateJavascript
you can reference https://www.elasticfeed.com/7ee71117c626c2021eb919c182ec483a/
code snippet

onPressed: () {
          webViewctrl.evaluateJavascript(
              "scanBarcode('123')");
        }

I add console.log(message); to javascript function scanBarcode to prove it work

function scanBarcode(message) {
   console.log(message);
   if (window.Barcode && window.Barcode.postMessage) {
      console.log(document.documentElement.innerHTML);
      Barcode.postMessage(message);
   }
}

Output

I/chromium( 5209): [INFO:CONSOLE(2)] "123", source: http://yoursite/jschannel/script.js (2)

full test code

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

WebViewController webViewctrl;

class _MyHomePageState extends State<MyHomePage> {
  final Completer<WebViewController> _controller =
      Completer<WebViewController>();

  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: const Text('Plugin example'),
            actions: <Widget>[
              //MenuList(_controller.future),
            ],
          ),
          body: Builder(builder: (BuildContext context) {
            return WebView(
              initialUrl: 'http://yoursite/jschannel/index.html',
              javascriptMode: JavascriptMode.unrestricted,
              onWebViewCreated: (WebViewController webViewController) {
                _controller.complete(webViewController);
                webViewctrl = webViewController;
              },
              javascriptChannels: <JavascriptChannel>[
                _scanBarcode(context),
              ].toSet(),
              onPageFinished: (String url) {
                //TODO : events after page loading finished
              },
            );
          }),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              webViewctrl.evaluateJavascript(
                  "scanBarcode('123')");
            },
            child: Icon(Icons.navigation),
            backgroundColor: Colors.green,
          )),
    );
  }
}

JavascriptChannel _scanBarcode(BuildContext context) {
  return JavascriptChannel(
      name: 'Barcode',
      onMessageReceived: (JavascriptMessage message) {
        /*String result = scanBarcode(context);
        ******I got result of scanned barcode in result variable*******/
      });
}
Share:
4,594
Ankit Sathvara
Author by

Ankit Sathvara

Updated on December 16, 2022

Comments

  • Ankit Sathvara
    Ankit Sathvara over 1 year

    I am new to flutter. I have developed js to flutter dart communication using webview_flutter. like this :

    Widget build(BuildContext context) {
       return MaterialApp(
          home: Scaffold(
          appBar: AppBar(
             title: const Text('Plugin example'),
             actions: <Widget>[
                MenuList(_controller.future),
             ],
          ),
          body: Builder(builder: (BuildContext context) {
             return WebView(
               initialUrl: localServerUrl,
               javascriptMode: JavascriptMode.unrestricted,
               onWebViewCreated: (WebViewController webViewController) {
                 _controller.complete(webViewController);
               },
               javascriptChannels: <JavascriptChannel>[
                 _scanBarcode(context),
               ].toSet(),
               onPageFinished: (String url) {
                 //TODO : events after page loading finished
               },
            );
         }),
       ),
     );
    }
    
    JavascriptChannel _scanBarcode(BuildContext context) {
      return JavascriptChannel(
         name: 'Barcode',
         onMessageReceived: (JavascriptMessage message) {
           String result = scanBarcode(context);
           ******I got result of scanned barcode in result variable******
         });
    }
    

    server html file

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      <script src="script.js"></script>
    </head>
    <body>
      <button id="btnBarcode" style="margin-top:20px; height:30px;">Scan Barcode</button>
    </body>
    </html>
    

    and this is JS file

    function scanBarcode(message) {
       if (window.Barcode && window.Barcode.postMessage) {
          Barcode.postMessage(message);
       }
    }
    
    window.onload = function () {
       document.getElementById('btnBarcode').onclick = function () {
         scanBarcode("Scan Barcode");
       }
    }
    

    I have successfully got result of scanned barcode in javascript channel _scanBarcode in Dart file.

    Now I want to callback this barcode result back to JS file in scanBarcode function.

    I have researched so much time but not getting anything.

    I am stuck here. Can anyone help me?? Thank you so much in advance.

  • Ankit Sathvara
    Ankit Sathvara over 4 years
    Thank you for your answer.. Its working. Can't we do directly return result like return result in dart file, and that we will get in JavaScript function using premise then().. somthing like this.. scanBarcode(..).then(function (barcodeResult) {// result from Dart})
  • chunhunghan
    chunhunghan over 4 years
    Glad to help. please mark this as answer if it help, thanks.
  • chunhunghan
    chunhunghan over 4 years
    you can do string concatenation to let javascript execute/evaluate this string. before that you have to make sure this long string works.
  • MNFS
    MNFS almost 4 years
    @chunhunghan hi thanks for the answer, i want to ask what is the Barcode means on JavascriptChannel param name? is it class name of js file? can i still got result if i call window.postMessage(result); on the javascript func?