My qr code scanner stopped working on Android and I do not understand why... It worked previously and the scanner still works on iOS.
Firebase ML kit simply returns an empty list when scanning and I have tried many different android devices and QR codes but none work (anymore).
I have tried to clean and reinstall all dependencies, I tried to clear all data in Google Play services and reinstalled the app (so that it reinstalls the ML model)
I had an idea that it could possibly be the image format that is not correct, the format from the camera is in YUV_420_888 and I think it is converted into NV21 with the code below, but not 100% sure how that works.
What's annoying is that this did work before but suddenly stoped working.
This is my implementation of the QR scanner it recieves an image from the camera stream
class QRCodeReader {
BarcodeDetector _barcodeDetector = FirebaseVision.instance.barcodeDetector(BarcodeDetectorOptions(barcodeFormats: BarcodeFormat.qrCode));
void dispose() {
_barcodeDetector.close();
}
void scanImage(CameraImage availableImage, ScanCompleted scanCompleted) async {
final FirebaseVisionImageMetadata metadata = FirebaseVisionImageMetadata(
rawFormat: availableImage.format.raw,
size: Size(availableImage.width.toDouble(), availableImage.height.toDouble()),
planeData: availableImage.planes.map((currentPlane) => FirebaseVisionImagePlaneMetadata(
bytesPerRow: currentPlane.bytesPerRow,
height: currentPlane.height,
width: currentPlane.width
)).toList(),
rotation: ImageRotation.rotation0,
);
final FirebaseVisionImage visionImage = FirebaseVisionImage.fromBytes(availableImage.planes[0].bytes, metadata);
//this list is empty on android
List barCodes = await _barcodeDetector.detectInImage(visionImage);
for(Barcode barcode in barCodes) {
//process barcode...
}
scanCompleted();
}
}
I initialize the stream like this...
_initializeControllerFuture = _controller.initialize();
_initializeControllerFuture.whenComplete(() {
setState((){
_controller.startImageStream(_handleImageStream);
});
});
void _handleImageStream(CameraImage availableImage) {
if (!_isScanning && !_disposed) {
final state = Provider.of<ScannerState>(context);
_isScanning = true;
qrReader.scanImage(availableImage, () => _isScanning = false);
}
}
app/build.gradle
...
dependencies {
...
api 'com.google.firebase:firebase-ml-vision-image-label-model:17.0.2'
}
apply plugin: 'com.google.gms.google-services'
build.gradle
buildscript {
...
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
classpath 'com.google.gms:google-services:4.2.0'
}
}
AndroidManifest.xml
...
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<application
android:name="io.flutter.app.FlutterApplication"
...>
<meta-data
android:name="com.google.firebase.ml.vision.DEPENDENCIES"
android:value="barcode" />
...
</application>
pubspec.yaml
...
dependencies:
...
camera: ^0.5.4+2
firebase_core: ^0.4.0+9
cloud_firestore: ^0.12.9+4
cloud_functions: ^0.4.1+1
firebase_ml_vision: ^0.9.2+1
...
Edit: As suggested by Frank, the issue was the resolution setting on the camera, if it is to low the QR code cannot be detected. Putting it on "high" or higher sovles this problem.
I solved this issue by rolling back the camera plugin to version: "camera: ^0.5.2+2"
Not sure what exactly breaks the ML vision package for android in the newer version, but this solved the issue for now.