-4.2 C
New York
Saturday, February 22, 2025

ios – Customized digital camera view not displaying


I’ve been utilizing Zxing.Maui nuget for QR code scanning nevertheless it doesn’t work for some small QR codes. After some digging I discovered that AVCaptureSession with IAVCaptureMetadataOutputObjectsDelegate works for this. I’m referring vinodiOS/SwiftQRCodeScanner to attain this.

My MAUI customized management code as follows. In debug I do see view is being created and CaptureSession working nevertheless UI doesn’t present digital camera preview. I additionally tried so as to add this ZXing.MAUI fork however IAVCaptureMetadataOutputObjectsDelegate.DidOutputMetadataObjects doesn’t get hit there even with [Export("captureOutput:didOutputMetadataObjects:fromConnection:")] getting used. I regarded up how they’re including sublayering VideoPreviewLayer in Zxing.MAUI library and tried that right here as nicely(see LayoutSubviews() beneath). That additionally doesn’t present UI.
I’m doing one thing flawed clearly. Cant determine what.

public class QRCodeReaderView : View
{
    public static readonly BindableProperty IsScanningProperty = BindableProperty.Create(nameof(IsScanning), typeof(bool), typeof(CameraView), true);

    public bool IsScanning
    {
        get => (bool)GetValue(IsScanningProperty);
        set => SetValue(IsScanningProperty, worth);
    }

    
    public occasion EventHandler? OnBarcodeDetected;

    public void RaiseBarcodeDetected(string barcode)
    {
        OnBarcodeDetected?.Invoke(this, new BarcodeDetectedEventArgs(barcode));
    }
}
public partial class QRCodeReaderViewHandler : ViewHandler
{
    protected override IosQRCodeReaderView CreatePlatformView()
    {
       var management = new IosQRCodeReaderView();
       return management;
    }
    
    personal static void MapIsScanning(QRCodeReaderViewHandler handler, QRCodeReaderView qrCodeReaderView)
    {
        
    }

    personal static void MapOnBarcodeDetected(QRCodeReaderViewHandler handler, QRCodeReaderView qrCodeReaderView, object? args)
    {
        //TODO
    }
}

Native view

utilizing System.Diagnostics;
utilizing AVFoundation;
utilizing CoreAnimation;
utilizing CoreFoundation;
utilizing Basis;
utilizing UIKit;

namespace QRCodeScanner;

public class IosQRCodeReaderView : UIView, IAVCaptureMetadataOutputObjectsDelegate
{
    personal readonly AVCaptureDevice? _defaultDevice; 
    personal AVCaptureInput? _defaultCaptureInput => _defaultDevice isn't null ?  AVCaptureDeviceInput.FromDevice(_defaultDevice) : null;
    personal readonly AVCaptureMetadataOutput _dataOutput;
    personal readonly AVCaptureSession _captureSession;
    personal readonly AVCaptureDevicePosition _devicePosition = AVCaptureDevicePosition.Again;

    public occasion EventHandler? QRCodeDetected;

    personal readonly AVCaptureVideoPreviewLayer _videoPreviewLayer;
    

    public IosQRCodeReaderView(AVCaptureDevicePosition place = AVCaptureDevicePosition.Again)
    {
        _defaultDevice = AVCaptureDevice.GetDefaultDevice(AVMediaTypes.Video);
        _captureSession =  new AVCaptureSession();
        _devicePosition = place;
        _dataOutput = new AVCaptureMetadataOutput();
        _videoPreviewLayer = new AVCaptureVideoPreviewLayer(_captureSession)
        {
            VideoGravity = AVLayerVideoGravity.ResizeAspectFill,
            CornerRadius = 10.0f,
        };
        PrepareQRScanner();
        StartScanningQRCode();
    }
    
