252 unknown exceptionflutter-beta
| @@ -79,6 +79,7 @@ unlinked_spec.ds | |||
| **/ios/**/DerivedData/ | |||
| **/ios/**/Icon? | |||
| **/ios/**/Pods/ | |||
| **/ios/.symlinks/ | |||
| **/ios/**/.symlinks/ | |||
| **/ios/**/profile | |||
| **/ios/**/xcuserdata | |||
| @@ -21,7 +21,7 @@ class FlutterQrPlugin : FlutterPlugin, ActivityAware { | |||
| } | |||
| private fun onAttachedToV1(registrar: PluginRegistry.Registrar) { | |||
| registrar.addRequestPermissionsResultListener(CameraRequestPermissionsListener()) | |||
| Shared.registrar = registrar | |||
| onAttachedToEngines(registrar.platformViewRegistry(), registrar.messenger(), registrar.activity()) | |||
| } | |||
| @@ -45,27 +45,23 @@ class FlutterQrPlugin : FlutterPlugin, ActivityAware { | |||
| override fun onAttachedToActivity(activityPluginBinding: ActivityPluginBinding) { | |||
| Shared.activity = activityPluginBinding.activity | |||
| activityPluginBinding.addRequestPermissionsResultListener(CameraRequestPermissionsListener()) | |||
| Shared.binding = activityPluginBinding | |||
| } | |||
| override fun onDetachedFromActivityForConfigChanges() { | |||
| Shared.activity = null | |||
| Shared.binding = null | |||
| } | |||
| override fun onReattachedToActivityForConfigChanges(activityPluginBinding: ActivityPluginBinding) { | |||
| Shared.activity = activityPluginBinding.activity | |||
| Shared.binding = activityPluginBinding | |||
| } | |||
| override fun onDetachedFromActivity() { | |||
| Shared.activity = null | |||
| Shared.binding = null | |||
| } | |||
| inner class CameraRequestPermissionsListener : PluginRegistry.RequestPermissionsResultListener { | |||
| override fun onRequestPermissionsResult(id: Int, permissions: Array<String>, grantResults: IntArray): Boolean { | |||
| if (id == Shared.CAMERA_REQUEST_ID && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |||
| return true | |||
| } | |||
| return false | |||
| } | |||
| } | |||
| } | |||
| @@ -4,40 +4,50 @@ import android.Manifest | |||
| import android.app.Activity | |||
| import android.app.Application | |||
| import android.content.pm.PackageManager | |||
| import android.os.Bundle | |||
| import android.view.View | |||
| import com.google.zxing.ResultPoint | |||
| import android.hardware.Camera.CameraInfo | |||
| import android.os.Build | |||
| import android.os.Bundle | |||
| import android.view.View | |||
| import com.google.zxing.BarcodeFormat | |||
| import com.google.zxing.ResultPoint | |||
| import com.journeyapps.barcodescanner.BarcodeCallback | |||
| import com.journeyapps.barcodescanner.BarcodeResult | |||
| import com.journeyapps.barcodescanner.BarcodeView | |||
| import io.flutter.plugin.common.BinaryMessenger | |||
| import io.flutter.plugin.common.MethodCall | |||
| import io.flutter.plugin.common.MethodChannel | |||
| import io.flutter.plugin.common.PluginRegistry | |||
| import io.flutter.plugin.platform.PlatformView | |||
| class QRView(messenger: BinaryMessenger, id: Int, private val params: HashMap<String, Any>) : | |||
| PlatformView, MethodChannel.MethodCallHandler { | |||
| PlatformView, MethodChannel.MethodCallHandler, PluginRegistry.RequestPermissionsResultListener { | |||
| private var isTorchOn: Boolean = false | |||
| private var isPaused: Boolean = false | |||
| private var barcodeView: BarcodeView? = null | |||
| private val channel: MethodChannel | |||
| private val channel: MethodChannel = MethodChannel(messenger, "net.touchcapture.qr.flutterqr/qrview_$id") | |||
| private var permissionGranted: Boolean = false | |||
| init { | |||
| checkAndRequestPermission(null) | |||
| channel = MethodChannel(messenger, "net.touchcapture.qr.flutterqr/qrview_$id") | |||
| if (Shared.binding != null) { | |||
| Shared.binding!!.addRequestPermissionsResultListener(this) | |||
| } | |||
| if (Shared.registrar != null) { | |||
| Shared.registrar!!.addRequestPermissionsResultListener(this) | |||
| } | |||
| channel.setMethodCallHandler(this) | |||
| Shared.activity?.application?.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks { | |||
| override fun onActivityPaused(p0: Activity) { | |||
| if (p0 == Shared.activity && !isPaused) { | |||
| if (p0 == Shared.activity && !isPaused && hasCameraPermission()) { | |||
| barcodeView?.pause() | |||
| } | |||
| } | |||
| override fun onActivityResumed(p0: Activity) { | |||
| if (p0 == Shared.activity && !isPaused) { | |||
| if (p0 == Shared.activity && !isPaused && hasCameraPermission()) { | |||
| barcodeView?.resume() | |||
| } | |||
| } | |||
| @@ -93,20 +103,22 @@ class QRView(messenger: BinaryMessenger, id: Int, private val params: HashMap<St | |||
| if (barcodeView == null) { | |||
| return barCodeViewNotSet(result) | |||
| } else if (!hasCameraPermission()) { | |||
| return cameraPermissionNotSet(result) | |||
| } | |||
| checkAndRequestPermission(result) | |||
| } else { | |||
| barcodeView!!.pause() | |||
| val settings = barcodeView!!.cameraSettings | |||
| if(settings.requestedCameraId == CameraInfo.CAMERA_FACING_FRONT) | |||
| settings.requestedCameraId = CameraInfo.CAMERA_FACING_BACK | |||
| else | |||
| settings.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT | |||
| barcodeView!!.pause() | |||
| val settings = barcodeView!!.cameraSettings | |||
| barcodeView!!.cameraSettings = settings | |||
| barcodeView!!.resume() | |||
| result.success(settings.requestedCameraId) | |||
| } | |||
| if(settings.requestedCameraId == CameraInfo.CAMERA_FACING_FRONT) | |||
| settings.requestedCameraId = CameraInfo.CAMERA_FACING_BACK | |||
| else | |||
| settings.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT | |||
| barcodeView!!.cameraSettings = settings | |||
| barcodeView!!.resume() | |||
| result.success(settings.requestedCameraId) | |||
| } | |||
| private fun getFlashInfo(result: MethodChannel.Result) { | |||
| @@ -119,8 +131,6 @@ class QRView(messenger: BinaryMessenger, id: Int, private val params: HashMap<St | |||
| private fun toggleFlash(result: MethodChannel.Result) { | |||
| if (barcodeView == null) { | |||
| return barCodeViewNotSet(result) | |||
| } else if (!hasCameraPermission()) { | |||
| return cameraPermissionNotSet(result) | |||
| } | |||
| if (hasFlash()) { | |||
| @@ -137,28 +147,28 @@ class QRView(messenger: BinaryMessenger, id: Int, private val params: HashMap<St | |||
| if (barcodeView == null) { | |||
| return barCodeViewNotSet(result) | |||
| } else if (!hasCameraPermission()) { | |||
| return cameraPermissionNotSet(result) | |||
| } | |||
| if (barcodeView!!.isPreviewActive) { | |||
| isPaused = true | |||
| barcodeView!!.pause() | |||
| checkAndRequestPermission(result) | |||
| } else { | |||
| if (barcodeView!!.isPreviewActive) { | |||
| isPaused = true | |||
| barcodeView!!.pause() | |||
| } | |||
| result.success(true) | |||
| } | |||
| result.success(true) | |||
| } | |||
| private fun resumeCamera(result: MethodChannel.Result) { | |||
| if (barcodeView == null) { | |||
| return barCodeViewNotSet(result) | |||
| } else if (!hasCameraPermission()) { | |||
| return cameraPermissionNotSet(result) | |||
| } | |||
| if (!barcodeView!!.isPreviewActive) { | |||
| isPaused = false | |||
| barcodeView!!.resume() | |||
| checkAndRequestPermission(result) | |||
| } else { | |||
| if (!barcodeView!!.isPreviewActive) { | |||
| isPaused = false | |||
| barcodeView!!.resume() | |||
| } | |||
| result.success(true) | |||
| } | |||
| result.success(true) | |||
| } | |||
| private fun hasFlash(): Boolean { | |||
| @@ -182,10 +192,6 @@ class QRView(messenger: BinaryMessenger, id: Int, private val params: HashMap<St | |||
| result.error("404", "No barcode view found", null) | |||
| } | |||
| private fun cameraPermissionNotSet(result: MethodChannel.Result) { | |||
| result.error("cameraPermission", " Permission denied to access the camera", null) | |||
| } | |||
| override fun getView(): View { | |||
| return initBarCodeView().apply {}!! | |||
| } | |||
| @@ -196,16 +202,17 @@ class QRView(messenger: BinaryMessenger, id: Int, private val params: HashMap<St | |||
| if (params["cameraFacing"] as Int == 1) { | |||
| barcodeView?.cameraSettings?.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT | |||
| } | |||
| barcodeView!!.resume() | |||
| } else { | |||
| if (hasCameraPermission()) { | |||
| if (!isPaused) barcodeView!!.resume() | |||
| } else { | |||
| checkAndRequestPermission(null) | |||
| } | |||
| } | |||
| return barcodeView | |||
| } | |||
| private fun startScan(arguments: List<Int>?, result: MethodChannel.Result) { | |||
| if (!hasCameraPermission()) { | |||
| return cameraPermissionNotSet(result) | |||
| } | |||
| val allowedBarcodeTypes = mutableListOf<BarcodeFormat>() | |||
| try { | |||
| arguments?.forEach { | |||
| @@ -254,7 +261,6 @@ class QRView(messenger: BinaryMessenger, id: Int, private val params: HashMap<St | |||
| private fun checkAndRequestPermission(result: MethodChannel.Result?) { | |||
| when { | |||
| hasCameraPermission() -> result?.success(true) | |||
| Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> { | |||
| Shared.activity?.requestPermissions( | |||
| arrayOf(Manifest.permission.CAMERA), | |||
| @@ -265,5 +271,20 @@ class QRView(messenger: BinaryMessenger, id: Int, private val params: HashMap<St | |||
| } | |||
| } | |||
| } | |||
| override fun onRequestPermissionsResult( requestCode: Int, | |||
| permissions: Array<out String>?, | |||
| grantResults: IntArray): Boolean { | |||
| if (requestCode == Shared.CAMERA_REQUEST_ID && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |||
| permissionGranted = true | |||
| channel.invokeMethod("onPermissionSet", true) | |||
| return true | |||
| } | |||
| permissionGranted = false | |||
| channel.invokeMethod("onPermissionSet", false) | |||
| return false | |||
| } | |||
| } | |||
| @@ -1,8 +1,12 @@ | |||
| package net.touchcapture.qr.flutterqr | |||
| import android.app.Activity | |||
| import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding | |||
| import io.flutter.plugin.common.PluginRegistry | |||
| object Shared { | |||
| const val CAMERA_REQUEST_ID = 513469796 | |||
| var activity: Activity? = null | |||
| var binding: ActivityPluginBinding? = null | |||
| var registrar: PluginRegistry.Registrar? = null | |||
| } | |||
| @@ -32,6 +32,7 @@ public class QRView:NSObject,FlutterPlatformView { | |||
| public init(withFrame frame: CGRect, withRegistrar registrar: FlutterPluginRegistrar, withId id: Int64, params: Dictionary<String, Any>){ | |||
| self.registrar = registrar | |||
| previewView = UIView(frame: frame) | |||
| scanner = MTBBarcodeScanner(previewView: previewView) | |||
| cameraFacing = MTBCamera.init(rawValue: UInt(Int(params["cameraFacing"] as! Double))) ?? MTBCamera.back | |||
| channel = FlutterMethodChannel(name: "net.touchcapture.qr.flutterqr/qrview_\(id)", binaryMessenger: registrar.messenger()) | |||
| } | |||
| @@ -77,226 +78,165 @@ public class QRView:NSObject,FlutterPlatformView { | |||
| return previewView | |||
| } | |||
| func setDimensions(_ result: @escaping FlutterResult, width: Double, height: Double, scanArea: Double, scanAreaOffset: Double) -> Void { | |||
| func requestPermissions(_ result: @escaping FlutterResult) { | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| // self?.channel.invokeMethod("onPermissionSet", arguments: true) | |||
| // First set the size of the preview area. | |||
| self.previewView.frame = CGRect(x: 0, y: 0, width: width, height: height) | |||
| // Then set the size of the scan area. | |||
| let midX = self.view().bounds.midX | |||
| let midY = self.view().bounds.midY | |||
| // Check if the scanner is already created. | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if let previewLayer = sc.previewLayer { | |||
| previewLayer.frame = self.previewView.bounds; | |||
| } | |||
| if (scanArea != 0) { | |||
| sc.scanRect = CGRect(x: Double(midX) - (scanArea / 2), y: Double(midY) - (scanArea / 2), width: scanArea, height: scanArea) | |||
| // Set offset if provided. | |||
| if (scanAreaOffset != 0) { | |||
| sc.scanRect = sc.scanRect.offsetBy(dx: 0, dy: CGFloat(scanAreaOffset)) | |||
| } | |||
| } | |||
| } else { | |||
| // Create a scanner view if it doesn't exist yet. | |||
| self.scanner = MTBBarcodeScanner(previewView: self.previewView) | |||
| if (scanArea != 0) { | |||
| self.scanner?.didStartScanningBlock = { | |||
| self.scanner?.scanRect = CGRect(x: Double(midX) - (scanArea / 2), y: Double(midY) - (scanArea / 2), width: scanArea, height: scanArea) | |||
| // Set offset if provided. | |||
| if (scanAreaOffset != 0) { | |||
| self.scanner?.scanRect = (self.scanner?.scanRect.offsetBy(dx: 0, dy: CGFloat(scanAreaOffset)))! | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return result(width) | |||
| self.channel.invokeMethod("onPermissionSet", arguments: true) | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| } | |||
| }) | |||
| } | |||
| func startScan(_ arguments: Array<Int>, _ result: @escaping FlutterResult) -> Void { | |||
| if (scanner == nil) { | |||
| scanner = MTBBarcodeScanner(previewView: previewView) | |||
| func setDimensions(_ result: @escaping FlutterResult, width: Double, height: Double, scanArea: Double, scanAreaOffset: Double) { | |||
| // First ask for permission | |||
| requestPermissions(result) | |||
| // Then set the size of the preview area. | |||
| self.previewView.frame = CGRect(x: 0, y: 0, width: width, height: height) | |||
| // Then set the size of the scan area. | |||
| let midX = self.view().bounds.midX | |||
| let midY = self.view().bounds.midY | |||
| // Set the size of the preview. | |||
| if let previewLayer = self.scanner?.previewLayer { | |||
| previewLayer.frame = self.previewView.bounds | |||
| } | |||
| // Set scanArea if provided. | |||
| if (scanArea != 0) { | |||
| self.scanner?.didStartScanningBlock = { | |||
| self.scanner?.scanRect = CGRect(x: Double(midX) - (scanArea / 2), y: Double(midY) - (scanArea / 2), width: scanArea, height: scanArea) | |||
| // Set offset if provided. | |||
| if (scanAreaOffset != 0) { | |||
| self.scanner?.scanRect = (self.scanner?.scanRect.offsetBy(dx: 0, dy: CGFloat(scanAreaOffset)))! | |||
| } | |||
| } | |||
| } | |||
| return result(width) | |||
| } | |||
| func startScan(_ arguments: Array<Int>, _ result: @escaping FlutterResult) { | |||
| // Check for allowed barcodes | |||
| var allowedBarcodeTypes: Array<AVMetadataObject.ObjectType> = [] | |||
| arguments.forEach { arg in | |||
| allowedBarcodeTypes.append( QRCodeTypes[arg]!) | |||
| } | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| self.channel.invokeMethod("onPermissionSet", arguments: true) | |||
| do { | |||
| try self.scanner?.startScanning(with: self.cameraFacing, resultBlock: { [weak self] codes in | |||
| if let codes = codes { | |||
| for code in codes { | |||
| var typeString: String; | |||
| switch(code.type) { | |||
| case AVMetadataObject.ObjectType.aztec: | |||
| typeString = "AZTEC" | |||
| case AVMetadataObject.ObjectType.code39: | |||
| typeString = "CODE_39" | |||
| case AVMetadataObject.ObjectType.code93: | |||
| typeString = "CODE_93" | |||
| case AVMetadataObject.ObjectType.code128: | |||
| typeString = "CODE_128" | |||
| case AVMetadataObject.ObjectType.dataMatrix: | |||
| typeString = "DATA_MATRIX" | |||
| case AVMetadataObject.ObjectType.ean8: | |||
| typeString = "EAN_8" | |||
| case AVMetadataObject.ObjectType.ean13: | |||
| typeString = "EAN_13" | |||
| case AVMetadataObject.ObjectType.itf14: | |||
| typeString = "ITF" | |||
| case AVMetadataObject.ObjectType.pdf417: | |||
| typeString = "PDF_417" | |||
| case AVMetadataObject.ObjectType.qr: | |||
| typeString = "QR_CODE" | |||
| case AVMetadataObject.ObjectType.upce: | |||
| typeString = "UPC_E" | |||
| default: | |||
| return | |||
| } | |||
| guard let stringValue = code.stringValue else { continue } | |||
| let result = ["code": stringValue, "type": typeString] | |||
| if allowedBarcodeTypes.count == 0 || allowedBarcodeTypes.contains(code.type) { | |||
| self?.channel.invokeMethod("onRecognizeQR", arguments: result) | |||
| } | |||
| } | |||
| do { | |||
| try self.scanner?.startScanning(with: self.cameraFacing, resultBlock: { [weak self] codes in | |||
| if let codes = codes { | |||
| for code in codes { | |||
| var typeString: String; | |||
| switch(code.type) { | |||
| case AVMetadataObject.ObjectType.aztec: | |||
| typeString = "AZTEC" | |||
| case AVMetadataObject.ObjectType.code39: | |||
| typeString = "CODE_39" | |||
| case AVMetadataObject.ObjectType.code93: | |||
| typeString = "CODE_93" | |||
| case AVMetadataObject.ObjectType.code128: | |||
| typeString = "CODE_128" | |||
| case AVMetadataObject.ObjectType.dataMatrix: | |||
| typeString = "DATA_MATRIX" | |||
| case AVMetadataObject.ObjectType.ean8: | |||
| typeString = "EAN_8" | |||
| case AVMetadataObject.ObjectType.ean13: | |||
| typeString = "EAN_13" | |||
| case AVMetadataObject.ObjectType.itf14: | |||
| typeString = "ITF" | |||
| case AVMetadataObject.ObjectType.pdf417: | |||
| typeString = "PDF_417" | |||
| case AVMetadataObject.ObjectType.qr: | |||
| typeString = "QR_CODE" | |||
| case AVMetadataObject.ObjectType.upce: | |||
| typeString = "UPC_E" | |||
| default: | |||
| return | |||
| } | |||
| }) | |||
| } catch { | |||
| let error = FlutterError(code: "unknown-error", message: "Unable to start scanning", details: nil) | |||
| return result(error) | |||
| guard let stringValue = code.stringValue else { continue } | |||
| let result = ["code": stringValue, "type": typeString] | |||
| if allowedBarcodeTypes.count == 0 || allowedBarcodeTypes.contains(code.type) { | |||
| self?.channel.invokeMethod("onRecognizeQR", arguments: result) | |||
| } | |||
| } | |||
| } | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| } | |||
| }) | |||
| }) | |||
| } catch { | |||
| let error = FlutterError(code: "unknown-error", message: "Unable to start scanning", details: nil) | |||
| return result(error) | |||
| } | |||
| } | |||
| func stopCamera(_ result: @escaping FlutterResult){ | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if sc.isScanning() { | |||
| sc.stopScanning() | |||
| } | |||
| } | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| func stopCamera(_ result: @escaping FlutterResult) { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if sc.isScanning() { | |||
| sc.stopScanning() | |||
| } | |||
| }) | |||
| } | |||
| } | |||
| func getCameraInfo(_ result: @escaping FlutterResult) -> Void { | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| result(sc.camera.rawValue) | |||
| } else { | |||
| let error = FlutterError(code: "cameraInformationError", message: "Could not get camera information", details: nil) | |||
| result(error) | |||
| } | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| } | |||
| }) | |||
| func getCameraInfo(_ result: @escaping FlutterResult) { | |||
| result(self.cameraFacing.rawValue) | |||
| } | |||
| func flipCamera(_ result: @escaping FlutterResult){ | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if sc.hasOppositeCamera() { | |||
| sc.flipCamera() | |||
| } | |||
| return result(sc.camera.rawValue) | |||
| } | |||
| return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil)) | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| func flipCamera(_ result: @escaping FlutterResult) { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if sc.hasOppositeCamera() { | |||
| sc.flipCamera() | |||
| self.cameraFacing = sc.camera | |||
| } | |||
| }) | |||
| return result(sc.camera.rawValue) | |||
| } | |||
| return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil)) | |||
| } | |||
| func getFlashInfo(_ result: @escaping FlutterResult) -> Void { | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| result(sc.torchMode.rawValue != 0) | |||
| } else { | |||
| let error = FlutterError(code: "cameraInformationError", message: "Could not get flash information", details: nil) | |||
| result(error) | |||
| } | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| } | |||
| }) | |||
| func getFlashInfo(_ result: @escaping FlutterResult) { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| result(sc.torchMode.rawValue != 0) | |||
| } else { | |||
| let error = FlutterError(code: "cameraInformationError", message: "Could not get flash information", details: nil) | |||
| result(error) | |||
| } | |||
| } | |||
| func toggleFlash(_ result: @escaping FlutterResult){ | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if sc.hasTorch() { | |||
| sc.toggleTorch() | |||
| return result(sc.torchMode == MTBTorchMode(rawValue: 1)) | |||
| } | |||
| return result(FlutterError(code: "404", message: "This device doesn\'t support flash", details: nil)) | |||
| } | |||
| return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil)) | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if sc.hasTorch() { | |||
| sc.toggleTorch() | |||
| return result(sc.torchMode == MTBTorchMode(rawValue: 1)) | |||
| } | |||
| }) | |||
| return result(FlutterError(code: "404", message: "This device doesn\'t support flash", details: nil)) | |||
| } | |||
| return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil)) | |||
| } | |||
| func pauseCamera(_ result: @escaping FlutterResult) { | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if sc.isScanning() { | |||
| sc.freezeCapture() | |||
| } | |||
| return result(true) | |||
| } | |||
| return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil)) | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if sc.isScanning() { | |||
| sc.freezeCapture() | |||
| } | |||
| }) | |||
| return result(true) | |||
| } | |||
| return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil)) | |||
| } | |||
| func resumeCamera(_ result: @escaping FlutterResult) { | |||
| MTBBarcodeScanner.requestCameraPermission(success: { permissionGranted in | |||
| if permissionGranted { | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if !sc.isScanning() { | |||
| sc.unfreezeCapture() | |||
| } | |||
| return result(true) | |||
| } | |||
| return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil)) | |||
| } else { | |||
| return result(FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)) | |||
| if let sc: MTBBarcodeScanner = self.scanner { | |||
| if !sc.isScanning() { | |||
| sc.unfreezeCapture() | |||
| } | |||
| }) | |||
| return result(true) | |||
| } | |||
| return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil)) | |||
| } | |||
| func getSystemFeatures(_ result: @escaping FlutterResult) -> Void { | |||
| func getSystemFeatures(_ result: @escaping FlutterResult) { | |||
| if let sc: MTBBarcodeScanner = scanner { | |||
| var hasBackCameraVar = false | |||
| var hasFrontCameraVar = false | |||
| @@ -0,0 +1,30 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter/foundation.dart'; | |||
| class LifecycleEventHandler extends WidgetsBindingObserver { | |||
| LifecycleEventHandler({ | |||
| this.resumeCallBack, | |||
| this.suspendingCallBack, | |||
| }); | |||
| final AsyncCallback resumeCallBack; | |||
| final AsyncCallback suspendingCallBack; | |||
| @override | |||
| Future<void> didChangeAppLifecycleState(AppLifecycleState state) async { | |||
| switch (state) { | |||
| case AppLifecycleState.resumed: | |||
| if (resumeCallBack != null) { | |||
| await resumeCallBack(); | |||
| } | |||
| break; | |||
| case AppLifecycleState.inactive: | |||
| case AppLifecycleState.paused: | |||
| case AppLifecycleState.detached: | |||
| if (suspendingCallBack != null) { | |||
| await suspendingCallBack(); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter/services.dart'; | |||
| import 'lifecycle_event_handler.dart'; | |||
| import 'qr_scanner_overlay_shape.dart'; | |||
| import 'types/barcode.dart'; | |||
| import 'types/barcode_format.dart'; | |||
| @@ -58,6 +59,19 @@ class QRView extends StatefulWidget { | |||
| class _QRViewState extends State<QRView> { | |||
| var _channel; | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| WidgetsBinding.instance.addObserver(LifecycleEventHandler( | |||
| resumeCallBack: () async => { | |||
| if (_channel != null) | |||
| { | |||
| QRViewController.updateDimensions(widget.key, _channel, | |||
| overlay: widget.overlay) | |||
| } | |||
| })); | |||
| } | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return NotificationListener( | |||
| @@ -75,6 +89,7 @@ class _QRViewState extends State<QRView> { | |||
| QRViewController.updateDimensions(widget.key, _channel, | |||
| overlay: widget.overlay) | |||
| }); | |||
| return false; | |||
| } | |||
| @@ -124,9 +139,9 @@ class _QRViewState extends State<QRView> { | |||
| _channel = MethodChannel('net.touchcapture.qr.flutterqr/qrview_$id'); | |||
| // Start scan after creation of the view | |||
| final controller = | |||
| QRViewController._(_channel, widget.key, widget.onPermissionSet) | |||
| .._startScan(widget.key, widget.overlay, widget.formatsAllowed); | |||
| final controller = QRViewController._( | |||
| _channel, widget.key, widget.onPermissionSet, widget.cameraFacing) | |||
| .._startScan(widget.key, widget.overlay, widget.formatsAllowed); | |||
| // Initialize the controller for controlling the QRView | |||
| if (widget.onQRViewCreated != null) { | |||
| @@ -151,8 +166,9 @@ class _QrCameraSettings { | |||
| class QRViewController { | |||
| QRViewController._(MethodChannel channel, GlobalKey qrKey, | |||
| PermissionSetCallback onPermissionSet) | |||
| : _channel = channel { | |||
| PermissionSetCallback onPermissionSet, CameraFacing cameraFacing) | |||
| : _channel = channel, | |||
| _cameraFacing = cameraFacing { | |||
| _channel.setMethodCallHandler((call) async { | |||
| switch (call.method) { | |||
| case 'onRecognizeQR': | |||
| @@ -189,11 +205,13 @@ class QRViewController { | |||
| } | |||
| final MethodChannel _channel; | |||
| final CameraFacing _cameraFacing; | |||
| final StreamController<Barcode> _scanUpdateController = | |||
| StreamController<Barcode>(); | |||
| Stream<Barcode> get scannedDataStream => _scanUpdateController.stream; | |||
| static bool _firstRun = true; | |||
| SystemFeatures _features; | |||
| bool _hasPermissions; | |||
| @@ -216,6 +234,8 @@ class QRViewController { | |||
| /// Gets information about which camera is active. | |||
| Future<CameraFacing> getCameraInfo() async { | |||
| try { | |||
| var cameraFacing = await _channel.invokeMethod('getCameraInfo') as int; | |||
| if (cameraFacing == -1) return _cameraFacing; | |||
| return CameraFacing | |||
| .values[await _channel.invokeMethod('getCameraInfo') as int]; | |||
| } on PlatformException catch (e) { | |||
| @@ -299,6 +319,10 @@ class QRViewController { | |||
| static Future<void> updateDimensions(GlobalKey key, MethodChannel channel, | |||
| {QrScannerOverlayShape overlay}) async { | |||
| if (defaultTargetPlatform == TargetPlatform.iOS) { | |||
| if (_firstRun) { | |||
| _firstRun = false; | |||
| await Future.delayed(Duration(milliseconds: 300)); | |||
| } | |||
| final RenderBox renderBox = key.currentContext.findRenderObject(); | |||
| try { | |||
| await channel.invokeMethod('setDimensions', { | |||