start method
Start scanning for barcodes. Upon calling this method, the necessary camera permission will be requested.
Returns an instance of MobileScannerArguments when the scanner was successfully started. Returns null if the scanner is currently starting.
Throws a MobileScannerException if starting the scanner failed.
Implementation
Future<MobileScannerArguments?> start({
CameraFacing? cameraFacingOverride,
}) async {
if (isStarting) {
debugPrint("Called start() while starting.");
return null;
}
events ??= _eventChannel
.receiveBroadcastStream()
.listen((data) => _handleEvent(data as Map));
isStarting = true;
// Check authorization status
if (!kIsWeb) {
final MobileScannerState state;
try {
state = MobileScannerState.fromRawValue(
await _methodChannel.invokeMethod('state') as int? ?? 0,
);
} on PlatformException catch (error) {
isStarting = false;
throw MobileScannerException(
errorCode: MobileScannerErrorCode.genericError,
errorDetails: MobileScannerErrorDetails(
code: error.code,
details: error.details as Object?,
message: error.message,
),
);
}
switch (state) {
// Android does not have an undetermined permission state.
// So if the permission state is denied, just request it now.
case MobileScannerState.undetermined:
case MobileScannerState.denied:
try {
final bool granted =
await _methodChannel.invokeMethod('request') as bool? ?? false;
if (!granted) {
isStarting = false;
throw const MobileScannerException(
errorCode: MobileScannerErrorCode.permissionDenied,
);
}
} on PlatformException catch (error) {
isStarting = false;
throw MobileScannerException(
errorCode: MobileScannerErrorCode.genericError,
errorDetails: MobileScannerErrorDetails(
code: error.code,
details: error.details as Object?,
message: error.message,
),
);
}
break;
case MobileScannerState.authorized:
break;
}
}
// Start the camera with arguments
Map<String, dynamic>? startResult = {};
try {
startResult = await _methodChannel.invokeMapMethod<String, dynamic>(
'start',
_argumentsToMap(cameraFacingOverride: cameraFacingOverride),
);
} on PlatformException catch (error) {
MobileScannerErrorCode errorCode = MobileScannerErrorCode.genericError;
final String? errorMessage = error.message;
if (kIsWeb) {
if (errorMessage == null) {
errorCode = MobileScannerErrorCode.genericError;
} else if (errorMessage.contains('NotFoundError') ||
errorMessage.contains('NotSupportedError')) {
errorCode = MobileScannerErrorCode.unsupported;
} else if (errorMessage.contains('NotAllowedError')) {
errorCode = MobileScannerErrorCode.permissionDenied;
} else {
errorCode = MobileScannerErrorCode.genericError;
}
}
isStarting = false;
throw MobileScannerException(
errorCode: errorCode,
errorDetails: MobileScannerErrorDetails(
code: error.code,
details: error.details as Object?,
message: error.message,
),
);
}
if (startResult == null) {
isStarting = false;
throw const MobileScannerException(
errorCode: MobileScannerErrorCode.genericError,
);
}
final hasTorch = startResult['torchable'] as bool? ?? false;
hasTorchState.value = hasTorch;
final Size size;
if (kIsWeb) {
size = Size(
startResult['videoWidth'] as double? ?? 0,
startResult['videoHeight'] as double? ?? 0,
);
} else {
final Map<Object?, Object?>? sizeInfo =
startResult['size'] as Map<Object?, Object?>?;
size = Size(
sizeInfo?['width'] as double? ?? 0,
sizeInfo?['height'] as double? ?? 0,
);
}
isStarting = false;
return startArguments.value = MobileScannerArguments(
numberOfCameras: startResult['numberOfCameras'] as int?,
size: size,
hasTorch: hasTorch,
textureId: kIsWeb ? null : startResult['textureId'] as int?,
webId: kIsWeb ? startResult['ViewID'] as String? : null,
);
}