Implementation of fluent web plug-in: get through JavaScript and Dart

Previously, I shared how to support Android and Windows in the fluent plug-in. This article will add the implementation method of Web plug-in and create a simple web one-dimensional code and two-dimensional code recognition application.

Reference resources


Developing the fluent web plug-in

The main problem in Web plug-in development is how to realize the mutual call between Dart and JavaScript. Firebase provided on the official website_ Web examples are worth learning and reference.

Initialize web plug-in

Add a Web template to the current plug-in project:

flutter create --template=plugin --platforms=web .

Unlike windows and Android, the web template does not generate a directory called web, nor does it generate any JavaScript code files. We only see a new flitter_ barcode_ sdk_ web. Dart file.

Next, add the plug-in declaration to pubspec In yaml:

        package: com.dynamsoft.flutter_barcode_sdk
        pluginClass: FlutterBarcodeSdkPlugin
        pluginClass: FlutterBarcodeSdkPlugin
        pluginClass: FlutterBarcodeSdkWeb
        fileName: flutter_barcode_sdk_web.dart

How to realize the interaction between JavaScript and Dart

Like other platforms, handleMethodCall() is the entry:

Future<dynamic> handleMethodCall(MethodCall call) async {
    switch (call.method) {
      case 'getPlatformVersion':
        return getPlatformVersion();
        throw PlatformException(
          code: 'Unimplemented',
              'flutter_barcode_sdk for web doesn\'t implement \'${call.method}\'',

But the difference is that the web does not need to introduce dependency library compilation into the plug-in. All we have to do is define the interface.

I have defined two interfaces: decodeFile() and decodeVideo(), which are used to recognize one-dimensional code and two-dimensional code through image and video respectively.

BarcodeManager _barcodeManager = BarcodeManager();

/// Decode barcodes from an image file.
Future<List<Map<dynamic, dynamic>>> decodeFile(String file) async {
  return _barcodeManager.decodeFile(file);

/// Decode barcodes from real-time video stream.
Future<void> decodeVideo() async {

In video mode, the result is returned through callback. However, in the upper layer of the flutter_ barcode_ sdk. In dart, the callback function reference cannot be passed down through invokeMethod. My solution is to use global variables to save callback functions:

Future<void> decodeVideo(Function callback) async {
  globalCallback = callback;
  await _channel.invokeMethod('decodeVideo');

To avoid conflicts with other platforms, this variable is defined separately in a global In dart file:

Function globalCallback = () => {};

Now open barcode_manager.dart, according to dynamsoft-javascript-barcode Define the calling interface of JavaScript:

library dynamsoft;

import 'dart:convert';
import 'dart:js';
import 'package:flutter_barcode_sdk/barcode_result.dart';
import 'package:flutter_barcode_sdk/global.dart';
import 'package:js/js.dart';
import 'utils.dart';

/// BarcodeScanner class
class BarcodeScanner {
  external static PromiseJsImpl<BarcodeScanner> createInstance();
  external void show();
  external set onFrameRead(Function func);

/// BarcodeReader class
class BarcodeReader {
  external static PromiseJsImpl<BarcodeReader> createInstance();
  external PromiseJsImpl<List<dynamic>> decode(dynamic file);

In order to implement the Promise of JavaScript, we need another utils Defined in dart file:

import 'dart:async';
import 'dart:js_util';
import 'package:js/js.dart';

typedef Func1<A, R> = R Function(A a);

external String stringify(Object obj);

external void log(Object obj);

class PromiseJsImpl<T> extends ThenableJsImpl<T> {
  external PromiseJsImpl(Function resolver);
  external static PromiseJsImpl<List> all(List<PromiseJsImpl> values);
  external static PromiseJsImpl reject(error);
  external static PromiseJsImpl resolve(value);

abstract class ThenableJsImpl<T> {
  external ThenableJsImpl then([Func1 onResolve, Func1 onReject]);

Future<T> handleThenable<T>(ThenableJsImpl<T> thenable) =>

Next, implement object initialization:

/// Initialize Barcode Scanner.
void initBarcodeScanner(BarcodeScanner scanner) {
  _barcodeScanner = scanner;
  _barcodeScanner.onFrameRead = allowInterop((results) =>

/// Initialize Barcode Reader.
void initBarcodeReader(BarcodeReader reader) {
  _barcodeReader = reader;

BarcodeManager() {
      .then((scanner) => {initBarcodeScanner(scanner)});

Dart's function needs to be encapsulated by allowInterop() before it can be called by JavaScript.

Implement decodeFile():

Future<List<Map<dynamic, dynamic>>> decodeFile(String filename) async {
    List<dynamic> barcodeResults =
        await handleThenable(_barcodeReader.decode(filename));

    return _resultWrapper(barcodeResults);

Implement the decodeVideo() callback:

_barcodeScanner.onFrameRead = allowInterop((results) =>

Create Web one-dimensional code and two-dimensional code recognition program

Create a new fluent project and create it on the web / index Add < script SRC to HTML=“ @8.2.3/dist/dbr. js" data-productKeys="PRODUCT-KEYS"></script>.

In pubspec Add image to yaml_ Picker and flitter_ barcode_ sdk:


Add two buttons in the UI, one for loading pictures and one for starting camera video streaming:

final picker = ImagePicker();

Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
        appBar: AppBar(
          title: const Text('Dynamsoft Barcode Reader'),
        body: Column(children: [
            height: 100,
            child: Row(children: <Widget>[
                style: TextStyle(fontSize: 14, color:,
            child: SingleChildScrollView(
              child: Column(
                children: [
                  _file == null
                      ? Image.asset('images/default.png')
                    style: TextStyle(fontSize: 14, color:,
            height: 100,
            child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                      child: Text('Barcode Reader'),
                      textColor: Colors.white,
                      onPressed: () async {
                        final pickedFile =
                            await picker.getImage(source:;

                        setState(() {
                          if (pickedFile != null) {
                            _file = pickedFile.path;
                          } else {
                            print('No image selected.');

                          _barcodeResults = '';

                        if (_file != null) {
                          List<BarcodeResult> results =
                              await _barcodeReader.decodeFile(_file);
                      child: Text('Barcode Scanner'),
                      textColor: Colors.white,
                      onPressed: () async {
                            (results) => {updateResults(results)});

Finally run the program:

flutter run -d chrome

Fluent plug-in download

Source code

Keywords: Javascript Web Development Flutter

Added by ksduded on Thu, 10 Feb 2022 14:05:00 +0200