DrafaKiller / CodeScanner-flutter

A flexible code scanner for QR codes, barcodes and many others. Using Google's ML Kit. Use it as a Widget with a camera or use the methods provided, with a camera controller.
MIT License
11 stars 4 forks source link

Possibly broken on Android 12 #1

Closed umangsh closed 2 years ago

umangsh commented 2 years ago

barcode scan doesn't work for me on Pixel 3 and Pixel 5, Android 12. The camera switches on, but nothing happens when pointed at a barcode. Barcode detection works fine on iOS. Flutter logs:

I/Camera (20069): close W/Camera (20069): The selected imageFormatGroup is not supported by Android. Defaulting to yuv420 I/Camera (20069): startPreview I/Camera (20069): CameraCaptureSession onConfigured I/Camera (20069): Updating builder settings D/Camera (20069): Updating builder with feature: ExposureLockFeature D/Camera (20069): Updating builder with feature: ExposurePointFeature I/Camera (20069): closeCaptureSession D/Camera (20069): Updating builder with feature: ZoomLevelFeature D/Camera (20069): Updating builder with feature: AutoFocusFeature D/Camera (20069): Updating builder with feature: NoiseReductionFeature I/Camera (20069): updateNoiseReduction | currentSetting: fast D/Camera (20069): Updating builder with feature: FocusPointFeature D/Camera (20069): Updating builder with feature: ResolutionFeature D/Camera (20069): Updating builder with feature: SensorOrientationFeature D/Camera (20069): Updating builder with feature: FlashFeature D/Camera (20069): Updating builder with feature: ExposureOffsetFeature D/Camera (20069): Updating builder with feature: FpsRangeFeature I/Camera (20069): refreshPreviewCaptureSession I/Camera (20069): refreshPreviewCaptureSession: captureSession not yet initialized, skipping preview capture session refresh. I/Camera (20069): CameraCaptureSession onClosed I/Camera (20069): startPreviewWithImageStream I/Camera (20069): CameraCaptureSession onConfigured I/Camera (20069): Updating builder settings D/Camera (20069): Updating builder with feature: ExposureLockFeature D/Camera (20069): Updating builder with feature: ExposurePointFeature D/Camera (20069): Updating builder with feature: ZoomLevelFeature D/Camera (20069): Updating builder with feature: AutoFocusFeature D/Camera (20069): Updating builder with feature: NoiseReductionFeature I/Camera (20069): updateNoiseReduction | currentSetting: fast D/Camera (20069): Updating builder with feature: FocusPointFeature D/Camera (20069): Updating builder with feature: ResolutionFeature D/Camera (20069): Updating builder with feature: SensorOrientationFeature D/Camera (20069): Updating builder with feature: FlashFeature D/Camera (20069): Updating builder with feature: ExposureOffsetFeature D/Camera (20069): Updating builder with feature: FpsRangeFeature I/Camera (20069): refreshPreviewCaptureSession W/System (20069): A resource failed to call release. W/System (20069): A resource failed to call release. D/TransportRuntime.SQLiteEventStore(20069): Storing event with priority=VERY_LOW, name=FIREBASE_ML_SDK for destination cct D/TransportRuntime.JobInfoScheduler(20069): Upload for context TransportContext(cct, VERY_LOW, 90bzNc) is already scheduled. Returning... D/TransportRuntime.SQLiteEventStore(20069): Storing event with priority=DEFAULT, name=FIREBASE_ML_SDK for destination cct D/TransportRuntime.JobInfoScheduler(20069): Upload for context TransportContext(cct, DEFAULT, 90bzNc) is already scheduled. Returning... D/TransportRuntime.SQLiteEventStore(20069): Storing event with priority=VERY_LOW, name=FIREBASE_ML_SDK for destination cct D/TransportRuntime.JobInfoScheduler(20069): Upload for context TransportContext(cct, VERY_LOW, 90bzNc) is already scheduled. Returning... D/TransportRuntime.SQLiteEventStore(20069): Storing event with priority=VERY_LOW, name=FIREBASE_ML_SDK for destination cct D/TransportRuntime.JobInfoScheduler(20069): Upload for context TransportContext(cct, VERY_LOW, 90bzNc) is already scheduled. Returning...

Saw this in the logs once, doesn't trigger consistently, could be related:

E/AndroidRuntime(16318): FATAL EXCEPTION: pool-7-thread-1 E/AndroidRuntime(16318): java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface! E/AndroidRuntime(16318): at android.hardware.camera2.CaptureRequest.convertSurfaceToStreamId(CaptureRequest.java:739) E/AndroidRuntime(16318): at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:1259) E/AndroidRuntime(16318): at android.hardware.camera2.impl.CameraDeviceImpl.setRepeatingRequest(CameraDeviceImpl.java:1315) E/AndroidRuntime(16318): at android.hardware.camera2.impl.CameraCaptureSessionImpl.setRepeatingRequest(CameraCaptureSessionImpl.java:313) E/AndroidRuntime(16318): at io.flutter.plugins.camera.Camera.refreshPreviewCaptureSession(Camera.java:510) E/AndroidRuntime(16318): at io.flutter.plugins.camera.Camera.access$900(Camera.java:100) E/AndroidRuntime(16318): at io.flutter.plugins.camera.Camera$2.onConfigured(Camera.java:440) E/AndroidRuntime(16318): at android.hardware.camera2.impl.CallbackProxies$SessionStateCallbackProxy.lambda$onConfigured$0$CallbackProxies$SessionStateCallbackProxy(CallbackProxies.java:53) E/AndroidRuntime(16318): at android.hardware.camera2.impl.CallbackProxies$SessionStateCallbackProxy$$ExternalSyntheticLambda4.run(Unknown Source:4) E/AndroidRuntime(16318): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) E/AndroidRuntime(16318): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) E/AndroidRuntime(16318): at java.lang.Thread.run(Thread.java:920)

