Skip to content

Commit

Permalink
2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
afriscic committed Nov 18, 2024
1 parent e7cb622 commit 3d7aa43
Show file tree
Hide file tree
Showing 23 changed files with 8,252 additions and 203 deletions.
19 changes: 10 additions & 9 deletions BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<!--TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks-->
<TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst;</TargetFrameworks>
<!--TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks-->

<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsAotCompatible>true</IsAotCompatible>
<Nullable>enable</Nullable>
<Version>1.6.0</Version>
<Version>2.0.0</Version>
<Authors>Alen Friščić</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
Expand All @@ -24,17 +25,17 @@
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-android')) != true">
<ItemGroup Condition="$(TargetFramework.StartsWith('net9.0-android')) != true">
<Compile Remove="**\Android\**\*.cs" />
<None Include="**\Android\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-ios')) != true AND $(TargetFramework.StartsWith('net8.0-maccatalyst')) != true">
<ItemGroup Condition="$(TargetFramework.StartsWith('net9.0-ios')) != true AND $(TargetFramework.StartsWith('net9.0-maccatalyst')) != true">
<Compile Remove="**\MaciOS\**\*.cs" />
<None Include="**\MaciOS\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-windows')) != true">
<ItemGroup Condition="$(TargetFramework.StartsWith('net9.0-windows')) != true">
<Compile Remove="**\Windows\**\*.cs" />
<None Include="**\Windows\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
Expand All @@ -46,19 +47,19 @@

<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0-android'">
<PackageReference Include="Xamarin.Google.MLKit.BarcodeScanning" Version="117.3.0.1" />
<PackageReference Include="Xamarin.AndroidX.Camera.View" Version="1.4.0.1" />
<PackageReference Include="Xamarin.AndroidX.Camera.Camera2" Version="1.4.0.1" />

<PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.9.3.1" />
<PackageReference Include="Xamarin.AndroidX.Collection.Ktx" Version="1.4.5.1" />
<PackageReference Include="Xamarin.AndroidX.Fragment.Ktx" Version="1.8.5.1" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0-windows'))">
<ItemGroup Condition="$(TargetFramework.StartsWith('net9.0-windows'))">
<PackageReference Include="ZXingCpp" Version="0.2.1-alpha" />
</ItemGroup>

Expand Down
68 changes: 28 additions & 40 deletions BarcodeScanning.Native.Maui/CameraView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -308,80 +308,68 @@ public float[] DeviceSwitchZoomFactor
public event EventHandler<OnImageCapturedEventArg>? OnImageCaptured;

private readonly HashSet<BarcodeResult> _pooledResults;
private readonly Lock _poolingLock;
private readonly Timer _poolingTimer;

public CameraView()
{
_pooledResults = [];
_poolingLock = new();
_poolingTimer = new()
{
AutoReset = false
};
_poolingTimer.Elapsed += PoolingTimer_Elapsed;
}

internal void DetectionFinished(HashSet<BarcodeResult> barCodeResults)
internal void DetectionFinished(HashSet<BarcodeResult> barCodeResults, Lock resultLock)
{
if (barCodeResults is null)
return;

if (PoolingInterval > 0)
{
if (!_poolingTimer.Enabled)
lock (_poolingLock)
{
_poolingTimer.Interval = PoolingInterval;
_poolingTimer.Start();
}
if (!_poolingTimer.Enabled)
{
_pooledResults.Clear();
_poolingTimer.Interval = PoolingInterval;
_poolingTimer.Start();
}

foreach (var result in barCodeResults)
{
if (!_pooledResults.Add(result))
foreach (var result in barCodeResults)
{
if (_pooledResults.TryGetValue(result, out var currentResult))
{
_pooledResults.Remove(currentResult);
_pooledResults.Add(result);
}
_pooledResults.Remove(result);
_pooledResults.Add(result);
}
}
}
else
{
TriggerOnDetectionFinished(barCodeResults);
if (_poolingTimer.Enabled)
_poolingTimer.Stop();

TriggerOnDetectionFinished(barCodeResults, resultLock);
}
}

private void PoolingTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
TriggerOnDetectionFinished(_pooledResults);
_pooledResults.Clear();
if (PoolingInterval > 0)
TriggerOnDetectionFinished(_pooledResults, _poolingLock);
}

private void TriggerOnDetectionFinished(HashSet<BarcodeResult> barcodeResults)
private void TriggerOnDetectionFinished(HashSet<BarcodeResult> barcodeResults, Lock resultLock)
{
if (PauseScanning)
return;

try
{
if (VibrationOnDetected && barcodeResults.Count > 0)
Vibration.Vibrate();
}
catch (Exception)
{
}

BarcodeResult[] results;
if (barcodeResults.Count == 0)
results = [];
else
results = [.. barcodeResults];
if (VibrationOnDetected && barcodeResults.Count > 0)
Vibration.Vibrate();

MainThread.BeginInvokeOnMainThread(() =>
{
OnDetectionFinished?.Invoke(this, new OnDetectionFinishedEventArg { BarcodeResults = results });
if (OnDetectionFinishedCommand?.CanExecute(results) ?? false)
OnDetectionFinishedCommand?.Execute(results);
lock (resultLock)
{
OnDetectionFinished?.Invoke(this, new OnDetectionFinishedEventArg { BarcodeResults = barcodeResults });
if (OnDetectionFinishedCommand?.CanExecute(barcodeResults) ?? false)
OnDetectionFinishedCommand?.Execute(barcodeResults);
}
});
}

Expand Down
72 changes: 46 additions & 26 deletions BarcodeScanning.Native.Maui/Platform/Android/BarcodeAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using Android.Gms.Tasks;
using Android.Graphics;
using Android.Runtime;
using AndroidX.Camera.Core;
using AndroidX.Camera.View.Transform;
using Microsoft.Maui.Graphics.Platform;
using System.Diagnostics;
using Xamarin.Google.MLKit.Vision.Barcode.Common;
using Xamarin.Google.MLKit.Vision.BarCode;
using Xamarin.Google.MLKit.Vision.Common;

Expand All @@ -16,7 +18,7 @@ namespace BarcodeScanning;

