docutain_sdk 1.2.0 docutain_sdk: ^1.2.0 copied to clipboard
Flutter plugin of the Docutain Scanner SDK for Android and iOS. High quality document scanning, data extraction, text recognition and PDF creation for your apps.
import 'dart:io';
import 'package:docutain_sdk/docutain_sdk_document_datareader.dart';
import 'package:docutain_sdk/docutain_sdk_logger.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:docutain_sdk/docutain_sdk.dart';
import 'package:docutain_sdk/docutain_sdk_ui.dart';
import 'package:docutain_sdk/docutain_sdk_document.dart';
import 'package:tuple/tuple.dart';
import 'package:open_file_plus/open_file_plus.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool _isDocutainPluginInitialized = false;
@override
void initState() {
// TODO: implement initState
super.initState();
initDocutainSdk();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DocutainSDK'),
),
body: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () async {
var traceFile = await DocutainSdkLogger.getTraceFile();
OpenFile.open(traceFile?.path);
},
child: const Text('GET TRACE FILE')),
ElevatedButton(
onPressed: () async {
//do not access sdk methods if it is not yet successfully initialized
if (!_isDocutainPluginInitialized) {
_showSnackbar(
"Docutain SDK not initialized. Reason:\n${await DocutainSdk.getLastError()}");
return;
}
var scanConfig = DocumentScannerConfiguration();
//instead of using the device's camera to scan documents (default), you can also run the
//Document Scanner on imported images, for example images picked by the user from the photo gallery
//scanConfig.source = Source.galleryMultiple;
//color theming
/*scanConfig.colorConfig.colorPrimary =
const Tuple2<Color, Color>(
Colors.purple, Colors.purple);
scanConfig.colorConfig.colorSecondary =
const Tuple2<Color, Color>(
Colors.purple, Colors.purple);
scanConfig.colorConfig.colorOnSecondary =
const Tuple2<Color, Color>(
Colors.white, Colors.black);
scanConfig.colorConfig.colorScanButtonsLayoutBackground =
const Tuple2<Color, Color>(
Colors.white, Colors.black);
scanConfig.colorConfig.colorScanButtonsForeground =
const Tuple2<Color, Color>(
Colors.black, Colors.white);
scanConfig.colorConfig.colorScanPolygon =
const Tuple2<Color, Color>(
Colors.purple, Colors.purple);
scanConfig.colorConfig.colorBottomBarBackground =
const Tuple2<Color, Color>(
Colors.purple, Colors.black);
scanConfig.colorConfig.colorBottomBarForeground =
const Tuple2<Color, Color>(
Colors.white, Colors.white);
scanConfig.colorConfig.colorTopBarBackground =
const Tuple2<Color, Color>(
Colors.purple, Colors.black);
scanConfig.colorConfig.colorTopBarForeground =
const Tuple2<Color, Color>(
Colors.white, Colors.white);*/
//optionally enable/disable editing possibilities depending on your needs
//check out https://docs.docutain.com/docs/Flutter/docScan for a complete list
//of currently supported configuration values
//scanConfig.allowCaptureModeSetting = true;
//scanConfig.pageEditConfig.allowPageFilter = false;
//scanConfig.pageEditConfig.allowPageRotation = false;
//scanConfig.autoCapture = false;
//scanConfig.defaultScanFilter = ScanFilter.auto;
//...
//start the document scanner and wait for the result
//true if user finished the scan process successfully, false if user canceled
bool rcScan =
await DocutainSdkUi.scanDocument(scanConfig);
if (!rcScan) {
_showSnackbar("User canceled scan process.");
return;
}
//You can also import files into the backend (no UI) and run OCR text recognition,
//data analysis and PDF creation on it
/*
FilePickerResult? result = await FilePicker.platform
.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'pdf']);
if (result == null) {
//user canceled the file picker
return;
}
try {
bool rcImport =
await DocutainSdkDocumentDataReader.loadFile(
result.files.single.path!,
password: "Password1+");
if (!rcImport) {
//an error occured
var error = await DocutainSdk.getLastError();
return;
}
} on PlatformException catch (exception) {
if (exception.code == "SecurityException") {
//file is encrypted and password was wrong or empty
return;
}
}
*/
//get the page count of the currently scanned document
final pageCount = await DocutainSdkDocument.pageCount();
//get the detected text of the currently scanned document, if any available
final text =
await DocutainSdkDocumentDataReader.getText();
//get the detected data of the currently scanned document, if any available
final data =
await DocutainSdkDocumentDataReader.analyze();
//get the application documents directory where we want to save the pdf or image file
final directory =
await getApplicationDocumentsDirectory();
//you can export the scanned pages as local JPG files
/*
for (var i = 1; i <= pageCount; i++) {
var fileReturn = await DocutainSdkDocument.writeImage(
i, directory.path, "Image$i.jpg");
}
*/
//You can also get the scanned pages as JPG Uint8List
//which you can use for further processing, for example wrapping it in ByteData
/*
for (var i = 1; i <= pageCount; i++) {
var bytes = await DocutainSdkDocument.getImageBytes(i,
pageSourceType: PageSourceType.cutFilter);
}
*/
//generate the pdf from the scanned document
//returns the file if pdf was successfully generated, returns null if pdf creation failed
File? pdfFile = await DocutainSdkDocument.writePDF(
directory.path, "testPDF");
if (pdfFile != null) {
//open the generated pdf file for demonstration purposes
OpenFile.open(pdfFile.path);
} else {
//pdf creation failed, get the last error
_showSnackbar(
"PDF creation failed. Reason:\n${await DocutainSdk.getLastError()}");
}
},
child: const Text('START SCAN'))
])),
);
}
void initDocutainSdk() async {
//initialize the sdk with your key
const licenseKey = "YOUR_LICENSE_KEY_HERE";
bool isDocutainPluginInitialized = await DocutainSdk.initSDK(licenseKey);
if (!isDocutainPluginInitialized) {
if (licenseKey == "YOUR_LICENSE_KEY_HERE") {
_showLicenseEmptyDialog();
} else{
_showLicenseErrorDialog(licenseKey);
}
//get the last error message
String error = await DocutainSdk.getLastError();
//implement handling to avoid accessing Docutain SDK when it is not initialized
}
//Reading payment state and BIC when getting the analyzed data is disabled by default
//If you want to analyze these 2 fields as well, you need to set the AnalyzeConfig accordingly
//A good place to do this, is right after initializing the Docutain SDK
var analyzeConfig = AnalyzeConfiguration();
analyzeConfig.readBIC = true;
analyzeConfig.readPaymentState = true;
if (!await DocutainSdkDocumentDataReader.setAnalyzeConfiguration(
analyzeConfig)) {
//get the last error message
String error = await DocutainSdk.getLastError();
}
//set the log level depending on your needs
await DocutainSdkLogger.setLogLevel(Level.verbose);
if (!mounted) return;
setState(() {
_isDocutainPluginInitialized = isDocutainPluginInitialized;
});
}
void _showSnackbar(String message) {
SnackBar snackBar = SnackBar(
content: Text(message),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
Future<void> _showLicenseEmptyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text('License needed'),
content: const SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(
'You need a trial license in order to run this example. You can generate a trial license key on our website for free.'),
],
),
),
actions: <Widget>[
TextButton(
child: const Text('Get trial license'),
onPressed: () async {
await launchUrl(Uri.parse(
'https://sdk.docutain.com/TrialLicense?Source=3277320'));
},
),
],
);
},
);
}
Future<void> _showLicenseErrorDialog(String licenseKey) async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text('License error'),
content: const SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(
'A valid license key is required. Please contact our support to get an extended trial license.'),
],
),
),
actions: <Widget>[
TextButton(
child: const Text('Contact Support'),
onPressed: () async {
await launchUrl(Uri.parse(
'mailto:support.sdk@Docutain.com?subject=Trial License Error&body=Please keep your following trial license key in this e-mail: $licenseKey'));
},
),
],
);
},
);
}
}