    public override void LayoutSubviews()
    {
        base.LayoutSubviews();
        var rework = CATransform3D.MakeRotation(0, 0, 0, 1.0f);
        swap (UIDevice.CurrentDevice.Orientation)
        {
            case UIDeviceOrientation.Portrait:
                rework = CATransform3D.MakeRotation(0, 0, 0, 1.0f);
                break;
            case UIDeviceOrientation.PortraitUpsideDown:
                rework = CATransform3D.MakeRotation((nfloat)Math.PI, 0, 0, 1.0f);
                break;
            case UIDeviceOrientation.LandscapeLeft:
                rework = CATransform3D.MakeRotation((nfloat)(-Math.PI / 2), 0, 0, 1.0f);
                break;
            case UIDeviceOrientation.LandscapeRight:
                rework = CATransform3D.MakeRotation((nfloat)Math.PI / 2, 0, 0, 1.0f);
                break;
            case UIDeviceOrientation.Unknown:
            case UIDeviceOrientation.FaceUp:
            case UIDeviceOrientation.FaceDown:
            default:
                break;
        }

        _videoPreviewLayer.Remodel = rework;
        _videoPreviewLayer.Body = Layer.Bounds;
        AddMaskToVideoPreviewLayer();
    }

    personal void SetupCaptureSession()
    {
        if (_captureSession.Working)
        {
            return;
        }
        _captureSession.BeginConfiguration();
        swap (_devicePosition)
        {
            case AVCaptureDevicePosition.Entrance:

                //TODO
                break;
            case AVCaptureDevicePosition.Unspecified:
            case AVCaptureDevicePosition.Again:
                if (_defaultCaptureInput isn't null && _captureSession.CanAddInput(_defaultCaptureInput))
                {
                    _captureSession.AddInput(_defaultCaptureInput);
                }
                break;
            default:
                Debug.WriteLine("Do nothing");
                break;
        }

        
        if (_captureSession.CanAddOutput(_dataOutput)  is fake)
        {
            return;
        }
        _captureSession.AddOutput(_dataOutput);
        _dataOutput.MetadataObjectTypes = _dataOutput.AvailableMetadataObjectTypes;
        _dataOutput.SetDelegate(this, DispatchQueue.MainQueue);
        Debug.WriteLine(_dataOutput.AvailableMetadataObjectTypes);
        _captureSession.CommitConfiguration();
    }

    personal void PrepareQRScanner()
    {
        SetupCaptureSession();
    }



    personal AVCaptureDeviceInput? GetCurrentInput()
    {
        if (_captureSession.Inputs.FirstOrDefault() is AVCaptureDeviceInput deviceInput)
        {
            return deviceInput;
        }
        return null;
    }

    personal void StartScanningQRCode()
    {
        if (_captureSession.Working)
        {
            return;
        }
        //DispatchQueue.GetGlobalQueue(DispatchQualityOfService.Background).DispatchAsync(_captureSession.StartRunning);
        MainThread.BeginInvokeOnMainThread(_captureSession.StartRunning);
    }
    
    personal void AddMaskToVideoPreviewLayer()
    {
        //TODO: add
    }

    personal int _delayCount = 0;
    personal const int MaxDelayCount = 15;

    [Export("captureOutput:didOutputMetadataObjects:fromConnection:")]
    public void DidOutputMetadataObjects(AVCaptureMetadataOutput captureOutput, AVMetadataObject[] metadataObjects, AVCaptureConnection connection)
    {
        attempt
        {
            foreach (var information in metadataObjects)
             _videoPreviewLayer.Bounds.Incorporates(remodeled.Bounds) is fake) 
                    proceed;
                _delayCount += 1;
                if (_delayCount < MaxDelayCount) 
                    proceed;
                if (string.IsNullOrEmpty(remodeled.StringValue))
                    proceed;
                QRCodeDetected?.Invoke(this, new QRCodeEventArgs(remodeled.StringValue));
                _captureSession.StopRunning();
            
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.StackTrace);
        }
    }
}

Handler task

builder.ConfigureMauiHandlers(handlers =>
{
     handlers.AddHandler();

});



    
        

personal async Job CheckAndRequestCameraPermission()
{
    var standing = await Permissions.CheckStatusAsync();
    if (standing != PermissionStatus.Granted)
    {
        standing = await Permissions.RequestAsync();
        if (standing != PermissionStatus.Granted)
        {
            await DisplayAlert("Digital camera Permission Denied", "This app wants entry to the digital camera to scan QR codes.", "OK");
            return; // Or disable the scanning performance
        }
    }
}

protected override async void OnAppearing()
{
    base.OnAppearing();
    await CheckAndRequestCameraPermission();
}

Screenshot

If anybody has an thought why is that this occurring that will be an important assist.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles