From 2195a09f3cf64afa08057f8c9e12401119e02bfc Mon Sep 17 00:00:00 2001 From: Jonathan Dick Date: Fri, 13 Mar 2020 10:21:06 -0400 Subject: [PATCH] Save and re-set iOS config on shutdown Apparently if you change some AVCaptureDevice settings on iOS and don't change them back, they are persisted to subsequent uses of the device within the same app. --- ZXing.Net.Mobile/iOS/ZXingScannerView.ios.cs | 122 ++++++++++++++----- 1 file changed, 89 insertions(+), 33 deletions(-) diff --git a/ZXing.Net.Mobile/iOS/ZXingScannerView.ios.cs b/ZXing.Net.Mobile/iOS/ZXingScannerView.ios.cs index 861999a4a..406cd0b4c 100644 --- a/ZXing.Net.Mobile/iOS/ZXingScannerView.ios.cs +++ b/ZXing.Net.Mobile/iOS/ZXingScannerView.ios.cs @@ -37,6 +37,7 @@ public ZXingScannerView(CGRect frame) : base(frame) } AVCaptureSession session; + AVCaptureDevice captureDevice = null; AVCaptureVideoPreviewLayer previewLayer; AVCaptureVideoDataOutput output; OutputRecorder outputRecorder; @@ -56,7 +57,9 @@ public ZXingScannerView(CGRect frame) : base(frame) bool shouldRotatePreviewBuffer = false; - void Setup(CGRect frame) + AVConfigs captureDeviceOriginalConfig; + + void Setup() { var started = DateTime.UtcNow; @@ -91,7 +94,6 @@ void Setup(CGRect frame) bool torch = false; bool analyzing = true; - bool SetupCaptureSession() { var started = DateTime.UtcNow; @@ -114,8 +116,6 @@ bool SetupCaptureSession() }; // create a device input and attach it to the session - // var captureDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video); - AVCaptureDevice captureDevice = null; var devices = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video); foreach (var device in devices) { @@ -273,9 +273,25 @@ bool SetupCaptureSession() var perf5 = PerformanceCounter.Start(); - NSError err = null; - if (captureDevice.LockForConfiguration(out err)) + if (captureDevice.LockForConfiguration(out var err)) { + captureDeviceOriginalConfig = new AVConfigs + { + FocusMode = captureDevice.FocusMode, + ExposureMode = captureDevice.ExposureMode, + WhiteBalanceMode = captureDevice.WhiteBalanceMode, + AutoFocusRangeRestriction = captureDevice.AutoFocusRangeRestriction, + }; + + if (captureDevice.HasFlash) + captureDeviceOriginalConfig.FlashMode = captureDevice.FlashMode; + if (captureDevice.HasTorch) + captureDeviceOriginalConfig.TorchMode = captureDevice.TorchMode; + if (captureDevice.FocusPointOfInterestSupported) + captureDeviceOriginalConfig.FocusPointOfInterest = captureDevice.FocusPointOfInterest; + if (captureDevice.ExposurePointOfInterestSupported) + captureDeviceOriginalConfig.ExposurePointOfInterest = captureDevice.ExposurePointOfInterest; + if (ScanningOptions.DisableAutofocus) { captureDevice.FocusMode = AVCaptureFocusMode.Locked; @@ -299,7 +315,9 @@ bool SetupCaptureSession() captureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.AutoWhiteBalance; if (UIDevice.CurrentDevice.CheckSystemVersion(7, 0) && captureDevice.AutoFocusRangeRestrictionSupported) + { captureDevice.AutoFocusRangeRestriction = AVCaptureAutoFocusRangeRestriction.Near; + } if (captureDevice.FocusPointOfInterestSupported) captureDevice.FocusPointOfInterest = new PointF(0.5f, 0.5f); @@ -489,7 +507,7 @@ public void StartScanning(Action scanResultHandler, MobileBarcodeScannin var perf = PerformanceCounter.Start(); - Setup(Frame); + Setup(); ScanningOptions = options ?? MobileBarcodeScanningOptions.Default; resultCallback = scanResultHandler; @@ -506,10 +524,11 @@ public void StartScanning(Action scanResultHandler, MobileBarcodeScannin if (Runtime.Arch == Arch.SIMULATOR) { - var simView = new UIView(new CGRect(0, 0, this.Frame.Width, this.Frame.Height)); - simView.BackgroundColor = UIColor.LightGray; - simView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight; - InsertSubview(simView, 0); + InsertSubview(new UIView(new CGRect(0, 0, this.Frame.Width, this.Frame.Height)) + { + BackgroundColor = UIColor.LightGray, + AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight + }, 0); } }); @@ -540,6 +559,30 @@ public void StopScanning() if (outputRecorder != null) outputRecorder.CancelTokenSource.Cancel(); + // Revert camera settings to original + if (captureDevice != null && captureDevice.LockForConfiguration(out var err)) + { + captureDevice.FocusMode = captureDeviceOriginalConfig.FocusMode; + captureDevice.ExposureMode = captureDeviceOriginalConfig.ExposureMode; + captureDevice.WhiteBalanceMode = captureDeviceOriginalConfig.WhiteBalanceMode; + + if (UIDevice.CurrentDevice.CheckSystemVersion(7, 0) && captureDevice.AutoFocusRangeRestrictionSupported) + captureDevice.AutoFocusRangeRestriction = captureDeviceOriginalConfig.AutoFocusRangeRestriction; + + if (captureDevice.FocusPointOfInterestSupported) + captureDevice.FocusPointOfInterest = captureDeviceOriginalConfig.FocusPointOfInterest; + + if (captureDevice.ExposurePointOfInterestSupported) + captureDevice.ExposurePointOfInterest = captureDeviceOriginalConfig.ExposurePointOfInterest; + + if (captureDevice.HasFlash) + captureDevice.FlashMode = captureDeviceOriginalConfig.FlashMode; + if (captureDevice.HasTorch) + captureDevice.TorchMode = captureDeviceOriginalConfig.TorchMode; + + captureDevice.UnlockForConfiguration(); + } + //Try removing all existing outputs prior to closing the session try { @@ -572,34 +615,35 @@ public void Torch(bool on) { try { - NSError err; - - var device = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video); - - if (device.HasTorch || device.HasFlash) + var device = captureDevice ?? AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video); + if (device != null && (device.HasTorch || device.HasFlash)) { + device.LockForConfiguration(out var err); - device.LockForConfiguration(out err); - - if (on) + if (err != null) { - if (device.HasTorch) - device.TorchMode = AVCaptureTorchMode.On; - if (device.HasFlash) - device.FlashMode = AVCaptureFlashMode.On; + if (on) + { + if (device.HasTorch) + device.TorchMode = AVCaptureTorchMode.On; + if (device.HasFlash) + device.FlashMode = AVCaptureFlashMode.On; + } + else + { + if (device.HasTorch) + device.TorchMode = AVCaptureTorchMode.Off; + if (device.HasFlash) + device.FlashMode = AVCaptureFlashMode.Off; + } } - else + + try { - if (device.HasTorch) - device.TorchMode = AVCaptureTorchMode.Off; - if (device.HasFlash) - device.FlashMode = AVCaptureFlashMode.Off; + device.UnlockForConfiguration(); } - - device.UnlockForConfiguration(); + catch { } } - device = null; - torch = on; } @@ -636,11 +680,23 @@ public bool HasTorch if (hasTorch.HasValue) return hasTorch.Value; - var device = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video); + var device = captureDevice ?? AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video); hasTorch = device.HasFlash || device.HasTorch; return hasTorch.Value; } } #endregion } + + struct AVConfigs + { + public AVCaptureFocusMode FocusMode; + public AVCaptureExposureMode ExposureMode; + public AVCaptureWhiteBalanceMode WhiteBalanceMode; + public AVCaptureAutoFocusRangeRestriction AutoFocusRangeRestriction; + public CGPoint FocusPointOfInterest; + public CGPoint ExposurePointOfInterest; + public AVCaptureFlashMode FlashMode; + public AVCaptureTorchMode TorchMode; + } }