Skip to content

Introduce the ability to extend camera functionality - #3274

Draft
bijington wants to merge 5 commits into
mainfrom
feature/sl-camera-processing
Draft

Introduce the ability to extend camera functionality#3274
bijington wants to merge 5 commits into
mainfrom
feature/sl-camera-processing

Conversation

@bijington

@bijington bijington commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Current status

This it the remaining TODO list

  • Tested on macOS for both - Shared page crashes
  • Needs to be built and tested on Android
  • Needs to be built and tested on Windows

Introduce the ability to extend camera functionality for concepts such as Barcode scanning.

Replaces the original PR attempt at #2841.

Description of Change

Camera Scenarios Usage Guide

The Community Toolkit for MAUI CameraView allows extending its functionality through "Scenarios". There are two primary ways to implement a scenario: PlatformCameraScenario and FrameBasedCameraScenario.

PlatformCameraScenario

PlatformCameraScenario is designed for scenarios where you want to leverage platform-specific high-performance APIs (e.g., Google ML Kit on Android, Apple Vision framework on iOS, or Windows Media Capture APIs).

When to use it
  • When performance is critical.
  • When you want to use a feature already provided by the operating system.
  • When you need fine-grained control over the platform-specific camera pipeline.
Implementation Example (Windows)

In the sample project, PlatformBarcodeScanningScenario on Windows uses the MediaFrameReader to capture frames and decode them using ZXing.Net within the platform-specific code.

// Platforms/Windows/PlatformBarcodeScanningScenario.cs
public class PlatformBarcodeScanningScenario : PlatformCameraScenario
{
    // ... Windows specific implementation using MediaFrameReader
}

FrameBasedCameraScenario

FrameBasedCameraScenario is a specialized version of PlatformCameraScenario that abstracts the frame capture process. It provides a platform-agnostic OnFrameReceived method that gives you access to a CameraFrame containing raw byte data.

When to use it
  • When you want to share the same processing logic across all platforms.
  • When you have a cross-platform library (like ZXing.Net) that can process raw image data.
  • When you don't need the absolute maximum performance of platform-native ML frameworks.
Implementation Example (Shared)

In the sample project, SharedBarcodeScanningScenario demonstrates how to implement barcode scanning in shared code.

// SharedBarcodeScanningScenario.cs
public class SharedBarcodeScanningScenario : FrameBasedCameraScenario
{
    public override void OnFrameReceived(CameraFrame frame)
    {
        // frame.Data contains the raw byte array
        // frame.Width and frame.Height provide dimensions
        
        var luminanceSource = new RGBLuminanceSource(frame.Data, frame.Width, frame.Height);
        var result = barcodeReader.Decode(luminanceSource);

        if (result is not null)
        {
            // Handle result
        }
    }
}

Key Differences

Feature PlatformCameraScenario FrameBasedCameraScenario
Logic Location Platform-specific folders Shared code
Performance Highest (Native APIs) Good (Shared processing)
Complexity Higher (Needs platform knowledge) Lower (Abstraction handled for you)
Data Access Native objects (e.g., ImageProxy, CMSampleBuffer) CameraFrame (Raw bytes)

Usage in XAML

Both types of scenarios are used in the same way with the CameraView.

<toolkit:CameraView>
    <toolkit:CameraView.Scenarios>
        <!-- Use either a platform-specific scenario -->
        <sample:PlatformBarcodeScanningScenario Command="{Binding OnCodeDetectedCommand}" />
        
        <!-- Or a shared frame-based scenario -->
        <sample:SharedBarcodeScanningScenario Command="{Binding OnCodeDetectedCommand}" />
    </toolkit:CameraView.Scenarios>
</toolkit:CameraView>

Linked Issues

  • Fixes #

PR Checklist

Additional information

Example of it working on macOS

scanning.mov

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we still supporting Tizen? it's not possible to build a MAUI app on tizen as it's stuck on Net6...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I needed to patch this for the builds to pass but it won't do anything

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an extensibility mechanism to CameraView via attachable “scenarios” (e.g., barcode scanning), wires scenario handling into platform camera pipelines (Android/iOS), and provides a sample barcode-scanning page demonstrating the new capability.

