fluttervisionsdkplugin 1.2.1 copy "fluttervisionsdkplugin: ^1.2.1" to clipboard
fluttervisionsdkplugin: ^1.2.1 copied to clipboard

A Flutter plugin package for integrating the Flutter Vision SDK into your Flutter application for scanning Barcodes and QrCodes

example/lib/main.dart

// ignore_for_file: avoid_print, unused_element, library_private_types_in_public_api

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttervisionsdkplugin/dtos/scanned_code_result.dart';
import 'package:fluttervisionsdkplugin/enums/camera_lens_face.dart';
import 'package:fluttervisionsdkplugin/settings/camera_settings.dart';
import 'package:fluttervisionsdkplugin/visionsdk.dart';
import 'package:fluttervisionsdkplugin_example/secrets.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:fluttervisionsdkplugin/settings/focus_settings.dart';
import 'package:fluttervisionsdkplugin/settings/object_detection_settings.dart';
import 'package:fluttervisionsdkplugin/visioncamerawidget.dart';
import 'package:fluttervisionsdkplugin/ondeviceocrmanager.dart';
import 'package:share_plus/share_plus.dart';

void main() {
  runApp(const MyApp());
}

int captureTime = 0;
int processingTime = 0;
int totalTime = 0;

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  FlutterToPluginCommunicator? communicator;
  OnDeviceOCRManagerCommunicator? onDeviceOCRManagerCommunicator;

  final env = Environment.staging;

  bool isAutoScanning = false;
  int scanMode = 1;

  int captureMode = 1;

  bool shouldDisplayFocusImage = false;

  ModelClass selectedModel = ModelClass.shippingLabel;
  bool getOnlinePredictions = true;

  bool isBarcodeBeingDetected = false;
  bool isQRCodeBeingDetected = false;
  bool isTextBeingDetected = false;
  bool isDocumentBeingDetected = false;

  CameraSettings cameraSettings =  CameraSettings();

  void updateScannedType(bool isText, bool isBarcode, bool isQrCode, bool isDocument) {
    setState(() {
      isTextBeingDetected = isText;
      isBarcodeBeingDetected = isBarcode;
      isQRCodeBeingDetected = isQrCode;
      isDocumentBeingDetected = isDocument;
    });
  }

  double? _configureProgress;

  void updateConfigureProgress(double? configureProgress) {
    setState(() {
      _configureProgress = configureProgress;
    });
  }

  List<ScannedCodeResult> _receivedCodes = [];

  void updateReceivedCodes(List<ScannedCodeResult> receivedCodes) {
    setState(() {
      _receivedCodes = receivedCodes;
    });
  }

  Map<String, dynamic> _ocrResult = {};

  void updateOCRResult(Map<String, dynamic> result) {
    setState(() {
      _ocrResult = result;
    });
  }

  bool isConfigured = false;

  void updateIsConfigured(bool isConfigured) {
    setState(() {
      this.isConfigured = isConfigured;
    });
  }

  @override
  void initState() {
    super.initState();
    VisionSDK().initialize(env);
    onDeviceOCRManagerCommunicator = OnDeviceOCRManagerCommunicator(
      MainOnDeviceOCRManagerListener(this)
    );
  }

  @override
  void dispose() {
    super.dispose();
    onDeviceOCRManagerCommunicator?.release();
  }

  @override
  Widget build(BuildContext buildContext) {
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder<PermissionStatus>(
          future: Permission.camera.status,
          builder: (context, snapshot) {
            if (Platform.isIOS || snapshot.data?.isGranted == true) {
              return Stack(
                children: [
                  SizedBox(
                    width: double.infinity,
                    height: double.infinity,
                    child: VisionCameraWidget(
                      onViewCreated: (communicator) {
                        this.communicator = communicator;
                        if (isAutoScanning) {
                          this.communicator?.setScanAuto();
                        } else {
                          this.communicator?.setScanManual();
                        }
                        this.communicator?.setObjectDetectionSettings(
                            ObjectDetectionSettings());
                        this.communicator?.setCameraSettings(cameraSettings);
                        this.communicator?.setFocusSettings(FocusSettings());
                        this.communicator?.setMultipleScanEnabled(true);
                        this.communicator?.startCamera();
                      },
                      listener: MainNativeViewWidgetListener(this),
                    ),
                  ),
                  Align(
                    alignment: Alignment.topRight,
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        SizedBox(height: 100,),
                        Text('Barcode', style: TextStyle(color: isBarcodeBeingDetected ? Colors.green : Colors.white,)),
                        Text('QRCode', style: TextStyle(color: isQRCodeBeingDetected ? Colors.green : Colors.white,)),
                        Text('Text', style: TextStyle(color: isTextBeingDetected ? Colors.green : Colors.white,)),
                        Text('Document', style: TextStyle(color: isDocumentBeingDetected ? Colors.green : Colors.white,)),
                      ],
                    ),
                  ),
                  Align(
                    alignment: Alignment.topCenter,
                    child: Container(
                      width: double.infinity,
                      color: const Color(0x88FFFFFF),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: [
                          const SizedBox(
                            height: 30,
                          ),
                          DropdownMenu(
                            dropDownOptions: const ['Barcode', 'QRCode', 'OCR'],
                            onItemSelected: (selectedItemIndex) {
                              switch (selectedItemIndex) {
                                case 0:
                                  setState(() {
                                    captureMode = 1; // BARCODE
                                  });
                                  communicator?.setCaptureModeBarcode();
                                  break;
                                case 1:
                                  setState(() {
                                    captureMode = 2; // QRCODE
                                  });
                                  communicator?.setCaptureModeQrCode();
                                  break;
                                case 2:
                                  setState(() {
                                    captureMode = 3; // OCR
                                  });
                                  communicator?.setCaptureModeOCR();
                                  break;
                              }
                            },
                          ),
                        ],
                      ),
                    ),
                  ),
                  Align(
                    alignment: Alignment.bottomCenter,
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Align(
                          alignment: Alignment.centerRight,
                          child: IconButton(iconSize: 34, icon: Icon(Icons.switch_camera,),
                          onPressed: (){
                            cameraSettings = CameraSettings(
                              nthFrameToProcess: cameraSettings.nthFrameToProcess,
                              cameraLensFace: cameraSettings.cameraLensFace == CameraLensFace.back ? CameraLensFace.front : CameraLensFace.back
                            );
                            communicator?.setCameraSettings(cameraSettings);
                          }),
                        ),
                        SizedBox(height: 20,),
                        Container(
                          color: const Color(0x88FFFFFF),
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            mainAxisAlignment: MainAxisAlignment.end,
                            children: [
                              if (captureMode == 3) // WHEN CAPTURE MODE IS OCR
                                Row(
                                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                  children: [
                                    Expanded(
                                      child: RadioListTile(
                                          value: true,
                                          title: const Text('Online OCR'),
                                          groupValue: getOnlinePredictions,
                                          onChanged: (i) {
                                            setState(() {
                                              getOnlinePredictions = true;
                                            });
                                          }),
                                    ),
                                    Expanded(
                                      child: RadioListTile(
                                          value: false,
                                          title: const Text('On-Device OCR'),
                                          groupValue: getOnlinePredictions,
                                          onChanged: (i) {
                                            setState(() {
                                              getOnlinePredictions = false;
                                            });
                                          }),
                                    ),
                                  ],
                                ),
                              if (captureMode == 3) // WHEN CAPTURE MODE IS OCR
                                DropdownMenu(
                                  dropDownOptions: const [
                                    'Shipping Label',
                                    'Bill Of Lading',
                                    'Item Label',
                                    'Document Classification',
                                  ],
                                  onItemSelected: (selectedItemIndex) {
                                    updateIsConfigured(false);
                                    onDeviceOCRManagerCommunicator?.release(); // THIS IS IMPORTANT. DO NOT CHANGE MODEL WITHOUT RELEASING PREVIOUS MODEL FIRST.
                                    switch (selectedItemIndex) {
                                      case 0:
                                        selectedModel = ModelClass.shippingLabel;
                                        break;
                                      case 1:
                                        selectedModel = ModelClass.billOfLading;
                                        break;
                                      case 2:
                                        selectedModel = ModelClass.itemLabel;
                                        break;
                                      case 3:
                                        selectedModel = ModelClass.documentClassification;
                                        break;
                                    }
                                  },
                                ),
                              Row(
                                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                children: [
                                  Expanded(
                                    child: RadioListTile(
                                        value: true,
                                        title: const Text('Auto'),
                                        groupValue: isAutoScanning,
                                        onChanged: (i) {
                                          setState(() {
                                            isAutoScanning = true;
                                          });
                                          communicator?.setScanAuto();
                                        }),
                                  ),
                                  Expanded(
                                    child: RadioListTile(
                                        value: false,
                                        title: const Text('Manual'),
                                        groupValue: isAutoScanning,
                                        onChanged: (i) {
                                          setState(() {
                                            isAutoScanning = false;
                                          });
                                          communicator?.setScanManual();
                                        }),
                                  ),
                                ],
                              ),
                              Row(
                                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                children: [
                                  if (!isAutoScanning && _configureProgress == null)
                                    ElevatedButton(
                                      onPressed: () {
                                        communicator?.capturePhoto();
                                      },
                                      child: const Text('Capture Photo'),
                                    ),
                                  if (_configureProgress != null)
                                    Row(
                                      children: [
                                        SizedBox(
                                            width: 30,
                                            height: 30,
                                            child: CircularProgressIndicator()),
                                        const SizedBox(width: 12,),
                                        Text(_configureProgress.toString())
                                      ],
                                    ),
                                  if (!getOnlinePredictions &&
                                      _configureProgress == null &&
                                      !isConfigured)
                                    ElevatedButton(
                                      onPressed: () async {
                                        updateConfigureProgress(0.0);
                                        communicator?.stopCamera();
                                        await onDeviceOCRManagerCommunicator?.configureOnDeviceOCR(
                                            apiKey: getApiKey(env),
                                            modelClass: selectedModel,
                                            modelSize: ModelSize.large);
                                      },
                                      child: const Text('Configure'),
                                    ),
                                ],
                              ),
                              const SizedBox(
                                height: 10,
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                  if (_receivedCodes.isNotEmpty)
                    AlertDialog(
                      content: SingleChildScrollView(
                        child: ListBody(
                          children: _receivedCodes.map((code) => Text('${code.scannedCode}\n${code.gs1ExtractedInfo}')).toList(),
                        ),
                      ),
                      actions: [
                        TextButton(
                            onPressed: () {
                              communicator?.rescan();
                              setState(() {
                                _receivedCodes.clear();
                              });
                            },
                            child: Text('OK'))
                      ],
                    ),
                  if (_ocrResult.isNotEmpty)
                    AlertDialog(
                      content: SingleChildScrollView(
                        child: Text(
                          _ocrResult.toString().replaceAll('\n', '')
                        ),
                      ),
                      actions: [
                        TextButton(
                            onPressed: () {
                              communicator?.rescan();
                              setState(() {
                                _ocrResult.clear();
                              });
                            },
                            child: Text('OK'))
                      ],
                    ),
                ],
              );
            } else {
              return Center(
                  child: FutureBuilder<bool>(
                future: Permission.camera.isPermanentlyDenied,
                builder: (context, snapshot) {
                  if (snapshot.data == true) {
                    return const Text(
                        "Go to Settings and allow camera permission");
                  } else {
                    return ElevatedButton(
                        onPressed: () async {
                          await Permission.camera.request();
                          setState(() {});
                        },
                        child: const Text('Request Camera Permission'));
                  }
                },
              ));
            }
          },
        ),
      ),
    );
  }
}

