flutter/dart : How to close camera after continuous few barcodes scanning - flutter

I have used flutter_barcode_scanner: ^2.0.0 package to scan barcodes it work fine but I scan continuously and after few barcodes i want to close the camera and return back to screen now I am stock so how the camera is closed after scanning few barcodes.
the following is a scenario I wont to implement
scanBarcode() {
FlutterBarcodeScanner.getBarcodeStreamReceiver(
"#ff6666",
"Cancel",
false,
ScanMode.DEFAULT,
)!
.listen(
(barcode) {
setState(() {
list.add(barcode);
});
if (list.length == 10) {
// I want to close camera here and show page again?
}
},
);
}

I had the same issue. The workaround is to loop on single scan. So as a result you can still continue to use flutter_barcode_scanner package :).
In my case i don't need to call setState or something like to update the UI but you can do it if you need.
Future<String?> _scanBarcodeNormal() async {
String? barcodeScanRes;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
barcodeScanRes = await FlutterBarcodeScanner.scanBarcode('#ff6666', 'Cancel', true, ScanMode.BARCODE);
} on PlatformException {
barcodeScanRes = 'Failed to get platform version.';
}
return barcodeScanRes;
}
void _scanBarCodeListAndFetchData() async{
String? barcode = await _scanBarcodeNormal();
final List<String> barcodeList = [];
// continue scanning
while(barcode != null){
if(barcode == "-1"){ // cancel button -> -1
barcode = null;
}
// add the barcode
else {
// avoid duplicates
if(!barcodeList.contains(barcode)){
barcodeList.add(barcode);
}
// you can also call setState(() {....} here
if (barcodeList.length == 10) {
barcode = null; // out !
}
else{ // next scan
barcode = await _scanBarcodeNormal();
}
}
}
if(barcodeList.isEmpty) {
UiUtils.showToast(message: "No barcode scanned, abort", toastLength: Toast.LENGTH_SHORT);
}
else{
UiUtils.showToast(message: "${barcodeList.length} barcodes scanned", toastLength: Toast.LENGTH_SHORT);
// your work
}
}

Related

How to pass data from a Barcode scanner to a Textfield (Flutter)

I am using the 'flutter_barcode_scanner' package and I want to pass some data from the barcode scanner to a TextField in the app that I am working on.
I have a TextEditingController like this:
var searchController = TextEditingController();
And the code I use for the barcode scanner is this:
Future<void> scanBarcodeNormal() async {
String barcodeScanRes;
try {
barcodeScanRes = await FlutterBarcodeScanner.scanBarcode('#ff6666', 'Cancel', true, ScanMode.BARCODE);
print(barcodeScanRes);
} on PlatformException {
barcodeScanRes = 'Cihazınız barkod okumayı desteklemiyor.';
}
if (!mounted) return;
setState(() {
_scanBarcode = barcodeScanRes;
});
}
I know that I need to change some things in the last part,
if (!mounted) return;
setState(() {
_scanBarcode = barcodeScanRes;
});
I want to replace the setState(() {}) with a code that achieves what I want (Passing the data from the barcode to the TextField.)
I am trying to replace the setState(() {}) of the barcode scanner with a code that passes the data to TextField.
Try replacing this statement
setState(() {
_scanBarcode = barcodeScanRes;
});
With this
searchController.text = barcodeScanRes;
Gist: https://gist.github.com/SteplerPaulo/cee0e6f03fb8c1b7a5014074f665594b

Switching stream with Flutter WebRTC seems to fail

I'm trying to switch from the front to back camera using Flutter WebRTC but cannot get it working.
I have the following
// Stop the current stream and remove the tracks
await Future.forEach(videoStream!.getVideoTracks(), (MediaStreamTrack? track) async {
if (track != null) {
try {
await track.stop();
await videoStream!.removeTrack(track);
} catch (e) {
if (kDebugMode) {
print(e);
}
}
}
});
videoStream!.getVideoTracks().forEach((track) {
track.stop();
videoStream!.removeTrack(track, removeFromNative: true);
});
final mediaConstraints = {
'audio': false, // NO need to capture audio again
'video': {
'deviceId': videoInputDeviceId,
}
};
MediaStream newStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
final newTrack = newStream.getVideoTracks()[0];
await videoStream!.addTrack(newTrack, addToNative: true);
Getting the following errors if I place try catch around them
flutter: PlatformException(mediaStreamRemoveTrack: Track is nil, null, null, null)
flutter: !--- Event: Failed to enable webcam
flutter: Concurrent modification during iteration: Instance(length:0) of '_GrowableList'.