DrafaKiller commented 2 years ago

I have tried to replicate this issue in 5 different devices using this package, I couldn't get the same issue.

QR Code:

Barcode and QR Code:

It's working fine on all of them. Maybe it has something to do with how you used it. If you think it would be useful to share how to replicate it, feel free to do so.


This issue was also reported in the ML Kit plugin dependency, so I will be closing this one and follow it there. bharat-biradar/Google-Ml-Kit-plugin#285

umangsh commented 2 years ago

Thanks for looking into this bug. I can verify that it works on emulators - Pixel 3 / Android 9 and Pixel 5 / Android 12 with laptop webcam work fine. On device, Pixel 3 / Android 12 doesn't work. The scanner window remains open without detecting barcode: https://streamable.com/4susyn

The scanner widget is straightforward, unclear if an Android specific setting might be missing:

class SearchScanner extends StatefulWidget {
  const SearchScanner({Key? key}) : super(key: key);

  @override
  State<SearchScanner> createState() => _SearchScannerState();
}

class _SearchScannerState extends State<SearchScanner>
    with TickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    return CodeScanner(
      onScan: (code, details, controller) {
        getSearchResultsWithQuery(barcode: code);
      },
      onAccessDenied: (error, controller) {
        clearSearchBar();
        return false;
      },
      formats: const [
        BarcodeFormat.upca,
        BarcodeFormat.upce,
        BarcodeFormat.ean8,
        BarcodeFormat.ean13,
      ],
      once: true,
    );
  }
}
DrafaKiller commented 2 years ago

I emulated Pixel 3, Android 12 (API 31, android-x64) and still couldn't replicate.

It was able to scan the exact barcode you tried to scan, and the same logs. However, I didn't get the fatal exception.

If it is an Android specific setting, then I'm not aware of it, mainly because if there was it should have been in the ML Kit plugin dependency.

I really wish I could replicate it, so I could test on it to have any idea.

Something I should note

The reason why the scanner window remains open, is that the camera and the barcode scanning are running separately, which means if the scanning stops, the camera will continue running. It would be up to the developer to notify the user or to disable the camera, if there's an unexpected error with the scanning.

I will be adding an onError callback, to make it easier. However, I haven't caught any error to be able to test it.

umangsh commented 2 years ago

Pixel 3 / Android 12 emulator works fine for me as well. The error happens only on device with Android 12 afaict. Were you able to test on a physical device with Android 12?

DrafaKiller commented 2 years ago

Were you able to test on a physical device with Android 12?

Yes, I tested it on a Samsung Galaxy Tab S6 Lite, Android 12, physically. However, it's a tablet device. I tried it again with the barcode you tried, it worked fine.

It's odd, it seems to be only from Pixel devices, physically. But I can't confirm that because I don't have any here to test it on.

sorgfal commented 2 years ago

I have exactly the same problems with Nokia x20 with google services. I can help with remote debug

umangsh commented 2 years ago

I just tested this on a lenovo Tablet with Android 10 and the scanner works on device. To summarize:

  1. Works on emulators - Pixel 3, Pixel5 with Android 12, Pixel 3 with Android 9.
  2. Works on device - lenovo Tab with Android 10.
  3. Works on Samsung Galaxy Tab S6 Lite, Android 12.
  4. Does NOT work on Pixel 3 and Pixel 5 with Android 12.
  5. Does NOT work on Nokia x20, with google services, Android version unknown.

Very strange.

DrafaKiller commented 2 years ago

I think we should get another confirmation with a different device of the same model. Right now we have nothing to use, other than to speculate. Perhaps it's not the model, maybe a setting or a permission.

If 2 devices of the same model have the same problem, then we can put uncertainty aside. The only coincidence we have is that devices closer to Google are failing, but then emulators work.

Resetting the device to factory settings and testing it again could maybe bring something. But that might be inconvenient, with no guarantees.

Can someone else confirm using Pixel 3, Pixel 5 or Nokia x20, Android 12?

umangsh commented 2 years ago

FWIW, I've tested it on two separate Pixel 3s with Android 12 (both broken). Hopefully, others can chime in as well. I like your onError callback suggestion, improves user experience.

DrafaKiller commented 2 years ago

I have done a workaround, although not a fix, it was commented a possible solution for this issue.

The resolution of the camera controller seems to have an affect. I haven't done much testing to actually find any real fix but I was able to get a device that appears having the same issue, Android 10, and setting it to high makes it work on both devices.

I changed the default resolution of this package from medium to high and added an warning on the resolution variable documentation, to avoid most frustrating issues. But this may cause low-end devices to struggle, so it's always an option for the developer to lower it to low resolution.


This comment confirms what seems to be the same issue. https://github.com/bharat-biradar/Google-Ml-Kit-plugin/issues/285#issuecomment-1184315840

If this is the issue, sadly I can't do anything other than what I'm already did on the newer version. Unless someone has a solution for this issue that can be implemented on this end, which I will gladly take.

@umangsh Can you confirm if this fixes your issue? I have published a newer version hopefully this one works as default, since it's using the high camera controller resolution option, instead of medium.

I have also added the onError callback, but there isn't an error being thrown in this situation.

umangsh commented 2 years ago

It does, no regressions on previously working devices as well. Thanks for the fix!