class MainOnDeviceOCRManagerListener implements OnDeviceOCRManagerListener {

  MainOnDeviceOCRManagerListener(this._state);

  final _MyAppState _state;

  @override
  void onOnDeviceConfigureProgress(double progress) {
    print('Configure progress $progress');
    _state.updateConfigureProgress(progress);
  }

  @override
  void onOnDeviceConfigurationComplete() {
    print('On-Device Configuration Completed');
    _state.updateConfigureProgress(null);
    _state.communicator?.startCamera();
    _state.updateIsConfigured(true);
  }

  @override
  void onOnDeviceOCRResult(Map<String, dynamic> result) {
    print('ON-DEVICE OCR RESPONSE');
    print(result);

    _state.updateOCRResult(result);

    // final processingTimeTaken = DateTime.now().millisecondsSinceEpoch - processingTime;
    // final totalTimeTaken = DateTime.now().millisecondsSinceEpoch - totalTime;
    // _state.updateScannedCode(
    //   "CAPTURE TIME: $captureTime millis\nPROCESSING TIME: $processingTimeTaken millis\nTOTAL TIME: $totalTimeTaken millis"
    // );
  }

  @override
  void onError(String error) {
    _state.updateOCRResult({'error': error});
    _state.updateConfigureProgress(null);
    _state.communicator?.startCamera();
  }

