3

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.

1 Answer 1

6

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*******/
      });
}
Sign up to request clarification or add additional context in comments.

4 Comments

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})
Glad to help. please mark this as answer if it help, thanks.
you can do string concatenation to let javascript execute/evaluate this string. before that you have to make sure this long string works.
@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?

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.