diff --git a/.gitignore b/.gitignore index 8dd4607..45739b3 100644 --- a/.gitignore +++ b/.gitignore @@ -395,4 +395,5 @@ FodyWeavers.xsd *.msp # JetBrains Rider -*.sln.iml \ No newline at end of file +*.sln.iml +.idea \ No newline at end of file diff --git a/BarcodeScanning.Native.Maui.sln b/BarcodeScanning.Native.Maui.sln index fef810c..8729af2 100644 --- a/BarcodeScanning.Native.Maui.sln +++ b/BarcodeScanning.Native.Maui.sln @@ -7,6 +7,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BarcodeScanning.Native.Maui EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BarcodeScanning.Test", "BarcodeScanning.Test\BarcodeScanning.Test.csproj", "{E858DBA6-F917-4145-A741-92E53E79EFD2}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5882D658-28FD-4470-BF7A-D148EBCD26B7}" + ProjectSection(SolutionItems) = preProject + .gitattributes = .gitattributes + .gitignore = .gitignore + LICENCE = LICENCE + README.md = README.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj b/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj index 4849726..1b863dd 100644 --- a/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj +++ b/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj @@ -12,6 +12,7 @@ Barcode scanning library for .NET MAUI https://github.com/afriscic/BarcodeScanning.Native.Maui .NET MAUI android ios barcode-scanner + BarcodeScanning 24.0 15.1 @@ -25,6 +26,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/BarcodeScanning.Native.Maui/CameraView.cs b/BarcodeScanning.Native.Maui/CameraView.cs index da96ac0..ea6410a 100644 --- a/BarcodeScanning.Native.Maui/CameraView.cs +++ b/BarcodeScanning.Native.Maui/CameraView.cs @@ -1,222 +1,61 @@ using System.Windows.Input; +using DependencyPropertyGenerator; using Timer = System.Timers.Timer; namespace BarcodeScanning; +[DependencyProperty("OnDetectionFinishedCommand", + Description = "Command that will be executed when barcode is detected.")] +[DependencyProperty("VibrationOnDetected", DefaultValue = true, + Description = "Disables or enables vibration on barcode detection. " + + "On Android make sure that the android.permission.VIBRATE permission " + + "is declared in the AndroidManifest.xml file.")] +[DependencyProperty("CameraEnabled", + Description = "Disables or enables camera.")] +[DependencyProperty("PauseScanning", + Description = "Pauses barcode scanning.")] +[DependencyProperty("ForceInverted", + Description = "Forces scanning of inverted barcodes. Reduces performance significantly. Android only.")] +[DependencyProperty("PoolingInterval", + Description = "Enables pooling of detections for better detection of multiple barcodes at once. " + + "Value in milliseconds. " + + "Default 0 (disabled).")] +[DependencyProperty("TorchOn", + Description = "Disables or enables torch.")] +[DependencyProperty("TapToFocusEnabled", + Description = "Disables or enables tap-to-focus.")] +[DependencyProperty("CameraFacing", + Description = "Select Back or Front camera." + + "Default value is Back Camera.")] +[DependencyProperty("CaptureQuality", DefaultValue = CaptureQuality.Medium, + Description = "Set the capture quality for the image analysis." + + "Recommended and default value is Medium." + + "Use highest values for more precision or lower for fast scanning.")] +[DependencyProperty("BarcodeSymbologies", + DefaultValue = BarcodeFormats.All, + Description = "Set the enabled symbologies." + + "Default value All.")] +[DependencyProperty("AimMode", + Description = "Disables or enables aim mode. " + + "When enabled only barcode that is in the center of the preview will be detected.")] +[DependencyProperty("ViewfinderMode", + Description = "Disables or enables viewfinder mode. " + + "When enabled only barcode that is visible in the preview will be detected.")] +[WeakEvent("OnDetectionFinished", + Description = "Event that will be triggered when barcode is detected.")] public partial class CameraView : View { - public static readonly BindableProperty OnDetectionFinishedCommandProperty = BindableProperty.Create(nameof(OnDetectionFinishedCommand) - , typeof(ICommand) - , typeof(CameraView) - , null - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).OnDetectionFinishedCommand = (ICommand)newValue); - public ICommand OnDetectionFinishedCommand + private readonly HashSet _pooledResults = new(); + private readonly Timer _poolingTimer = new() { - get => (ICommand)GetValue(OnDetectionFinishedCommandProperty); - set => SetValue(OnDetectionFinishedCommandProperty, value); - } - - public static readonly BindableProperty VibrationOnDetectedProperty = BindableProperty.Create(nameof(VibrationOnDetected) - , typeof(bool) - , typeof(CameraView) - , true - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).VibrationOnDetected = (bool)newValue); - /// - /// Disables or enables vibration on barcode detection. - /// - public bool VibrationOnDetected - { - get => (bool)GetValue(VibrationOnDetectedProperty); - set => SetValue(VibrationOnDetectedProperty, value); - } - - public static readonly BindableProperty CameraEnabledProperty = BindableProperty.Create(nameof(CameraEnabled) - , typeof(bool) - , typeof(CameraView) - , false - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).CameraEnabled = (bool)newValue); - /// - /// Disables or enables camera. - /// - public bool CameraEnabled - { - get => (bool)GetValue(CameraEnabledProperty); - set => SetValue(CameraEnabledProperty, value); - } - - public static readonly BindableProperty PauseScanningProperty = BindableProperty.Create(nameof(PauseScanning) - , typeof(bool) - , typeof(CameraView) - , false - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).PauseScanning = (bool)newValue); - /// - /// Pauses barcode scanning. - /// - public bool PauseScanning - { - get => (bool)GetValue(PauseScanningProperty); - set => SetValue(PauseScanningProperty, value); - } - - public static readonly BindableProperty ForceInvertedProperty = BindableProperty.Create(nameof(ForceInverted) - , typeof(bool) - , typeof(CameraView) - , false - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).ForceInverted = (bool)newValue); - /// - /// Forces scanning of inverted barcodes. Reduces performance significantly. Android only. - /// - public bool ForceInverted - { - get => (bool)GetValue(ForceInvertedProperty); - set => SetValue(ForceInvertedProperty, value); - } - - public static readonly BindableProperty PoolingIntervalProperty = BindableProperty.Create(nameof(PoolingInterval) - , typeof(int) - , typeof(CameraView) - , 0 - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).PoolingInterval = (int)newValue); - /// - /// Enables pooling of detections for better detection of multiple barcodes at once. - /// Value in milliseconds. Default 0 (disabled). - /// - public int PoolingInterval - { - get => (int)GetValue(PoolingIntervalProperty); - set => SetValue(PoolingIntervalProperty, value); - } - - public static readonly BindableProperty TorchOnProperty = BindableProperty.Create(nameof(TorchOn) - , typeof(bool) - , typeof(CameraView) - , false - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).TorchOn = (bool)newValue); - /// - /// Disables or enables torch. - /// - public bool TorchOn - { - get => (bool)GetValue(TorchOnProperty); - set => SetValue(TorchOnProperty, value); - } - - public static readonly BindableProperty TapToFocusEnabledProperty = BindableProperty.Create(nameof(TapToFocusEnabled) - , typeof(bool) - , typeof(CameraView) - , false - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).TapToFocusEnabled = (bool)newValue); - /// - /// Disables or enables tap-to-focus. - /// - public bool TapToFocusEnabled - { - get => (bool)GetValue(TapToFocusEnabledProperty); - set => SetValue(TapToFocusEnabledProperty, value); - } - - public static readonly BindableProperty CameraFacingProperty = BindableProperty.Create(nameof(CameraFacing) - , typeof(CameraFacing) - , typeof(CameraView) - , CameraFacing.Back - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).CameraFacing = (CameraFacing)newValue); - /// - /// Select Back or Front camera. - /// Default value is Back Camera. - /// - public CameraFacing CameraFacing - { - get => (CameraFacing)GetValue(CameraFacingProperty); - set => SetValue(CameraFacingProperty, value); - } - - public static readonly BindableProperty CaptureQualityProperty = BindableProperty.Create(nameof(CaptureQuality) - , typeof(CaptureQuality) - , typeof(CameraView) - , CaptureQuality.Medium - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).CaptureQuality = (CaptureQuality)newValue); - /// - /// Set the capture quality for the image analysys. - /// Reccomended and default value is Medium. - /// Use highest values for more precision or lower for fast scanning. - /// - public CaptureQuality CaptureQuality - { - get => (CaptureQuality)GetValue(CaptureQualityProperty); - set => SetValue(CaptureQualityProperty, value); - } - - public static readonly BindableProperty BarcodeSymbologiesProperty = BindableProperty.Create(nameof(BarcodeSymbologies) - , typeof(BarcodeFormats) - , typeof(CameraView) - , BarcodeFormats.All - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).BarcodeSymbologies = (BarcodeFormats)newValue); - /// - /// Set the enabled symbologies. - /// Default value All. - /// - public BarcodeFormats BarcodeSymbologies - { - get => (BarcodeFormats)GetValue(BarcodeSymbologiesProperty); - set => SetValue(BarcodeSymbologiesProperty, value); - } - - public static readonly BindableProperty AimModeProperty = BindableProperty.Create(nameof(AimMode) - , typeof(bool) - , typeof(CameraView) - , false - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).AimMode = (bool)newValue); - /// - /// Disables or enables aim mode. When enabled only barcode that is in the center of the preview will be detected. - /// - public bool AimMode - { - get => (bool)GetValue(AimModeProperty); - set => SetValue(AimModeProperty, value); - } - - public static readonly BindableProperty ViewfinderModeProperty = BindableProperty.Create(nameof(ViewfinderMode) - , typeof(bool) - , typeof(CameraView) - , false - , defaultBindingMode: BindingMode.TwoWay - , propertyChanged: (bindable, value, newValue) => ((CameraView)bindable).ViewfinderMode = (bool)newValue); - /// - /// Disables or enables viewfinder mode. When enabled only barcode that is visible in the preview will be detected. - /// - public bool ViewfinderMode - { - get => (bool)GetValue(ViewfinderModeProperty); - set => SetValue(ViewfinderModeProperty, value); - } - - public event EventHandler OnDetectionFinished; - - private readonly HashSet _pooledResults; - private readonly Timer _poolingTimer; + AutoReset = false, + }; public CameraView() { this.Loaded += CameraView_Loaded; this.Unloaded += CameraView_Unloaded; - _pooledResults = new(); - _poolingTimer = new() - { - AutoReset = false - }; _poolingTimer.Elapsed += PoolingTimer_Elapsed; } @@ -281,7 +120,11 @@ private void TriggerOnDetectionFinished(HashSet barCodeResults) var results = barCodeResults.ToHashSet(); MainThread.BeginInvokeOnMainThread(() => { - OnDetectionFinished?.Invoke(this, new OnDetectionFinishedEventArg { BarcodeResults = results }); + RaiseOnDetectionFinishedEvent(this, new OnDetectionFinishedEventArg + { + BarcodeResults = results, + }); + if (OnDetectionFinishedCommand?.CanExecute(results) ?? false) OnDetectionFinishedCommand?.Execute(results); }); diff --git a/BarcodeScanning.Native.Maui/CameraViewHandler.cs b/BarcodeScanning.Native.Maui/CameraViewHandler.cs index ce9db6b..9424eb2 100644 --- a/BarcodeScanning.Native.Maui/CameraViewHandler.cs +++ b/BarcodeScanning.Native.Maui/CameraViewHandler.cs @@ -2,25 +2,20 @@ namespace BarcodeScanning; -public partial class CameraViewHandler : ViewHandler +public partial class CameraViewHandler() + : ViewHandler(CameraViewMapper, CameraCommandMapper) { public static readonly PropertyMapper CameraViewMapper = new() { - [nameof(CameraView.CameraFacing)] = (handler, virtualView) => handler.UpdateCamera(), - [nameof(CameraView.CaptureQuality)] = (handler, virtualView) => handler.UpdateResolution(), - [nameof(CameraView.BarcodeSymbologies)] = (handler, virtualView) => handler.UpdateAnalyzer(), - [nameof(CameraView.TorchOn)] = (handler, virtualView) => handler.UpdateTorch(), - [nameof(CameraView.CameraEnabled)] = (handler, virtualView) => handler.HandleCameraEnabled(), - [nameof(CameraView.AimMode)] = (handler, virtualView) => handler.HandleAimModeEnabled() + [nameof(CameraView.CameraFacing)] = (handler, _) => handler.UpdateCamera(), + [nameof(CameraView.CaptureQuality)] = (handler, _) => handler.UpdateResolution(), + [nameof(CameraView.BarcodeSymbologies)] = (handler, _) => handler.UpdateAnalyzer(), + [nameof(CameraView.TorchOn)] = (handler, _) => handler.UpdateTorch(), + [nameof(CameraView.CameraEnabled)] = (handler, _) => handler.HandleCameraEnabled(), + [nameof(CameraView.AimMode)] = (handler, _) => handler.HandleAimModeEnabled() }; - public static readonly CommandMapper CameraCommandMapper = new() - { - }; - - public CameraViewHandler() : base(CameraViewMapper, CameraCommandMapper) - { - } + public static readonly CommandMapper CameraCommandMapper = new(); protected override void DisconnectHandler(BarcodeView barcodeView) { diff --git a/BarcodeScanning.Native.Maui/Shared/Methods.cs b/BarcodeScanning.Native.Maui/Shared/Methods.cs index 3a5d81c..c12a246 100644 --- a/BarcodeScanning.Native.Maui/Shared/Methods.cs +++ b/BarcodeScanning.Native.Maui/Shared/Methods.cs @@ -7,18 +7,18 @@ public static async Task AskForRequiredPermissionAsync() try { var status = await Permissions.CheckStatusAsync(); - if (status != PermissionStatus.Granted) - { - await Permissions.RequestAsync(); - } - status = await Permissions.CheckStatusAsync(); if (status == PermissionStatus.Granted) + { return true; + } + + status = await Permissions.RequestAsync(); + + return status == PermissionStatus.Granted; } catch (Exception) { - + return false; } - return false; } } \ No newline at end of file diff --git a/README.md b/README.md index 17eba14..66bb392 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ This library was inspired by existing MAUI barcode scanning libraries: [BarcodeS Edit `AndroidManifest.xml` file (under the Platforms\Android folder) and add the following permissions inside of the `manifest` node: ```xml + + ``` #### iOS Edit `info.plist` file (under the Platforms\iOS folder) and add the following permissions inside of the `dict` node: