freedelity / flutter_native_barcode_scanner

Fast barcode/QR scanner flutter plugin using PlatformView and processing on native side
https://pub.dev/packages/native_barcode_scanner
BSD 3-Clause "New" or "Revised" License
6 stars 8 forks source link

Error: metadataObjects array is nil or doesn't contain any object (iOS) #26

Closed tmpfs closed 3 months ago

tmpfs commented 4 months ago

Hi,

Sometimes I am getting this error when scanning but it happens intermittently so I don't know if it's a bug or an edge case that I should handle (ask the user to try again?). I am seeing it on iOS so not sure if it happens on Android too.

Full exception message looks like this:

PlatformException(native_scanner_failed, metaDataObjects array is nil or doesn't contain any object, null, null)

Any idea what is causing this?

Thanks!

Verbruik commented 3 months ago

Hi !

Actually it's because the reader is already closed when this error happens and it is returned because the output is empty. So instead of restart the reader directly from iOS without sending any information I let the Flutter part manage it and restart the scanner if necessary.

See in BarcodeScannerController.swift

    public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {

        // Check if the metadataObjects array is not nil and it contains at least one object.
        if metadataObjects.count == 0 {
            barcodeStream?(FlutterError(code: "native_scanner_failed", message: "metadataObjects array is nil or doesn't contains any object", details: nil))
            return
        }

        // Get the metadata object.
        let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
        if supportedCodeTypes.contains(metadataObj.type) {
            if metadataObj.stringValue != nil {
                barcodeStream?(["barcode": metadataObj.stringValue!, "format": convertBarcodeType(type: metadataObj.type)])
            }
        } else {
            barcodeStream?(FlutterError(code: "native_scanner_failed", message: "unsupported barcode type", details: "barcode type : \(metadataObj.type)"))
            barcodeStream?(["barcode": "", "format": -1])
        }
    }
tmpfs commented 3 months ago

Thanks for clarifying, do you have some example code that handles this error and restarts the view as it doesn't seem to work for me.

I catch the error, update the parent state to re-render (giving the child BarcodeScannerWidget a UniqueKey) and it fails to trigger a scan afterwards. I also encountered this error:

flutter: ══╡ EXCEPTION CAUGHT BY SERVICES LIBRARY ╞══════════════════════════════════════════════════════════
flutter: The following PlatformException was thrown while de-activating platform stream on channel
flutter: be.freedelity/native_scanner/imageStream:
flutter: PlatformException(error, No active stream to cancel, null, null)
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:648:7)
flutter: #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:334:18)
flutter: <asynchronous suspension>
flutter: #2      EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:688:9)
flutter: <asynchronous suspension>
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════

I think it would be better to perhaps handle this in the native code and keep trying to scan.

Edit: setting stopScanOnBarcodeDetected to false allows it to continue scanning when this error occurs, seems to work ok.

Verbruik commented 3 months ago

Edit: setting stopScanOnBarcodeDetected to false allows it to continue scanning when this error occurs, seems to work ok.

Indeed as it's an empty barcode detected, the scanner is stopped, si with this it wont stop until you ask manually with BarcodeScanner.stopScanner(). Otherwise, you can restart the scanner with BarcodeScanner.startScanner()

Glad to see that you fixed it by yourself, If you have any other suggestion to improve the plugin do not hesitate ;-)

Mathieu.