internal class BarcodeAnalyzer : Java.Lang.Object, ImageAnalysis.IAnalyzer, IOnSuccessListener, IOnCompleteListener
{
public Size DefaultTargetResolution => Methods.TargetResolution(CaptureQuality.Medium);
public Size DefaultTargetResolution => Methods.TargetResolution(null);
public int TargetCoordinateSystem => ImageAnalysis.CoordinateSystemViewReferenced;

private IBarcodeScanner? _barcodeScanner;
Expand All @@ -25,14 +27,21 @@ internal class BarcodeAnalyzer : Java.Lang.Object, ImageAnalysis.IAnalyzer, IOnS

private bool _processInverted = false;
private bool _updateCoordinateTransform = false;
private Point _previewViewCenter = new();
private RectF _previewViewRect = new();

private readonly HashSet<BarcodeResult> _barcodeResults;
private readonly CameraManager _cameraManager;
private readonly Lock _resultsLock;

internal BarcodeAnalyzer(CameraManager cameraManager)
{
_barcodeResults = [];
_cameraManager = cameraManager;
_resultsLock = new();

_previewViewRect.X = 0;
_previewViewRect.Y = 0;

UpdateSymbologies();
}
Expand All @@ -56,10 +65,16 @@ public void Analyze(IImageProxy proxy)
{
ArgumentNullException.ThrowIfNull(_proxy?.Image);
ArgumentNullException.ThrowIfNull(_cameraManager?.CameraView);
ArgumentNullException.ThrowIfNull(_barcodeScanner);

_barcodeResults.Clear();
_processInverted = _cameraManager.CameraView.ForceInverted;

if (_cameraManager.CameraView.PauseScanning)
{
CloseProxy();
return;
}

if (_cameraManager.CameraView.CaptureNextFrame)
{
_cameraManager.CameraView.CaptureNextFrame = false;
Expand All @@ -70,10 +85,15 @@ public void Analyze(IImageProxy proxy)
if (_updateCoordinateTransform)
{
_coordinateTransform = _cameraManager.GetCoordinateTransform(_proxy);

_previewViewCenter.X = _cameraManager.PreviewView.Width / 2;
_previewViewCenter.Y = _cameraManager.PreviewView.Height / 2;
_previewViewRect.Width = _cameraManager.PreviewView.Width;
_previewViewRect.Height = _cameraManager.PreviewView.Height;

_updateCoordinateTransform = false;
}

ArgumentNullException.ThrowIfNull(_barcodeScanner);

using var inputImage = InputImage.FromMediaImage(_proxy.Image, _proxy.ImageInfo.RotationDegrees);
_barcodeScanner.Process(inputImage).AddOnSuccessListener(this).AddOnCompleteListener(this);
}
Expand All @@ -88,34 +108,34 @@ public void OnSuccess(Java.Lang.Object? result)
{
try
{
Methods.ProcessBarcodeResult(result, _barcodeResults, _coordinateTransform);

if (!_processInverted)
lock (_resultsLock)
{
if (_cameraManager?.CameraView?.AimMode ?? false)
{
var previewCenter = new Point(_cameraManager.PreviewView.Width / 2, _cameraManager.PreviewView.Height / 2);
if (_processInverted == _cameraManager?.CameraView?.ForceInverted)
_barcodeResults.Clear();

foreach (var barcode in _barcodeResults)
{
if (!barcode.PreviewBoundingBox.Contains(previewCenter))
_barcodeResults.Remove(barcode);
}
}

if (_cameraManager?.CameraView?.ViewfinderMode ?? false)
if (result is not JavaList javaList)
return;

foreach (Barcode barcode in javaList)
{
var previewRect = new RectF(0, 0, _cameraManager.PreviewView.Width, _cameraManager.PreviewView.Height);
if (barcode is null)
continue;
if (string.IsNullOrEmpty(barcode.DisplayValue) && string.IsNullOrEmpty(barcode.RawValue))
continue;

var barcodeResult = barcode.AsBarcodeResult(_coordinateTransform);

foreach (var barcode in _barcodeResults)
{
if (!previewRect.Contains(barcode.PreviewBoundingBox))
_barcodeResults.Remove(barcode);
}
}
if ((_cameraManager?.CameraView?.AimMode ?? false) && !barcodeResult.PreviewBoundingBox.Contains(_previewViewCenter))
continue;
if ((_cameraManager?.CameraView?.ViewfinderMode ?? false) && !_previewViewRect.Contains(barcodeResult.PreviewBoundingBox))
continue;

_cameraManager?.CameraView?.DetectionFinished(_barcodeResults);
_barcodeResults.Add(barcodeResult);
}
}

if (!_processInverted)
_cameraManager?.CameraView?.DetectionFinished(_barcodeResults, _resultsLock);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Widget;
using AndroidX.Camera.Core;
using AndroidX.Camera.Core.ResolutionSelector;
Expand All @@ -15,7 +14,6 @@

using Color = Android.Graphics.Color;
using Paint = Android.Graphics.Paint;
using Path = Android.Graphics.Path;

namespace BarcodeScanning;

Expand Down Expand Up @@ -245,7 +243,7 @@ private async void MainDisplayInfoChanged(object? sender, DisplayInfoChangedEven
if (_previewView is not null)
{
_previewView.Controller = null;
await Task.Delay(50);
await Task.Delay(100);
_previewView.Controller = _cameraController;
}
}
Expand Down
44 changes: 44 additions & 0 deletions BarcodeScanning.Native.Maui/Platform/Android/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using AndroidX.Camera.View.Transform;
using Microsoft.Maui.Graphics.Platform;
using Xamarin.Google.MLKit.Vision.Barcode.Common;

namespace BarcodeScanning;

public static partial class Extensions
{
internal static BarcodeResult AsBarcodeResult(this Barcode barcode, CoordinateTransform? coordinateTransform = null)
{
RectF imageRect, previewRect;
if (barcode.BoundingBox is null)
{
imageRect = RectF.Zero;
previewRect = RectF.Zero;
}
else
{
using var barcodeBox = barcode.BoundingBox.AsRectF();
imageRect = barcodeBox.AsRectangleF();

if (coordinateTransform is null)
{
previewRect = RectF.Zero;
}
else
{
coordinateTransform.MapRect(barcodeBox);
previewRect = barcodeBox.AsRectangleF();
}
}

return new BarcodeResult()
{
BarcodeType = Methods.ConvertBarcodeResultTypes(barcode.ValueType),
BarcodeFormat = (BarcodeFormats)barcode.Format,
DisplayValue = barcode.DisplayValue ?? string.Empty,
RawValue = barcode.RawValue ?? string.Empty,
RawBytes = barcode.GetRawBytes() ?? [],
PreviewBoundingBox = previewRect,
ImageBoundingBox = imageRect
};
}
}
Loading

0 comments on commit 3d7aa43

Please sign in to comment.