CameraView.Maui 1.3.2

dotnet add package CameraView.Maui --version 1.3.2
                    
NuGet\Install-Package CameraView.Maui -Version 1.3.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CameraView.Maui" Version="1.3.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CameraView.Maui" Version="1.3.2" />
                    
Directory.Packages.props
<PackageReference Include="CameraView.Maui" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CameraView.Maui --version 1.3.2
                    
#r "nuget: CameraView.Maui, 1.3.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CameraView.Maui@1.3.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CameraView.Maui&version=1.3.2
                    
Install as a Cake Addin
#tool nuget:?package=CameraView.Maui&version=1.3.2
                    
Install as a Cake Tool

CameraView.Maui

CameraView.Maui is a .NET MAUI camera preview control for Android and iOS. It uses Camera2 and AVFoundation, emits encoded JPEG frames or zero-copy native camera buffers, and exposes live zoom, torch, focus, exposure, and preview-mirroring controls.

The package supports .NET 9 and .NET 10 MAUI applications.

Supported platforms

Platform Minimum version
Android API 28
iOS 15.0

Installation

dotnet add package CameraView.Maui

Register the handler in MauiProgram.cs:

using CameraView.Maui;

builder
    .UseMauiApp<App>()
    .UseCameraView();

XAML usage

<ContentPage
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:camera="clr-namespace:CameraView.Maui;assembly=CameraView.Maui">

    <camera:CameraView
        x:Name="CameraPreview"
        Camera="Rear"
        Orientation="Portrait" />
</ContentPage>

Subscribe to OnFrameResult to receive JPEG frames. The callback runs on a native capture queue, so marshal UI updates to the main thread:

private void OnFrameResult(CameraResult result)
{
    if (!result.Success || result.Image is null)
        return;

    byte[] jpeg = result.Image;

    MainThread.BeginInvokeOnMainThread(() =>
    {
        StatusLabel.Text = $"Received {jpeg.Length:N0} bytes";
    });
}

Subscribe and unsubscribe with the page lifecycle:

protected override void OnAppearing()
{
    base.OnAppearing();
    CameraPreview.OnFrameResult += OnFrameResult;
    CameraPreview.Enabled = true;
}

protected override void OnDisappearing()
{
    CameraPreview.Enabled = false;
    CameraPreview.OnFrameResult -= OnFrameResult;
    base.OnDisappearing();
}

CameraResult.Image is a complete JPEG byte array. It can be saved directly:

var path = Path.Combine(FileSystem.CacheDirectory, "camera-frame.jpg");
await File.WriteAllBytesAsync(path, result.Image);

High-throughput raw frames

Use the opt-in realtime profile for OCR, barcode, computer-vision, and ML workloads that can consume luminance or YUV data directly:

CameraPreview.CaptureOptions = CameraCaptureOptions.Realtime;
CameraPreview.FrameAvailable += (_, args) =>
{
    CameraFrame frame = args.Frame;
    CameraFramePlane yPlane = frame.Planes[0];
    AnalyzeLuminance(
        yPlane.Span,
        yPlane.Width,
        yPlane.Height,
        yPlane.RowStride,
        frame.RotationDegrees);
};

The event frame is borrowed. Access it synchronously, or call Retain() before asynchronous work and dispose the retained frame afterward. Native resolves to YUV on both platforms: Android supplies three YUV_420_888 planes and iOS supplies two NV12 planes. Inspect EffectiveConfiguration.Capabilities before requesting optional formats such as Bgra8888.

Processing frames

Frames can arrive faster than OCR, barcode, ML, upload, or disk processing can finish. Avoid starting an unlimited number of tasks. This gate drops incoming frames while one frame is being processed:

private readonly SemaphoreSlim _frameGate = new(1, 1);

private async void OnFrameResult(CameraResult result)
{
    if (!result.Success ||
        result.Image is null ||
        !_frameGate.Wait(0))
        return;

    try
    {
        using var stream = new MemoryStream(result.Image, writable: false);

        // Pass stream or result.Image to the selected processor.
        await ProcessJpegAsync(stream);
    }
    catch (Exception exception)
    {
        System.Diagnostics.Debug.WriteLine(
            $"Frame processing failed: {exception}");
    }
    finally
    {
        _frameGate.Release();
    }
}

private static Task ProcessJpegAsync(Stream jpeg)
{
    // Call the selected OCR, barcode, ML, upload, or decoder API.
    return Task.CompletedTask;
}

For “latest frame wins” processing, use a bounded Channel<byte[]> with capacity one and BoundedChannelFullMode.DropOldest. The full example includes lifecycle cancellation.

