fluttervisionsdkplugin 0.6.0 fluttervisionsdkplugin: ^0.6.0 copied to clipboard
A Flutter plugin package for integrating the Flutter Vision SDK into your Flutter application for scanning Barcodes and QrCodes
// ignore_for_file: avoid_print, unused_element, library_private_types_in_public_api
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:fluttervisionsdkplugin/settings/camera_settings.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';
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;
final env = Environment.sandbox;
bool isBarcodeBeingDetected = false;
bool isQRCodeBeingDetected = false;
bool isTextBeingDetected = false;
String scannedCode = '';
String scanErrorMessage = '';
String progress = '';
bool isConfiguring = false;
bool isAutoScanning = false;
bool isOnlineOCREnabled = true;
int scanMode = 1;
bool shouldDisplayFocusImage = false;
List<String> receivedCodes = [];
void _onScanError(String errorMessage) {
print('Scan Error: $errorMessage');
setState(() {
scanErrorMessage = errorMessage;
});
}
void updateReceivedCodes(List<String> codes) {
setState(() {
receivedCodes = codes;
});
}
void _onCodesReceived(List<String> codes) {
updateReceivedCodes(codes);
if (codes.isNotEmpty) {
updateScannedCode(codes.first);
} else {
updateScannedCode('');
}
}
void _onDetectionResult(bool textDetected, bool barCodeDetected, bool qrCodeDetected) {
print('Text Detected: $textDetected');
print('Barcode Detected: $barCodeDetected');
print('QR Code Detected: $qrCodeDetected');
}
void _onOCRImagesReceived(Map<String, dynamic> scanResult) {
print(scanResult);
}
void _changeCaptureMode(String mode) {
print('Changing Capture Mode to: $mode');
}
void _changeScanMode(String mode) {
print('Changing Scan Mode to: $mode');
}
void updateScannedType(bool isText, bool isBarcode, bool isQrCode) {
setState(() {
isTextBeingDetected = isText;
isBarcodeBeingDetected = isBarcode;
isQRCodeBeingDetected = isQrCode;
});
}
void updateScannedCode(String code) {
setState(() {
scannedCode = code;
});
}
void updateProgress(String progress) {
setState(() {
this.progress = progress;
});
}
void updateIsConfiguring(bool isConfiguring) {
setState(() {
this.isConfiguring = isConfiguring;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder<PermissionStatus>(
future: Permission.camera.status,
builder: (context, snapshot) {
if (Platform.isIOS || snapshot.data?.isGranted == true) {
return Column(
children: [
SizedBox(
width: double.infinity,
height: 400,
child: VisionCameraWidget(
environment: env,
onViewCreated: (communicator) {
this.communicator = communicator;
this.communicator?.setObjectDetectionSettings(ObjectDetectionSettings());
this.communicator?.setCameraSettings(CameraSettings());
this.communicator?.startCamera();
},
listener: MainNativeViewWidgetListener(this),
),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
Text(
'Scanned Code: $scannedCode',
style: const TextStyle(color: Colors.black, fontSize: 16),
),
Text(
'Barcode: $isBarcodeBeingDetected\t\tQRCode: $isQRCodeBeingDetected\t\tText: $isTextBeingDetected',
style: const TextStyle(color: Colors.black, fontSize: 16),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: RadioListTile(
value: true,
title: const Text('Auto'),
groupValue: isAutoScanning,
onChanged: (i) {
setState(() {
isAutoScanning = true;
});
communicator?.setScanMode(1);
}),
),
Expanded(
child: RadioListTile(
value: false,
title: const Text('Manual'),
groupValue: isAutoScanning,
onChanged: (i) {
setState(() {
isAutoScanning = false;
});
communicator?.setScanMode(2);
}),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Flexible(
child: RadioListTile(
value: 1,
title: const Text('B'),
groupValue: scanMode,
onChanged: (i) {
setState(() {
scanMode = 1;
});
communicator?.setCaptureModeBarcode();
}),
),
Flexible(
child: RadioListTile(
value: 2,
title: const Text('Q'),
groupValue: scanMode,
onChanged: (i) {
setState(() {
scanMode = 2;
});
communicator?.setCaptureModeQrCode();
}),
),
if (!isAutoScanning)
Flexible(
child: RadioListTile(
value: 3,
title: const Text('O'),
groupValue: scanMode,
onChanged: (i) {
setState(() {
scanMode = 3;
});
communicator?.setCaptureModeOCR();
}),
),
],
),
if (!isAutoScanning && !isConfiguring)
ElevatedButton(
onPressed: () {
isOnlineOCREnabled = true;
communicator?.capturePhoto();
},
child: const Text('Capture Photo'),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!isConfiguring)
ElevatedButton(
onPressed: () async {
updateIsConfiguring(true);
updateProgress('Working...');
communicator?.stopCamera();
await communicator?.configureOnDeviceOCR(
apiKey: getApiKey(env),
modelClass: ModelClass.shippingLabel,
modelSize: ModelSize.micro);
},
child: const Text('Configure'),
),
if (progress.isNotEmpty) Text(progress)
],
),
if (!isConfiguring)
ElevatedButton(
onPressed: () {
isOnlineOCREnabled = false;
communicator?.capturePhoto();
captureTime = DateTime.now().millisecondsSinceEpoch;
totalTime = captureTime;
},
child: const Text('Get Predictions'),
),
],
),
),
),
],
);
} 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 MainNativeViewWidgetListener implements PluginToFlutterCommunicator {
MainNativeViewWidgetListener(this._state);
final _MyAppState _state;
Timer? _timerTask;
Uint8List? byteArrayImage; List<String>? codes;
@override
void onCameraStarted() {
_state.communicator?.setFocusSettings(FocusSettings());
}
@override
void onCameraStopped() {}
@override
void onCodesReceived(List<String> codes) {
_state.updateScannedCode(codes.join(','));
_resetTextAfterDelay();
}
@override
void onDetectionResult(bool isText, bool isBarcode, bool isQrCode) {
_state.updateScannedType(isText, isBarcode, isQrCode);
}
@override
void onImageCaptured(Uint8List byteArrayImage, List<String> codes) {
captureTime = DateTime.now().millisecondsSinceEpoch - captureTime;
processingTime = DateTime.now().millisecondsSinceEpoch;
this.byteArrayImage = byteArrayImage;
this.codes = codes;
if (_state.isOnlineOCREnabled) {
_state.communicator?.callBolApi(
apiKey: getBolApiKey(_state.env),
image: byteArrayImage,
barcodes: codes);
// _state.communicator?.callOcrApi(
// 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.communicator?.getPredictions(byteArrayImage, codes);
}
}
@override
void onOnDeviceConfigureProgress(double progress) {
print('Configure progress $progress');
_state.updateProgress(progress.toString());
}
@override
void onOnDeviceConfigurationComplete() {
print('On-Device Configuration Completed');
_state.communicator?.startCamera();
_state.updateProgress('');
_state.updateIsConfiguring(false);
}
@override
void onOnlineSLResult(Map<String, dynamic> result) {
_state.updateScannedCode(result.toString());
_resetTextAfterDelay();
}
@override
void onMatchingResult(Map<String, dynamic> result) {
_state.updateScannedCode(result.toString());
_resetTextAfterDelay();
}
@override
void onOnlineBOLResult(Map<String, dynamic> result) {
_state.updateScannedCode(result.toString());
_resetTextAfterDelay();
}
@override
void onOnDeviceOCRResult(Map<String, dynamic> result) {
print('ON-DEVICE OCR RESPONSE');
print(result);
byteArrayImage = null;
codes = null;
// 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"
// );
_state.updateScannedCode(result.toString().replaceAll('\n', ''));
_resetTextAfterDelay();
}
@override
void onReportResult(Map<ReportResult, String> reportResult) {
switch (reportResult.keys.first) {
case ReportResult.successful:
_state.updateScannedCode("Report submitted successfully");
break;
case ReportResult.savedForLater:
_state.updateScannedCode("Report saved for later");
break;
case ReportResult.failed:
_state.updateScannedCode(reportResult.values.first);
break;
}
_resetTextAfterDelay();
}
@override
void onScanError(String error) {
_state.updateScannedCode(error);
_resetTextAfterDelay();
}
void _resetTextAfterDelay() {
_timerTask?.cancel();
_timerTask = Timer(const Duration(seconds: 4), () {
_state.updateScannedCode('');
_state.communicator?.rescan();
});
}
}
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(),
};
}
String getBolApiKey(Environment env) {
return switch (env) {
Environment.qa => throw UnimplementedError(),
Environment.dev => DEV.bolApiKey,
Environment.staging => STAGING.bolApiKey,
Environment.sandbox => SANDBOX.bolApiKey,
Environment.production => throw UnimplementedError(),
};
}