An alert dialog is not displayed at the widget load, why?

In my application I am reading a qr code with the flutter_barcode_scanner package, and when reading a valid code it is supposed to show me an alert dialog saying that it is correct, otherwise, well, no.
To implement this package, an example tells us that based on an action (such as pressing a button) start the scanning method, and save what is read in a variable. Thus:
Future<void> scanQr() async {
try {
final qrCode = await FlutterBarcodeScanner.scanBarcode(
'#ffffff', 'Cancel', true, ScanMode.QR);
if (!mounted) {
return;
}
setState(() {
this.qrCode = qrCode.isEmpty
? 'EMPTY'
: qrCode == '-1'
? 'INVALID'
: qrCode;
});
} on PlatformException {
qrCode = 'fail';
}
}
We can see what the set state occupies in order to update the value. This in a variable that, as you can see, is called qrCode. Which in the example puts it in a text widget and it works fine. when reading something, it is updated.
So, what I want to do is a simple validation, and based on said validation, show an alertdialog saying if what was read in the qr is right or wrong.
I have my validation in the same setstate, I ask if a certain part of the read string looks like what I want. Likewise, I have an int variable, which when updated in the set state, draws an alertdialog.
Future<void> scanQr() async {
try {
final qrCode = await FlutterBarcodeScanner.scanBarcode(
'#ffffff', 'Cancel', true, ScanMode.QR);
if (!mounted) {
return;
}
setState(() {
this.qrCode = qrCode.isEmpty
? 'EMPTY'
: qrCode == '-1'
? 'INVALID'
: qrCode;
});
if (qrCode.substring(0, 2) == 'somepattern') {
setState(() {
value = 1;
});
} else {
setState(() {
value = 2;
});
}
//saveContact(qrCode);
} on PlatformException {
qrCode = 'fail';
}
}
In the build method I have:
String qrCode = '';
int value = 0;
#override
Widget build(BuildContext context) {
//Future(() async {
(value == 1)
? alerta('Yeah', "This code are right!")
: (value == 2)
? alerta(
'Oh no!', 'An invalid qr code')
: null;
//});
return Scaffold(...
As you can see, I even try it with a future to give it time to draw, but it doesn't show any alertDialog. The text widget with the each is displayed. Even, i print the value, and its right, prints 2 and 1 respectively; but the alert dialog is never showed
Why doesn't it draw my alert dialog? What am I doing wrong?
Instead of writing the alert dialog logic inside build method, you should have it in scanQR method
Future<void> scanQr() async {
try {
final qrCode = await FlutterBarcodeScanner.scanBarcode(
'#ffffff', 'Cancel', true, ScanMode.QR);
if (!mounted) {
return;
}
setState(() {
this.qrCode = qrCode.isEmpty
? 'EMPTY'
: qrCode == '-1'
? 'INVALID'
: qrCode;
});
if (qrCode.substring(0, 2) == 'somepattern') {
setState(() {
value = 1;
alerta('Yeah', "This code are right!");
});
} else {
setState(() {
value = 2;
alerta(
'Oh no!', 'An invalid qr code');
});
}
//saveContact(qrCode);
} on PlatformException {
qrCode = 'fail';
}
}
Try this and let me know.

Barcode crash without errors

I am making an app using the qrCode scanner and when i open the app on my iphone and touch the button for the qrCode scanning it shuts down automatically , not opening even the camera.I used barcode_scan in pubspec.yaml and the code is:
String qrResult = "Not yet Scanned";
onPressed: () async {
String scaning = await BarcodeScanner.scan();
setState(() {
qrResult = scaning;
});
},
The app is made in flutter
Please You can use this package flutter_barcode_scanner 1.0.1 to make your Work Simple.Cheers!!
scan() async {
try {
dynamic bar = await BarcodeScanner.scan();
if(bar != null && bar.isNotEmpty){
print(" scanning qrcode ------------------------ $barcode");
setState(() {
barcode = bar;
});
}} on PlatformException catch (e) {
setState(() => this.barcode = '');
} on FormatException{
setState(() => this.barcode = '');
} catch (e) {
setState(() => this.barcode = '');
}
}

How to synchronize a call from the asynchronous function in dart

I am working on my first app in Flutter, I have a bit of experience with Java and js, but I never worked with flutter before so sorry if my question will seem ridiculous to you.
The app is the voice assistant chatbot, and it is supposed to perform text to speech on each new message that customer receives, my problem is that since I am using firebase messaging all of the requests that I receive are in the asynchronous call, but I need to synchronize the access to the text to speech service otherwise I run into problem of having one text interrupt another.
This is what my code looks like at the moment:
Firebase messaging:
onMessage: (Map<String, dynamic> message) {
return this.handleBotMessage(appState, message);
},
Method that desides how to handle each particular message:
Future handleBotMessage(
Store<AppState> store,
Map<String, dynamic> dataJson,
) {
#logic that convert the message into json and extracts the message type
if (type == MessageType.CHAT_MESSAGE) {
return handleChatMessage(store, subtype, messageMap);
}
}
The method that handles text messages:
Future<dynamic> handleChatMessage(
Store<AppState> store,
MessageSubtype subtype,
Map<String, dynamic> message,
) {
#Text to speach is build as a singleton and this always returns the same instance
TextToSpeech tts = TextToSpeech();
if (subtype == MessageSubtype.TEXT) {
TextMessage textMessage = TextMessage.fromJson(message);
return tts
.speak(textMessage.text)
.then((result) => store.dispatch(NewBotMessageAction(textMessage)));
} else if (subtype == MessageSubtype.QUICK_REPLY) {
QuickReplyMessage qrMessage = QuickReplyMessage.fromJson(message);
return tts
.speak(qrMessage.text)
.then((result) => store.dispatch(NewQrOptionsAction(qrMessage)));
} else {
throw new Exception('Unexpected message subtype!');
}
}
The method that actually performs the text to speech
Future<dynamic> speak(String text) async {
return flutterTts.speak(text).then((resp) {
ttsRunning = false;
print(resp);
return resp;
}, onError: (obj, st) {
ttsRunning = false;
print(obj);
print(st.toString());
});
}
Text to speech initialization
Future init() async {
await flutterTts.setLanguage("en-US");
var res = await flutterTts.isLanguageAvailable("en-US");
print(res);
return res;
}
https://pub.dev/packages/flutter_tts
Ok, I have found the solution, the issue was as frank06 pointed out with the fact that flutter tts completes the future immediately rather than after the whole phrase was spoken.
So here is my solution, it is not perfect, but it works:
Completer completer;
Future<dynamic> speak(String text) {
print('Started speeking');
print(new DateTime.now().toIso8601String());
if (TextToSpeech.lastRequest == null) {
lastRequest = _executeSpeech(text);
} else {
lastRequest = lastRequest.then((resp) {
return _executeSpeech(text);
});
}
return lastRequest;
}
Future<dynamic> _executeSpeech(String text) {
completer = Completer();
flutterTts.speak(text).then((resp) {
ttsRunning = false;
print(resp);
return resp;
}, onError: (obj, st) {
ttsRunning = false;
print(obj);
print(st.toString());
});
return completer.future;
}
flutterTts.setCompletionHandler(() {
print('Finished speeking');
print(new DateTime.now().toIso8601String());
ttsState = TtsState.stopped;
completer.complete(ttsState);
});
flutterTts.setErrorHandler((msg) {
ttsState = TtsState.stopped;
completer.complete(ttsState);
});
If you don't want new messages interrupting those being spoken, you can queue them up. This way the new messages will wait for the current message to finish. Check out this approach:
Queue of Future in dart