Changes:

  • Introduces ICameraView.Scenarios / CameraView.Scenarios as a collection of CameraScenario instances.
  • Adds CameraManager scenario management (add/remove/reset) plus platform hooks to integrate platform-specific outputs/use-cases.
  • Adds a new sample page and platform implementations for barcode scanning (including an Android MLKit package reference).

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
src/CommunityToolkit.Maui.Camera/Views/CameraView.shared.cs Adds Scenarios bindable collection to CameraView.
src/CommunityToolkit.Maui.Camera/Interfaces/ICameraView.shared.cs Exposes Scenarios on the camera view contract.
src/CommunityToolkit.Maui.Camera/Handlers/CameraViewHandler.shared.cs Maps Scenarios and reacts to collection changes to update camera pipeline.
src/CommunityToolkit.Maui.Camera/Primitives/CameraScenario.shared.cs Introduces base scenario lifecycle API (Initialize, attach/detach hooks).
src/CommunityToolkit.Maui.Camera/Primitives/PlatformCameraScenario.shared.cs Adds a platform-specialized scenario base type.
src/CommunityToolkit.Maui.Camera/Primitives/PlatformCameraScenario.android.cs Declares Android-specific platform scenario surface (UseCase).
src/CommunityToolkit.Maui.Camera/Primitives/PlatformCameraScenario.macios.cs Declares Apple-specific platform scenario surface (AVCaptureOutput).
src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs Adds scenario list + add/remove/reset and preview refresh behavior.
src/CommunityToolkit.Maui.Camera/CameraManager.android.cs Integrates additional UseCases into rebinding flow.
src/CommunityToolkit.Maui.Camera/CameraManager.macios.cs Integrates scenario outputs into AVCaptureSession startup.
src/CommunityToolkit.Maui.Camera/CameraManager.net.cs Adds scenario APIs for unsupported platforms (throws NotSupported).
src/CommunityToolkit.Maui.Camera/CameraManager.tizen.cs Adjusts partial method signatures and adds scenario APIs (throws NotSupported).
samples/CommunityToolkit.Maui.Sample/ViewModels/Views/ViewsGalleryViewModel.cs Adds a sample gallery entry for barcode scanning.
samples/CommunityToolkit.Maui.Sample/ViewModels/Views/CameraView/BarcodeScanningViewModel.cs New view model to display detected barcode text and refresh cameras.
samples/CommunityToolkit.Maui.Sample/Pages/Views/CameraView/BarcodeScanningPage.xaml New page wiring CameraView.Scenarios to a barcode-scanning scenario.
samples/CommunityToolkit.Maui.Sample/Pages/Views/CameraView/BarcodeScanningPage.xaml.cs New page code-behind to refresh camera list on appearing.
samples/CommunityToolkit.Maui.Sample/PlatformBarcodeScanningScenario.cs Shared scenario surface (bindable Command) for barcode detection callbacks.
samples/CommunityToolkit.Maui.Sample/Platforms/PlatformBarcodeScanningScenario.cs Adds a partial scenario file in Platforms folder.
samples/CommunityToolkit.Maui.Sample/Platforms/Android/PlatformBarcodeScanningScenario.cs Android-specific scenario implementation using CameraX ImageAnalysis.
samples/CommunityToolkit.Maui.Sample/Platforms/Android/BarcodeAnalyzer.cs Android barcode analyzer implementation using MLKit.
samples/CommunityToolkit.Maui.Sample/Platforms/iOS/PlatformBarcodeScanningScenario.cs iOS-specific scenario using AVCaptureMetadataOutput.
samples/CommunityToolkit.Maui.Sample/Platforms/MacCatalyst/PlatformBarcodeScanningScenario.cs Mac Catalyst-specific scenario using AVCaptureMetadataOutput.
samples/CommunityToolkit.Maui.Sample/MauiProgram.cs Registers the new barcode scanning page + view model.
samples/CommunityToolkit.Maui.Sample/AppShell.xaml.cs Adds shell mapping for barcode scanning page.
samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj Adds Android-only MLKit barcode scanning package reference.

Comment on lines +25 to +27
readonly IList<CameraScenario> scenarios = [];

protected IReadOnlyList<CameraScenario> Scenarios => scenarios.AsReadOnly();
Comment on lines +5 to +9
/// <summary>
///
/// </summary>
partial class PlatformCameraScenario : CameraScenario
{
Comment on lines +5 to +9
/// <summary>
///
/// </summary>
partial class PlatformCameraScenario : CameraScenario
{
Comment on lines +6 to +12
/// <summary>
///
/// </summary>
public partial class PlatformBarcodeScanningScenario : PlatformCameraScenario
{
public ICommand? Command { get; set; }
} No newline at end of file
Comment on lines +19 to +21
<toolkit:CameraView.Scenarios>
<sample:PlatformBarcodeScanningScenario Command="{Binding BindingContext.CodeDetectedCommand, Source={x:Reference Camera}}" />
</toolkit:CameraView.Scenarios>
Comment on lines +24 to +26
/// <summary>Bindable property for <see cref="CameraScenario"/>.</summary>
public static readonly BindableProperty ScenariosProperty = ScenariosPropertyKey.BindableProperty;

Comment on lines 295 to 297
/// <inheritdoc cref="ICameraView.StopCameraPreview"/>
public void StopCameraPreview() =>
Handler.CameraManager.StopCameraPreview();
public void StopCameraPreview() =>Handler.CameraManager.StopCameraPreview();

Comment on lines +14 to +18
base.OnAppearing();

var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(3));
await BindingContext.RefreshCamerasCommand.ExecuteAsync(cancellationTokenSource.Token);
}
Comment on lines +21 to +33
/// <summary>
///
/// </summary>
public virtual void OnAttached()
{
}

/// <summary>
///
/// </summary>
public virtual void OnDetached()
{
}
Comment on lines +3 to +7
/// <summary>
///
/// </summary>
public abstract partial class PlatformCameraScenario : CameraScenario
{
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants