juliuscanute / qr_code_scanner

QR Code Scanner for Flutter
BSD 2-Clause "Simplified" License
995 stars 731 forks source link

[BUG] onPermissionSet executed multiple times since v1.0.0 #564

Open Johandrex opened 2 years ago

Johandrex commented 2 years ago

Describe the bug When the user doesn't have permission to access the camera onPermissionSet is executed multiple times (like 30 times a second)

Flutter information

[√] Flutter (Channel stable, 3.0.2, on Microsoft Windows [Version 10.0.19043.1706], locale sv-SE)
    • Flutter version 3.0.2 at C:\Users\40117872\Flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision cd41fdd495 (2 weeks ago), 2022-06-08 09:52:13 -0700
    • Engine revision f15f824b57
    • Dart version 2.17.3
    • DevTools version 2.12.2

[!] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    • Android SDK at C:\Users\40117872\AppData\Local\Android\sdk
    X cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    X Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.

[X] Chrome - develop for the web (Cannot find Chrome executable at .\Google\Chrome\Application\chrome.exe)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[X] Visual Studio - develop for Windows
    X Visual Studio not installed; this is necessary for Windows development.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components

[√] Android Studio (version 2021.2)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+7-b1504.28-7817840)

[√] IntelliJ IDEA Ultimate Edition (version 2021.2)
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.3
    • Flutter plugin version 63.2.3
    • Dart plugin version 212.5632

[√] VS Code (version 1.68.1)
    • VS Code at C:\Users\40117872\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension can be installed from:
       https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[√] Connected device (3 available)
    • Android SDK built for x86 (mobile) • emulator-5554 • android-x86    • Android 11 (API 30) (emulator)
    • Windows (desktop)                  • windows       • windows-x64    • Microsoft Windows [Version 10.0.19043.1706]
    • Edge (web)                         • edge          • web-javascript • Microsoft Edge 101.0.1210.32

[√] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 3 categories.

Device (please complete the following information):

Johandrex commented 2 years ago

Here's the QrScanner widget code, right now I'm using shownPermissionDenied to prevent multiple dialog openings. But as you can see in the video, the top and lower bar is glitching..

https://user-images.githubusercontent.com/8752172/174981905-2db1917f-8368-415d-8636-1fdc2e581b86.mp4

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:hdd/helpers/config.dart';
import 'package:hdd/widgets/app_custom_dialog_box.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';

// ignore: must_be_immutable
class QrScanner extends StatelessWidget {
  final GlobalKey<FormState> formKey;
  final Function qrCallbackFunction;
  QRViewController? controller;

  // permission display
  bool shownPermissionDenied = false;
  final String? description;
  final String? declineText;
  final Function? declineAction;

  QrScanner({Key? key, required this.formKey, this.controller, required this.qrCallbackFunction, this.description, this.declineText, this.declineAction}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return QRView(
      formatsAllowed: const [BarcodeFormat.code128, BarcodeFormat.code39],
      key: formKey,
      onQRViewCreated: _onQRViewCreated,
      onPermissionSet: (ctrl, p) async {
        if (!shownPermissionDenied) {
          await _onPermissionDenied(context, ctrl, p);
        }
      },
    );
  }

  void resumeCamera() {
    if (Platform.isAndroid) {
      controller?.pauseCamera();
    }
    controller?.resumeCamera();
  }

  void _onQRViewCreated(QRViewController _controller) {
    controller = _controller;
    resumeCamera();
    controller!.scannedDataStream.listen((scanData) async {
      await qrCallbackFunction(scanData.code.toString());
    });
  }

  Future<void> _onPermissionDenied(BuildContext context, QRViewController ctrl, bool p) async {
    if (!p) {
      showDialog(
        barrierDismissible: false,
        context: context,
        builder: (BuildContext context) {
          return CustomDialogBox(
            dialogType: DialogType.CONFIRM,
            title: 'No Camera Access',
            description: (description != null) ? description : Config.NO_CAMERA_ACCESS,
            acceptText: 'Settings',
            declineText: (declineText != null) ? declineText : 'Close',
            declineAction: (declineAction != null) ? declineAction : null,
            acceptAction: openAppSettings,
          );
        },
      );
    }

    shownPermissionDenied = true;
  }
}
geekywoman commented 2 years ago

We are facing the same issue in our team. This is quite critical as it will get stuck in a loop of hell triggering the "onPermissionSet" callback until the app simply crashes.

Edit: this error seems to occur only on android, not on iOS

OOTPAppsDotCom commented 2 years ago

On a new Android app installation, utilizing this library, there is no request for permissions shown to the user at all. You will receive the following error upon installation on a new Android device and opening the camera for the first time:

E/FrameEvents(32209): updateAcquireFence: Did not find frame. E/MethodChannel#flutter/platform_views(32209): Failed to handle method call E/MethodChannel#flutter/platform_views(32209): java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference E/MethodChannel#flutter/platform_views(32209): at android.view.ViewConfiguration.get(ViewConfiguration.java:523) E/MethodChannel#flutter/platform_views(32209): at android.view.View.<init>(View.java:5321) E/MethodChannel#flutter/platform_views(32209): at android.view.View.<init>(View.java:5466) E/MethodChannel#flutter/platform_views(32209): at android.view.ViewGroup.<init>(ViewGroup.java:702) E/MethodChannel#flutter/platform_views(32209): at android.view.ViewGroup.<init>(ViewGroup.java:698) E/MethodChannel#flutter/platform_views(32209): at android.view.ViewGroup.<init>(ViewGroup.java:694) E/MethodChannel#flutter/platform_views(32209): at android.view.ViewGroup.<init>(ViewGroup.java:690) E/MethodChannel#flutter/platform_views(32209): at com.journeyapps.barcodescanner.CameraPreview.<init>(CameraPreview.java:228) E/MethodChannel#flutter/platform_views(32209): at com.journeyapps.barcodescanner.BarcodeView.<init>(BarcodeView.java:76) E/MethodChannel#flutter/platform_views(32209): at net.touchcapture.qr.flutterqr.CustomFramingRectBarcodeView.<init>(CustomFramingRectBarcodeView.kt:12) E/MethodChannel#flutter/platform_views(32209): at net.touchcapture.qr.flutterqr.QRView.initBarCodeView(QRView.kt:117) E/MethodChannel#flutter/platform_views(32209): at net.touchcapture.qr.flutterqr.QRView.getView(QRView.kt:70) E/MethodChannel#flutter/platform_views(32209): at io.flutter.plugin.platform.PlatformViewsController$1.createForTextureLayer(PlatformViewsController.java:227) E/MethodChannel#flutter/platform_views(32209): at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.create(PlatformViewsChannel.java:122) E/MethodChannel#flutter/platform_views(32209): at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.onMethodCall(PlatformViewsChannel.java:60) E/MethodChannel#flutter/platform_views(32209): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262) E/MethodChannel#flutter/platform_views(32209): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295) E/MethodChannel#flutter/platform_views(32209): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319) E/MethodChannel#flutter/platform_views(32209): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12) E/MethodChannel#flutter/platform_views(32209): at android.os.Handler.handleCallback(Handler.java:938) E/MethodChannel#flutter/platform_views(32209): at android.os.Handler.dispatchMessage(Handler.java:99) E/MethodChannel#flutter/platform_views(32209): at android.os.Looper.loopOnce(Looper.java:201) E/MethodChannel#flutter/platform_views(32209): at android.os.Looper.loop(Looper.java:288) E/MethodChannel#flutter/platform_views(32209): at android.app.ActivityThread.main(ActivityThread.java:7870) E/MethodChannel#flutter/platform_views(32209): at java.lang.reflect.Method.invoke(Native Method) E/MethodChannel#flutter/platform_views(32209): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) E/MethodChannel#flutter/platform_views(32209): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) E/flutter (32209): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: PlatformException(error, Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference, null, java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference E/flutter (32209): at android.view.ViewConfiguration.get(ViewConfiguration.java:523) E/flutter (32209): at android.view.View.<init>(View.java:5321) E/flutter (32209): at android.view.View.<init>(View.java:5466) E/flutter (32209): at android.view.ViewGroup.<init>(ViewGroup.java:702) E/flutter (32209): at android.view.ViewGroup.<init>(ViewGroup.java:698) E/flutter (32209): at android.view.ViewGroup.<init>(ViewGroup.java:694) E/flutter (32209): at android.view.ViewGroup.<init>(ViewGroup.java:690) E/flutter (32209): at com.journeyapps.barcodescanner.CameraPreview.<init>(CameraPreview.java:228) E/flutter (32209): at com.journeyapps.barcodescanner.BarcodeView.<init>(BarcodeView.java:76) E/flutter (32209): at net.touchcapture.qr.flutterqr.CustomFramingRectBarcodeView.<init>(CustomFramingRectBarcodeView.kt:12) E/flutter (32209): at net.touchcapture.qr.flutterqr.QRView.initBarCodeView(QRView.kt:117) E/flutter (32209): at net.touchcapture.qr.flutterqr.QRView.getView(QRView.kt:70) E/flutter (32209): at io.flutter.plugin.platform.PlatformViewsController$1.createForTextureLayer(PlatformViewsController.java:227) E/flutter (32209): at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.create(PlatformViewsChannel.java:122) E/flutter (32209): at io.flutter.embedding.engine.systemchannels.PlatformViewsChannel$1.onMethodCall(PlatformViewsChannel.java:60) E/flutter (32209): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:262) E/flutter (32209): at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295) E/flutter (32209): at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:319) E/flutter (32209): at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12) E/flutter (32209): at android.os.Handler.handleCallback(Handler.java:938) E/flutter (32209): at android.os.Handler.dispatchMessage(Handler.java:99) E/flutter (32209): at android.os.Looper.loopOnce(Looper.java:201) E/flutter (32209): at android.os.Looper.loop(Looper.java:288) E/flutter (32209): at android.app.ActivityThread.main(ActivityThread.java:7870) E/flutter (32209): at java.lang.reflect.Method.invoke(Native Method) E/flutter (32209): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) E/flutter (32209): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) E/flutter (32209): ) E/flutter (32209): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7) E/flutter (32209): #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:167:18) E/flutter (32209): <asynchronous suspension> E/flutter (32209): #2 TextureAndroidViewController._sendCreateMessage (package:flutter/src/services/platform_views.dart:1134:18) E/flutter (32209): <asynchronous suspension> E/flutter (32209): #3 AndroidViewController.create (package:flutter/src/services/platform_views.dart:762:5) E/flutter (32209): <asynchronous suspension> E/flutter (32209): #4 TextureAndroidViewController.setSize (package:flutter/src/services/platform_views.dart:1062:7) E/flutter (32209): <asynchronous suspension> E/flutter (32209): #5 RenderAndroidView._sizePlatformView (package:flutter/src/rendering/platform_view.dart:179:29) E/flutter (32209): <asynchronous suspension> E/flutter (32209):