CameraView.Maui does not force a specific decoder. If the processor needs pixels instead of JPEG bytes, decode off the UI thread with a mobile-compatible image library, dispose decoder resources promptly, and move only final UI updates to MainThread.

Do not render every callback into another MAUI Image: CameraView already displays a native live preview, and a second decode adds avoidable CPU and allocation pressure.

Camera state

CameraPreview.Camera = CameraOptions.Front;
CameraPreview.Orientation = CameraOrientation.Landscape;
CameraPreview.Enabled = false;

Changing Camera or Orientation reconfigures the native session. Set Enabled to false when preview or capture is not required. The control releases the camera while the app is inactive and restarts it when the app resumes if Enabled remains true.

Observe the actual native state and structured failures:

CameraPreview.StateChanged += (_, args) =>
    StateLabel.Text = $"{args.State} ({args.Camera})";

CameraPreview.ErrorOccurred += (_, args) =>
    ErrorLabel.Text = $"{args.Code}: {args.Message}";

StateChanged and ErrorOccurred run through the MAUI dispatcher. State can be Stopped, Starting, Running, Suspended, PermissionDenied, or Failed; IsRunning is true only for an active native session. OnFrameResult and FrameAvailable remain on the native capture queue.

Capture configuration

Apply resolution, quality, and delivery-rate changes together:

CameraPreview.CaptureOptions = CameraCaptureOptions.Balanced with
{
    PreferredResolution = new CameraResolution(1600, 1200),
    ResolutionSelectionMode = CameraResolutionSelectionMode.AtMost,
    JpegQuality = 82,
    MaximumFrameRate = 12.5
};

CameraPreview.EffectiveConfigurationChanged += (_, args) =>
{
    if (args.Configuration is { } selected)
        StatusLabel.Text = $"{selected.CaptureResolution}";
};

Use Closest, AtMost, or AtLeast for deterministic fallback. Exact fails with SessionConfigurationFailed when the device does not expose the requested size. CameraCaptureOptions.Default retains the platform JPEG default and 720p-or-lower selection used by 1.0.

Interactive controls

Control changes update the active native request/device without restarting capture:

CameraPreview.ControlOptions = CameraPreview.ControlOptions with
{
    ZoomFactor = 2,
    TorchEnabled = true,
    ExposureCompensation = 0.5,
    FocusMode = CameraFocusMode.Single,
    FocusPoint = new CameraPoint(0.4, 0.6),
    PreviewMirroring = CameraPreviewMirroringMode.Automatic
};

CameraPoint is normalized against the visible preview from top-left (0,0) to bottom-right (1,1). Use Single for tap-to-focus and reset to Continuous with a null point for centered continuous autofocus.

Subscribe to EffectiveControlsChanged to configure UI from the selected camera's actual capabilities and applied values:

CameraPreview.EffectiveControlsChanged += (_, args) =>
{
    if (args.State is not { } controls)
        return;

    ZoomSlider.Minimum = controls.Capabilities.MinimumZoomFactor;
    ZoomSlider.Maximum = controls.Capabilities.MaximumZoomFactor;
    ZoomSlider.IsEnabled = controls.Capabilities.IsZoomSupported;
    TorchButton.IsEnabled = controls.Capabilities.IsTorchSupported;
    ZoomSlider.Value = controls.ZoomFactor;
};

Zoom and exposure are clamped, Android exposure can be quantized to a native step, and unsupported torch/focus requests fall back without stopping capture. Inspect the Used*Fallback flags. Options survive camera switching and resume and are renegotiated for the active camera.

PreviewMirroring changes only the preview. Inspect CameraFrame.IsMirrored for delivered output.

Permissions

The package contributes android.permission.CAMERA and the optional android.hardware.camera.any feature to the merged Android manifest.

iOS applications must add a user-facing description to Info.plist:

<key>NSCameraUsageDescription</key>
<string>The camera is used to capture images.</string>

More information

Full documentation, troubleshooting, and release notes are available in the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net9.0-android35.0 is compatible.  net9.0-ios18.0 is compatible.  net10.0-android was computed.  net10.0-android36.0 is compatible.  net10.0-ios was computed.  net10.0-ios26.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.2 145 8/8/2026
1.3.1 117 8/8/2026
1.3.0 113 8/7/2026
1.2.2 113 8/7/2026
1.2.1 125 8/7/2026
1.1.0 115 8/5/2026
1.0.1 122 8/5/2026
1.0.0 119 8/5/2026