Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,30 @@ The `BarcodeGeneratorView` supports UTF-8 character encoding by default, which a

The `CharacterSet` property defaults to "UTF-8" if not specified. Other common values include "ISO-8859-1", "Shift_JIS", etc., depending on your barcode format requirements.

## Troubleshooting

### Release Build Crashes (Trimming/Linker Issues)

If your app crashes when opening the scanner in release builds but works fine in debug builds, this is likely due to aggressive code trimming by the .NET linker.

**This library is now trimmer-safe** and includes the necessary `[DynamicDependency]` attributes to preserve required code during trimming.

If you're still experiencing issues:

1. **Update to the latest version** of ZXing.Net.Maui.Controls which includes trimming safety improvements
2. **Verify you're calling `UseBarcodeReader()`** in your `MauiProgram.cs` - this properly registers the handlers with trimming support
3. **If issues persist**, you can exclude the assembly from trimming by adding this to your .csproj:

```xml
<ItemGroup>
<TrimmerRootAssembly Include="ZXing.Net.Maui" />
<TrimmerRootAssembly Include="ZXing.Net.Maui.Controls" />
</ItemGroup>
```

For more information about .NET MAUI trimming:
- [Trim a .NET MAUI app](https://learn.microsoft.com/dotnet/maui/deployment/trimming)
- [Prepare .NET libraries for trimming](https://learn.microsoft.com/dotnet/core/deploying/trimming/prepare-libraries-for-trimming)



5 changes: 5 additions & 0 deletions ZXing.Net.MAUI.Controls/Controls/BarcodeGeneratorView.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using System.Diagnostics.CodeAnalysis;

namespace ZXing.Net.Maui.Controls
{
/// <summary>
/// A MAUI view for generating barcode images.
/// This class is trimmer-safe through the bindable property system.
/// </summary>
public partial class BarcodeGeneratorView : View, IBarcodeGeneratorView
{
public static readonly BindableProperty FormatProperty =
Expand Down
5 changes: 5 additions & 0 deletions ZXing.Net.MAUI.Controls/Controls/CameraBarcodeReaderView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
using Microsoft.Maui.Graphics;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;

namespace ZXing.Net.Maui.Controls
{
/// <summary>
/// A MAUI view for camera-based barcode scanning.
/// This class is trimmer-safe through the bindable property system.
/// </summary>
public partial class CameraBarcodeReaderView : View, ICameraBarcodeReaderView
{
public event EventHandler<BarcodeDetectionEventArgs> BarcodesDetected;
Expand Down
5 changes: 5 additions & 0 deletions ZXing.Net.MAUI.Controls/Controls/CameraView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
using Microsoft.Maui.Graphics;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;

namespace ZXing.Net.Maui.Controls
{
/// <summary>
/// A MAUI view for camera preview functionality.
/// This class is trimmer-safe through the bindable property system.
/// </summary>
public partial class CameraView : View, ICameraView
{
public event EventHandler<CameraFrameBufferEventArgs> FrameReady;
Expand Down
13 changes: 12 additions & 1 deletion ZXing.Net.MAUI.Controls/HostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,23 @@
using Microsoft.Maui;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZXing.Net.Maui.Controls;

namespace ZXing.Net.Maui.Controls
{
/// <summary>
/// Extension methods for configuring barcode reader in MAUI applications.
/// </summary>
public static class CameraViewExtensions
{
/// <summary>
/// Registers barcode reader handlers and services with the MAUI app builder.
/// </summary>
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(Readers.ZXingBarcodeReader))]
public static MauiAppBuilder UseBarcodeReader(this MauiAppBuilder builder)
{
builder.ConfigureMauiHandlers(handlers =>
Expand All @@ -48,7 +56,10 @@ public static MauiAppBuilder UseBarcodeReader(this MauiAppBuilder builder)
return builder;
}

public static MauiAppBuilder UseBarcodeReader<TBarcodeReader>(this MauiAppBuilder builder) where TBarcodeReader : class, Readers.IBarcodeReader
/// <summary>
/// Registers barcode reader handlers and services with a custom barcode reader implementation.
/// </summary>
public static MauiAppBuilder UseBarcodeReader<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TBarcodeReader>(this MauiAppBuilder builder) where TBarcodeReader : class, Readers.IBarcodeReader
{
builder.ConfigureMauiHandlers(handlers =>
{
Expand Down
5 changes: 4 additions & 1 deletion ZXing.Net.MAUI.Controls/ZXing.Net.MAUI.Controls.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
<DebugType>portable</DebugType>
<OutputType>Library</OutputType>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<!-- Enable trimming support and indicate library is trim-safe and AOT-compatible -->
<IsTrimmable>true</IsTrimmable>
Comment thread
jfversluis marked this conversation as resolved.
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ZXing.Net" Version="0.16.11" />
</ItemGroup>
Expand Down
11 changes: 11 additions & 0 deletions ZXing.Net.MAUI/BarcodeGeneratorViewHandler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Maui;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System;
using ZXing;
Expand All @@ -9,6 +10,10 @@

namespace ZXing.Net.Maui
{
/// <summary>
/// Handler for BarcodeGeneratorView that generates barcode images.
/// This handler is trimmer-safe with appropriate DynamicDependency attributes.
/// </summary>
public partial class BarcodeGeneratorViewHandler : ViewHandler<IBarcodeGeneratorView, NativePlatformImageView>
{
Size desiredSize;
Expand All @@ -24,11 +29,17 @@ public partial class BarcodeGeneratorViewHandler : ViewHandler<IBarcodeGenerator
[nameof(IBarcodeGeneratorView.CharacterSet)] = MapUpdateBarcode,
};

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(BarcodeGeneratorViewHandler))]
[DynamicDependency(nameof(BarcodeGeneratorViewMapper))]
[DynamicDependency(nameof(MapUpdateBarcode))]
Comment on lines +32 to +34
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't understand these DynamicDependency attributes, why are they here? Also where are we accessing the BarcodeGeneratorViewMapper or MapUpdateBarcode methods by reflection? It seems those DD attributes should be used in that location and not here.

public BarcodeGeneratorViewHandler() : base(BarcodeGeneratorViewMapper)
{
writer = new BarcodeWriter();
}

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(BarcodeGeneratorViewHandler))]
[DynamicDependency(nameof(BarcodeGeneratorViewMapper))]
[DynamicDependency(nameof(MapUpdateBarcode))]
public BarcodeGeneratorViewHandler(PropertyMapper? mapper = null) : base(mapper ?? BarcodeGeneratorViewMapper)
{
writer = new BarcodeWriter();
Expand Down
21 changes: 21 additions & 0 deletions ZXing.Net.MAUI/CameraBarcodeReaderViewHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Versioning;

using Microsoft.Extensions.DependencyInjection;
Expand All @@ -10,6 +11,10 @@

namespace ZXing.Net.Maui
{
/// <summary>
/// Handler for CameraBarcodeReaderView that manages camera preview and barcode detection.
/// This handler is trimmer-safe with appropriate DynamicDependency attributes.
/// </summary>
public partial class CameraBarcodeReaderViewHandler : ViewHandler<ICameraBarcodeReaderView, NativePlatformCameraPreviewView>
{
public static PropertyMapper<ICameraBarcodeReaderView, CameraBarcodeReaderViewHandler> CameraBarcodeReaderViewMapper = new()
Expand All @@ -28,10 +33,26 @@ public partial class CameraBarcodeReaderViewHandler : ViewHandler<ICameraBarcode
[nameof(ICameraBarcodeReaderView.AutoFocus)] = MapAutoFocus,
};

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CameraBarcodeReaderViewHandler))]
[DynamicDependency(nameof(CameraBarcodeReaderViewMapper))]
[DynamicDependency(nameof(CameraBarcodeReaderCommandMapper))]
[DynamicDependency(nameof(MapOptions))]
[DynamicDependency(nameof(MapIsDetecting))]
[DynamicDependency(nameof(MapVisibility))]
[DynamicDependency(nameof(MapFocus))]
[DynamicDependency(nameof(MapAutoFocus))]
public CameraBarcodeReaderViewHandler() : base(CameraBarcodeReaderViewMapper, CameraBarcodeReaderCommandMapper)
{
}

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CameraBarcodeReaderViewHandler))]
[DynamicDependency(nameof(CameraBarcodeReaderViewMapper))]
[DynamicDependency(nameof(CameraBarcodeReaderCommandMapper))]
[DynamicDependency(nameof(MapOptions))]
[DynamicDependency(nameof(MapIsDetecting))]
[DynamicDependency(nameof(MapVisibility))]
[DynamicDependency(nameof(MapFocus))]
[DynamicDependency(nameof(MapAutoFocus))]
public CameraBarcodeReaderViewHandler(PropertyMapper? propertyMapper = null, CommandMapper? commandMapper = null)
: base(propertyMapper ?? CameraBarcodeReaderViewMapper, commandMapper ?? CameraBarcodeReaderCommandMapper)
{
Expand Down
17 changes: 17 additions & 0 deletions ZXing.Net.MAUI/CameraViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Versioning;

#nullable enable

namespace ZXing.Net.Maui
{
/// <summary>
/// Handler for CameraView that manages camera preview functionality.
/// This handler is trimmer-safe with appropriate DynamicDependency attributes.
/// </summary>
public partial class CameraViewHandler : ViewHandler<ICameraView, NativePlatformCameraPreviewView>
{
public static PropertyMapper<ICameraView, CameraViewHandler> CameraViewMapper = new()
Expand All @@ -29,10 +34,22 @@ public partial class CameraViewHandler : ViewHandler<ICameraView, NativePlatform
volatile ICameraView? _virtualView;
volatile bool _isConnected;

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CameraViewHandler))]
[DynamicDependency(nameof(CameraViewMapper))]
[DynamicDependency(nameof(CameraCommandMapper))]
[DynamicDependency(nameof(MapVisibility))]
[DynamicDependency(nameof(MapFocus))]
[DynamicDependency(nameof(MapAutoFocus))]
public CameraViewHandler() : base(CameraViewMapper)
{
}

[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(CameraViewHandler))]
[DynamicDependency(nameof(CameraViewMapper))]
[DynamicDependency(nameof(CameraCommandMapper))]
[DynamicDependency(nameof(MapVisibility))]
[DynamicDependency(nameof(MapFocus))]
[DynamicDependency(nameof(MapAutoFocus))]
public CameraViewHandler(PropertyMapper? mapper = null) : base(mapper ?? CameraViewMapper)
{
}
Expand Down
5 changes: 4 additions & 1 deletion ZXing.Net.MAUI/ZXing.Net.MAUI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
<DebugType>portable</DebugType>
<IsPackable>true</IsPackable>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<!-- Enable trimming support and indicate library is trim-safe and AOT-compatible -->
<IsTrimmable>true</IsTrimmable>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<PackageReference Include="Xamarin.AndroidX.Camera.Camera2" Version="1.4.2.3" />
<PackageReference Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.4.2.3" />
Expand Down