  @override
  void onReportResult(Map<ReportResult, String> reportResult) {
    switch (reportResult.keys.first) {
      case ReportResult.successful:
        _state.updateOCRResult({'response': 'Report submitted successfully'});
        break;

      case ReportResult.savedForLater:
      _state.updateOCRResult({'response': 'Report saved for later'});
        break;

      case ReportResult.failed:
      _state.updateOCRResult({'error': reportResult.values.first});
        break;
    }
  }

  @override
  void onLogFileExported(String logFilePath) {
    Share.shareXFiles([XFile(logFilePath)]);
  }
}

class MainNativeViewWidgetListener implements PluginToFlutterCommunicator {
  MainNativeViewWidgetListener(this._state);

  final _MyAppState _state;

  Uint8List? byteArrayImage;
  List<String>? codes;

  @override
  void onCameraStarted() {}

  @override
  void onCameraStopped() {}

  @override
  void onCodesReceived(List<ScannedCodeResult> codes) {
    _state.updateReceivedCodes(codes);
  }

  @override
  void onDetectionResult(bool isText, bool isBarcode, bool isQrCode, bool isDocument) {
    _state.updateScannedType(isText, isBarcode, isQrCode, isDocument);
  }

  @override
  void onImageCaptured(Uint8List byteArrayImage, List<ScannedCodeResult> scannedCodeResults) {
    captureTime = DateTime.now().millisecondsSinceEpoch - captureTime;
    processingTime = DateTime.now().millisecondsSinceEpoch;

    final codes = scannedCodeResults.map(
      (item) { return item.scannedCode; }
    ).toList();

    this.byteArrayImage = byteArrayImage;
    this.codes = codes;

    switch (_state.selectedModel) {
      case ModelClass.shippingLabel:
        if (_state.getOnlinePredictions) {
          _state.communicator?.callShippingLabelApi(
              apiKey: getApiKey(_state.env),
              image: byteArrayImage,
              barcodes: codes,
              sender: {
                'contact_id': 'ctct_hNxjevb74gV62i5XTQvqg6'
              },
              recipient: {
                'contact_id': 'ctct_hNxjevb74gV62i5XTQvqg6'
              },
              // options: {
              //   'match': {
              //     'search': ['recipients'],
              //     'location': true
              //   },
              //   'postprocess': {'require_unique_hash': false},
              //   'transform': {
              //     'tracker': 'outbound',
              //     'use_existing_tracking_number': false
              //   }
              // },
              metadata: {
                'Test': 'Pass'
              });
        } else {
          _state.onDeviceOCRManagerCommunicator?.getPredictions(byteArrayImage, codes);
        }
        break;
      case ModelClass.billOfLading:
        if (_state.getOnlinePredictions) {
          _state.communicator?.callBolApi(
              apiKey: getApiKey(_state.env),
              image: byteArrayImage,
              barcodes: codes);
        } else {
          _state.onDeviceOCRManagerCommunicator?.getPredictions(byteArrayImage, codes);
        }
        break;
      case ModelClass.itemLabel:
        if (_state.getOnlinePredictions) {
          _state.communicator?.callItemLabelApi(
            apiKey: getApiKey(_state.env),
            image: byteArrayImage
          );
        } else {
          _state.onDeviceOCRManagerCommunicator?.getPredictions(byteArrayImage, codes);
        }
        break;
      case ModelClass.documentClassification:
        if (_state.getOnlinePredictions) {
          _state.communicator?.callDocumentClassificationApi(
            apiKey: getApiKey(_state.env),
            image: byteArrayImage
          );
        } else {
          _state.onDeviceOCRManagerCommunicator?.getPredictions(byteArrayImage, codes);
        }
        break;
    }
  }

  @override
  void onOnlineSLResult(Map<String, dynamic> result) {
    _state.updateOCRResult(result);
  }

  @override
  void onMatchingResult(Map<String, dynamic> result) {
    _state.updateOCRResult(result);
  }

  @override
  void onOnlineBOLResult(Map<String, dynamic> result) {
    _state.updateOCRResult(result);
  }

  @override
  void onOnlineItemLabelResult(Map<String, dynamic> result) {
    _state.updateOCRResult(result);
  }

  @override
  void onOnlineDocumentClassificationResult(Map<String, dynamic> result) {
    _state.updateOCRResult(result);
  }

  @override
  void onScanError(String error) {
    _state.updateOCRResult({'error': error});
  }
}

String getApiKey(Environment env) {
  return switch (env) {
    Environment.qa => throw UnimplementedError(),
    Environment.dev => DEV.apiKey,
    Environment.staging => STAGING.apiKey,
    Environment.sandbox => SANDBOX.apiKey,
    Environment.production => PRODUCTION.apiKey
  };
}

class DropdownMenu extends StatefulWidget {
  final List<String> dropDownOptions;
  final Function(int) onItemSelected;

  const DropdownMenu(
      {super.key, required this.dropDownOptions, required this.onItemSelected});

  @override
  State<DropdownMenu> createState() => _DropdownMenuState();
}

class _DropdownMenuState extends State<DropdownMenu> {
  String dropdownValue = '';

  @override
  void initState() {
    super.initState();
    dropdownValue = widget.dropDownOptions.first;
  }

  @override
  Widget build(BuildContext context) {
    return DropdownButton<String>(
      value: dropdownValue,
      style: const TextStyle(color: Colors.deepPurple),
      onChanged: (String? value) {
        setState(() {
          dropdownValue = value!;
        });
        widget.onItemSelected(widget.dropDownOptions.indexOf(value!));
      },
      items:
          widget.dropDownOptions.map<DropdownMenuItem<String>>((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(value),
        );
      }).toList(),
    );
  }
}
copied to clipboard
2
likes
140
points
1.2k
downloads

Publisher

verified publisherpackagex.io

Weekly Downloads

2024.09.13 - 2025.03.28

A Flutter plugin package for integrating the Flutter Vision SDK into your Flutter application for scanning Barcodes and QrCodes

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

flutter, flutter_web_plugins, plugin_platform_interface

More

Packages that depend on fluttervisionsdkplugin