mobile_scanner
mobile_scanner copied to clipboard
Bug : Camera permission called again if user denied first one
When user denied camera permission, system popup is called again.
mobile_scanner : 3.0.0
Code :
import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
void main() => runApp(const MaterialApp(home: MyHome()));
class MyHome extends StatelessWidget {
const MyHome({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flutter Demo Home Page')),
body: SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute<dynamic>(
builder: (BuildContext context) => const BarcodeScannerWithController(),
),
);
},
child: const Text('MobileScanner with Controller'),
),
],
),
),
);
}
}
class BarcodeScannerWithController extends StatefulWidget {
const BarcodeScannerWithController({super.key});
@override
_BarcodeScannerWithControllerState createState() => _BarcodeScannerWithControllerState();
}
class _BarcodeScannerWithControllerState extends State<BarcodeScannerWithController> with SingleTickerProviderStateMixin {
BarcodeCapture? barcode;
final MobileScannerController controller = MobileScannerController(
torchEnabled: true,
autoStart: true,
);
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(controller.hashCode.toString()),
),
backgroundColor: Colors.black,
body: Stack(
children: <Widget>[
MobileScanner(
startDelay: true,
controller: controller,
errorBuilder: (
BuildContext context,
MobileScannerException error,
Widget? child,
) {
return ScannerErrorWidget(error: error);
},
fit: BoxFit.contain,
onDetect: (BarcodeCapture barcode) {
setState(() {
this.barcode = barcode;
});
},
),
],
),
);
}
}
class ScannerErrorWidget extends StatelessWidget {
const ScannerErrorWidget({super.key, required this.error});
final MobileScannerException error;
@override
Widget build(BuildContext context) {
String errorMessage;
switch (error.errorCode) {
case MobileScannerErrorCode.controllerUninitialized:
errorMessage = 'Controller not ready.';
break;
case MobileScannerErrorCode.permissionDenied:
errorMessage = 'Permission denied';
break;
default:
errorMessage = 'Generic Error';
break;
}
return ColoredBox(
color: Colors.black,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Padding(
padding: EdgeInsets.only(bottom: 16),
child: Icon(Icons.error, color: Colors.white),
),
Text(
errorMessage,
style: const TextStyle(color: Colors.white),
),
],
),
),
);
}
}
Could be interesting to let us decide when call camera permission. This library can just display error when permission is missing :)
I have the same, reproduced on the latest version, before updating I had 3.0.0-beta.1 and it worked fine
reproduced only on android
I have noticed the same behavior, but not only when denying but also when accepting. The system permission dialog shows up twice. However, in my case it only appears to happen on the emulator. Running the code on an actual device seems fine.
Possibly related to #419 and #407
I have noticed the same behavior, but not only when denying but also when accepting. The system permission dialog shows up twice. However, in my case it only appears to happen on the emulator. Running the code on an actual device seems fine.
Possibly related to #419 and #407
It will happen on a physical device.
Hello, any news about this issue, even in 3.2.0 i go this issue only on Android only on denied case ?
Any updates here? current version is 3.3.0
For me it is working on Android if I change the didChangeAppLifecycleState inside the mobile_scanner to following:
switch (state) {
case AppLifecycleState.resumed:
if (_resumeFromBackground)
_startScanner();
break;
case AppLifecycleState.paused:
_resumeFromBackground = true;
break;
case AppLifecycleState.inactive:
_resumeFromBackground = false; // I guess this line is dead code
_controller.stop();
break;
case AppLifecycleState.detached:
break;
}
additional info:
first time the methodchannel invokes the request channel which opens the popup that furthermore triggers the resumed lifecycle state and therefore restarts the controller (because _resumeFromBackground has still the initial value false). when denying the permission pop up it calls the popup again. didn't check why it doesnt end in a infinite loop afterwards (maybe something is happening in the channel then)...
so the first popup triggers a resumed state. when going to background it calls first the inactive, then the paused state and in the end the resumed.
Reproduced on Android mobile_scanner 3.5.2 go with camera 0.10.5
On Android 11 and below, the permission window will appear several times, and then begin endless attempts, which greatly slows down the application.
@juliansteenbakker