flutter_document_reader_btdevice_beta 0.0.12 flutter_document_reader_btdevice_beta: ^0.0.12 copied to clipboard
This is a flutter module for Regula document reader. It allows you to easily scan documents, for example passport, using your phone's camera. Supports Android and iOS
import 'dart:convert';
import 'dart:io' as io;
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart'
show EventChannel, PlatformException, rootBundle;
import 'package:flutter_document_reader_api_beta/document_reader.dart';
import 'package:image_picker/image_picker.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<List<String>> getImages() async {
setStatus("Processing image...");
List<XFile>? files = await ImagePicker().pickMultiImage();
List<String> result = [];
for (XFile file in files)
result.add(base64Encode(io.File(file.path).readAsBytesSync()));
return result;
}
Object setStatus(String s) => {setState(() => _status = s)};
String _status = "Loading...";
bool isReadingRfidCustomUi = false;
bool isReadingRfid = false;
String rfidUIHeader = "Reading RFID";
Color rfidUIHeaderColor = Colors.black;
String rfidDescription = "Place your phone on top of the NFC tag";
double rfidProgress = -1;
var _portrait = Image.asset('assets/images/portrait.png');
var _docImage = Image.asset('assets/images/id.png');
List<List<String>> _scenarios = [];
String _selectedScenario = "Mrz";
bool _canRfid = false;
bool _doRfid = false;
bool getDocumentReaderIsReady = false;
String btDeviceName = "Regula 0000";
bool isBleServiceConnected = false;
bool isBleDeviceReady = false;
var printError =
(Object error) => print((error as PlatformException).message);
@override
void initState() {
super.initState();
initPlatformState();
EventChannel('flutter_document_reader_api/event/completion')
.receiveBroadcastStream()
.listen((jsonString) => this.handleCompletion(
DocumentReaderCompletion.fromJson(json.decode(jsonString))!));
EventChannel('flutter_document_reader_api/event/database_progress')
.receiveBroadcastStream()
.listen(
(progress) => setStatus("Downloading database: " + progress + "%"));
EventChannel(
'flutter_document_reader_api/event/rfid_notification_completion')
.receiveBroadcastStream()
.listen((event) =>
print("rfid_notification_completion: " + event.toString()));
EventChannel('flutter_document_reader_api/event/bleOnServiceConnectedEvent')
.receiveBroadcastStream()
.listen((event) => bleOnServiceConnected());
EventChannel(
'flutter_document_reader_api/event/bleOnServiceDisconnectedEvent')
.receiveBroadcastStream()
.listen((event) => bleOnServiceDisconnected());
EventChannel('flutter_document_reader_api/event/bleOnDeviceReadyEvent')
.receiveBroadcastStream()
.listen((event) => bleOnDeviceReady());
}
Future<void> initPlatformState() async {
print(await DocumentReader.prepareDatabase("FullAuth"));
setStatus("Database prepared");
}
void bleOnServiceConnected() {
print("bleService connected, searching devices");
setState(() => isBleServiceConnected = true);
Future.delayed(const Duration(milliseconds: 7000), () {
if (!isBleDeviceReady) {
print("Failed to connect to the torch device");
setStatus("Failed to connect to the torch device");
}
});
}
void bleOnServiceDisconnected() {
print("bleService disconnected");
setState(() => isBleServiceConnected = false);
}
void bleOnDeviceReady() {
print("device connected, initializing");
setStatus("Initializing...");
setState(() => isBleDeviceReady = true);
DocumentReader.initializeReaderBleDeviceConfig()
.then((value) => {onInitCompleted()});
}
checkPermissionsAndConnect() {
DocumentReader.isBlePermissionsGranted().then((granted) {
if (granted) {
this.setStatus("Loading...");
if (!isBleServiceConnected) {
print("connecting bleService");
DocumentReader.setConfig({
"functionality": {
"useAuthenticator": true,
"btDeviceName": btDeviceName
}
}).then((s) => DocumentReader.startBluetoothService());
} else
print("bleService already connected");
} else
setStatus("ble permissions denied");
});
}
void addCertificates() async {
List certificates = [];
final manifestJson =
await DefaultAssetBundle.of(context).loadString('AssetManifest.json');
final certPaths = json
.decode(manifestJson)
.keys
.where((String key) => key.startsWith('assets/certificates'));
for (var path in certPaths) {
var findExt = path.split('.');
var pkdResourceType = 0;
if (findExt.length > 0)
pkdResourceType =
PKDResourceType.getType(findExt[findExt.length - 1].toLowerCase());
ByteData byteData = await rootBundle.load(path);
var certBase64 = base64.encode(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
certificates
.add({"binaryData": certBase64, "resourceType": pkdResourceType});
}
DocumentReader.addPKDCertificates(certificates)
.then((value) => print("certificates added"));
}
void handleCompletion(DocumentReaderCompletion completion) {
if (isReadingRfidCustomUi &&
(completion.action == DocReaderAction.CANCEL ||
completion.action == DocReaderAction.ERROR)) this.hideRfidUI();
if (isReadingRfidCustomUi &&
completion.action == DocReaderAction.NOTIFICATION)
this.updateRfidUI(completion.results!.documentReaderNotification);
if (completion.action ==
DocReaderAction.COMPLETE) if (isReadingRfidCustomUi) if (completion
.results!.rfidResult !=
1)
this.restartRfidUI();
else {
this.hideRfidUI();
this.displayResults(completion.results!);
}
else
this.handleResults(completion.results!);
if (completion.action == DocReaderAction.TIMEOUT)
this.handleResults(completion.results!);
if (completion.action == DocReaderAction.CANCEL ||
completion.action == DocReaderAction.ERROR) isReadingRfid = false;
}
void showRfidUI() {
// show animation
setState(() => isReadingRfidCustomUi = true);
}
hideRfidUI() {
// show animation
this.restartRfidUI();
DocumentReader.stopRFIDReader();
setState(() {
isReadingRfidCustomUi = false;
rfidUIHeader = "Reading RFID";
rfidUIHeaderColor = Colors.black;
});
}
restartRfidUI() {
setState(() {
rfidUIHeaderColor = Colors.red;
rfidUIHeader = "Failed!";
rfidDescription = "Place your phone on top of the NFC tag";
rfidProgress = -1;
});
}
updateRfidUI(results) {
if (results.code ==
ERFIDNotificationCodes.RFID_NOTIFICATION_PCSC_READING_DATAGROUP)
setState(() => rfidDescription = results.number);
setState(() {
rfidUIHeader = "Reading RFID";
rfidUIHeaderColor = Colors.black;
rfidProgress = results.value / 100;
});
if (Platform.isIOS)
DocumentReader.setRfidSessionStatus(
rfidDescription + "\n" + results.value.toString() + "%");
}
customRFID() {
this.showRfidUI();
DocumentReader.readRFID();
}
usualRFID() {
isReadingRfid = true;
DocumentReader.startRFIDReader();
}
void onInitCompleted() async {
setStatus("Ready");
bool canRfid = await DocumentReader.isRFIDAvailableForUse();
setState(() => _canRfid = canRfid);
List<List<String>> scenarios = [];
var scenariosTemp =
json.decode(await DocumentReader.getAvailableScenarios());
for (var i = 0; i < scenariosTemp.length; i++) {
DocumentReaderScenario scenario = DocumentReaderScenario.fromJson(
scenariosTemp[i] is String
? json.decode(scenariosTemp[i])
: scenariosTemp[i])!;
scenarios.add([scenario.name!, scenario.caption!]);
}
setState(() => _scenarios = scenarios);
DocumentReader.setConfig({
"functionality": {
"videoCaptureMotionControl": true,
"showCaptureButton": true
},
"customization": {
"showResultStatusMessages": true,
"showStatusMessages": true
},
"processParams": {"scenario": _selectedScenario}
});
DocumentReader.setRfidDelegate(RFIDDelegate.NO_PA);
// addCertificates();
}
displayResults(DocumentReaderResults results) async {
var name = await results.textFieldValueByType(EVisualFieldType.FT_SURNAME_AND_GIVEN_NAMES);
var doc = await results.graphicFieldImageByType(EGraphicFieldType.GF_DOCUMENT_IMAGE);
var portrait = await results.graphicFieldImageByType(EGraphicFieldType.GF_PORTRAIT);
setState(() {
_status = name ?? "";
_docImage = Image.asset('assets/images/id.png');
_portrait = Image.asset('assets/images/portrait.png');
if (doc != null)
_docImage = Image.memory(doc.data!.contentAsBytes());
if (portrait != null)
_portrait = Image.memory(portrait.data!.contentAsBytes());
});
}
void handleResults(DocumentReaderResults results) {
if (_doRfid && !isReadingRfid && results.chipPage != 0) {
// customRFID();
usualRFID();
} else {
isReadingRfid = false;
displayResults(results);
}
}
void onChangeRfid(bool? value) {
setState(() => _doRfid = value! && _canRfid);
DocumentReader.setConfig({
"processParams": {"doRfid": _doRfid}
});
}
Widget createImage(
String title, double height, double width, ImageProvider image) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(title),
Image(height: height, width: width, image: image)
]);
}
Widget createButton(String text, VoidCallback onPress) {
return Container(
padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
transform: Matrix4.translationValues(0, -7.5, 0),
child: TextButton(
style: TextButton.styleFrom(
backgroundColor: Color.fromARGB(50, 10, 10, 10)),
onPressed: onPress,
child: Text(text)),
width: 150,
);
}
Widget _buildRow(int index) {
Radio radio = new Radio(
value: _scenarios[index][0],
groupValue: _selectedScenario,
onChanged: (value) => setState(() {
_selectedScenario = value;
DocumentReader.setConfig({
"processParams": {"scenario": _selectedScenario}
});
}));
return Container(
child: ListTile(
title: GestureDetector(
onTap: () => radio.onChanged!(_scenarios[index][0]),
child: Text(_scenarios[index][1])),
leading: radio),
padding: EdgeInsets.only(left: 40));
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Center(child: Text(_status))),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Visibility(
visible: isReadingRfidCustomUi,
child: Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[]),
Container(
child: Text(rfidUIHeader,
textScaleFactor: 1.75,
style: TextStyle(color: rfidUIHeaderColor)),
padding: EdgeInsets.only(bottom: 40)),
Container(
child:
Text(rfidDescription, textScaleFactor: 1.4),
padding: EdgeInsets.only(bottom: 40)),
FractionallySizedBox(
widthFactor: 0.6,
child: LinearProgressIndicator(
value: rfidProgress,
minHeight: 10,
valueColor: new AlwaysStoppedAnimation<Color>(
Color(0xFF4285F4)))),
TextButton(
onPressed: () => hideRfidUI(),
child: Text("X"),
style: TextButton.styleFrom(
padding: EdgeInsets.only(top: 50)),
),
]))),
Visibility(
visible: !isReadingRfidCustomUi,
child: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
createImage(
"Portrait", 150, 150, _portrait.image),
createImage("Document image", 150, 200,
_docImage.image),
]),
Expanded(
child: Container(
color: Color.fromARGB(5, 10, 10, 10),
child: ListView.builder(
itemCount: _scenarios.length,
itemBuilder:
(BuildContext context, int index) =>
_buildRow(index)))),
CheckboxListTile(
value: _doRfid,
onChanged: onChangeRfid,
title: Text(
"Process rfid reading ${_canRfid ? "" : "(unavailable)"}")),
Padding(
padding: EdgeInsets.only(bottom: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("btDeviceName: "),
SizedBox(
width: 120,
child: TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'btDeviceName'),
onChanged: (text) {
setState(() => btDeviceName = text);
},
initialValue: btDeviceName,
),
),
])),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
createButton("Scan document",
() => DocumentReader.showScanner()),
createButton("Start service",
() => checkPermissionsAndConnect()),
])
]))),
])),
);
}
}