fluttervisionsdkplugin 0.83.0 copy "fluttervisionsdkplugin: ^0.83.0" to clipboard
fluttervisionsdkplugin: ^0.83.0 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/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';

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.sandbox;

  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;

  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<String> _receivedCodes = [];

  void updateReceivedCodes(List<String> 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(Environment.sandbox);
    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: Container(
                      color: const Color(0x88FFFFFF),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: [
                          if (captureMode == 3 &&
                              selectedModel !=
                                  ModelClass
                                      .billOfLading) // 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;
                                    setState(() {
                                      getOnlinePredictions = true;
                                    });
                                    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((e) => Text(e)).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;
    }
  }
}

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<String> 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<String> codes) {
    captureTime = DateTime.now().millisecondsSinceEpoch - captureTime;
    processingTime = DateTime.now().millisecondsSinceEpoch;

    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:
        _state.communicator?.callBolApi(
            apiKey: getApiKey(_state.env),
            image: byteArrayImage,
            barcodes: 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 => throw UnimplementedError(),
  };
}

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(),
    );
  }
}
2
likes
0
points
891
downloads

Publisher

verified publisherpackagex.io

Weekly Downloads

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

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, flutter_web_plugins, plugin_platform_interface

More

Packages that depend on fluttervisionsdkplugin