Manually granting camera permissions prevents this error from occuring again. Device is on Android 12, Pixel 4a 5G.

Johandrex commented 2 years ago

So @juliansteenbakker , is this getting an fix anytime soon?

manjarqo commented 2 years ago

the same issue in our team

wendellperes commented 1 year ago

quando tu vai resolver????

2e2ee95304418f96 commented 1 year ago

I debugged the code, found that QrShared.activity?.registerLifecycleCallbacks onResume is calling continously. But I don't find the reason.

JamesVu33 commented 1 year ago

Android platform: After run scan successful, The app will crash after I change camera permission on setting page (ask every time or don't allow) while the app is running. Either the app is now opening scan page or another. I still not figure out the reason, somebody helps

adminant commented 1 year ago

Is there a fix for this? I face the same issue - onPermissionSet is called continuously after I disallowed camera usage on Android

Gargoros commented 1 year ago

a similar problem in our team

korea1501541730 commented 8 months ago

a similar problem in our team

Gobmichet commented 4 months ago

Same here :( Does anybody have a solution ?

Anybody to create a qr_code_scanner_plus ? :s

That's really critical and yet that's still and by far the most popular flutter qrcode lib !?

EDIT : i do use a flag to be able to show a dialog once and redirect the user that already had denied permission on openAppSetting() when he clicks on "Parameters"

BUT that doesn't change the bug and the onSetPermission still infinite loop until crash

DarenF-20C commented 4 months ago

As for now, I'm facing this issue too. I'm just doing a flag to record is it thrown the permission "false", is yes then skip the rest. Although this doesn't solve the issue, but at least it solve the user ux. And as mentioned above, new android version will no more request for permission, so this issue will no longer exist in upcoming android version.

Here's a conceptual approach example, not the real code.

bool noPermissionRecorded = false;

onPermissionSet( permission ){
print("onPermissionSet");
  if(!permission && !noPermissionRecorded){
     // do alert or dialog
  }
}