diff --git a/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj b/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj index b1e7d0a..bcd7968 100644 --- a/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj +++ b/BarcodeScanning.Native.Maui/BarcodeScanning.Native.Maui.csproj @@ -5,7 +5,7 @@ true true enable - 1.2.1 + 1.2.2 Alen Friščić MIT README.md diff --git a/BarcodeScanning.Native.Maui/CameraView.cs b/BarcodeScanning.Native.Maui/CameraView.cs index 4797bc5..da96ac0 100644 --- a/BarcodeScanning.Native.Maui/CameraView.cs +++ b/BarcodeScanning.Native.Maui/CameraView.cs @@ -205,10 +205,11 @@ public bool ViewfinderMode public event EventHandler OnDetectionFinished; private readonly HashSet _pooledResults; - private readonly Timer _poolingTimer; + private readonly Timer _poolingTimer; public CameraView() { + this.Loaded += CameraView_Loaded; this.Unloaded += CameraView_Unloaded; _pooledResults = new(); @@ -219,6 +220,18 @@ public CameraView() _poolingTimer.Elapsed += PoolingTimer_Elapsed; } + private void CameraView_Loaded(object sender, EventArgs e) + { + if (this.Handler is not null) + DeviceDisplay.Current.MainDisplayInfoChanged += ((CameraViewHandler)this.Handler).Current_MainDisplayInfoChanged; + } + + private void CameraView_Unloaded(object sender, EventArgs e) + { + if (this.Handler is not null) + DeviceDisplay.Current.MainDisplayInfoChanged -= ((CameraViewHandler)this.Handler).Current_MainDisplayInfoChanged; + } + internal void DetectionFinished(HashSet barCodeResults) { if (barCodeResults is null) @@ -273,15 +286,4 @@ private void TriggerOnDetectionFinished(HashSet barCodeResults) OnDetectionFinishedCommand?.Execute(results); }); } - - /// - /// DisconnectHandler has to be called manually - /// https://learn.microsoft.com/en-us/dotnet/maui/user-interface/handlers/create?view=net-maui-8.0#native-view-cleanup - /// - /// - /// - private void CameraView_Unloaded(object sender, EventArgs e) - { - this.Handler?.DisconnectHandler(); - } } diff --git a/BarcodeScanning.Native.Maui/CameraViewHandler.cs b/BarcodeScanning.Native.Maui/CameraViewHandler.cs index 43902a4..ce9db6b 100644 --- a/BarcodeScanning.Native.Maui/CameraViewHandler.cs +++ b/BarcodeScanning.Native.Maui/CameraViewHandler.cs @@ -24,7 +24,6 @@ public CameraViewHandler() : base(CameraViewMapper, CameraCommandMapper) protected override void DisconnectHandler(BarcodeView barcodeView) { - this.Stop(); base.DisconnectHandler(barcodeView); this.DisposeView(); } diff --git a/BarcodeScanning.Native.Maui/NET/BarcodeView.cs b/BarcodeScanning.Native.Maui/NET/BarcodeView.cs index 1899c78..a04c0c3 100644 --- a/BarcodeScanning.Native.Maui/NET/BarcodeView.cs +++ b/BarcodeScanning.Native.Maui/NET/BarcodeView.cs @@ -2,4 +2,4 @@ public class BarcodeView { -} +} \ No newline at end of file diff --git a/BarcodeScanning.Native.Maui/NET/CameraViewHandler.cs b/BarcodeScanning.Native.Maui/NET/CameraViewHandler.cs index d584ea2..8a248b5 100644 --- a/BarcodeScanning.Native.Maui/NET/CameraViewHandler.cs +++ b/BarcodeScanning.Native.Maui/NET/CameraViewHandler.cs @@ -3,8 +3,6 @@ public partial class CameraViewHandler { protected override BarcodeView CreatePlatformView() => throw new NotImplementedException(); - private void Start() => throw new NotImplementedException(); - private void Stop() => throw new NotImplementedException(); private void UpdateCamera() => throw new NotImplementedException(); private void UpdateResolution() => throw new NotImplementedException(); private void UpdateAnalyzer() => throw new NotImplementedException(); @@ -13,4 +11,5 @@ public partial class CameraViewHandler private void HandleAimModeEnabled() => throw new NotImplementedException(); private void DisposeView() => throw new NotImplementedException(); + internal void Current_MainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e) => throw new NotImplementedException(); } diff --git a/BarcodeScanning.Native.Maui/Platforms/Android/BarcodeView.cs b/BarcodeScanning.Native.Maui/Platforms/Android/BarcodeView.cs index 64d4f8d..e37e019 100644 --- a/BarcodeScanning.Native.Maui/Platforms/Android/BarcodeView.cs +++ b/BarcodeScanning.Native.Maui/Platforms/Android/BarcodeView.cs @@ -59,4 +59,14 @@ internal void RemoveAimingDot() } } + + protected override void Dispose(bool disposing) + { + this.RemoveAllViews(); + _relativeLayout.RemoveAllViews(); + + _imageView?.Dispose(); + _relativeLayout?.Dispose(); + base.Dispose(disposing); + } } diff --git a/BarcodeScanning.Native.Maui/Platforms/Android/CameraViewHandler.cs b/BarcodeScanning.Native.Maui/Platforms/Android/CameraViewHandler.cs index e03ab0e..3479d0e 100644 --- a/BarcodeScanning.Native.Maui/Platforms/Android/CameraViewHandler.cs +++ b/BarcodeScanning.Native.Maui/Platforms/Android/CameraViewHandler.cs @@ -20,8 +20,6 @@ public partial class CameraViewHandler protected override BarcodeView CreatePlatformView() { - DeviceDisplay.Current.MainDisplayInfoChanged += Current_MainDisplayInfoChanged; - _cameraExecutor = Executors.NewSingleThreadExecutor(); _cameraController = new LifecycleCameraController(Context) { @@ -140,13 +138,13 @@ private void HandleAimModeEnabled() private void DisposeView() { - DeviceDisplay.Current.MainDisplayInfoChanged -= Current_MainDisplayInfoChanged; - _ = Task.Run(async () => { await Task.Delay(100); MainThread.BeginInvokeOnMainThread(() => { + this.Stop(); + _barcodeView?.Dispose(); _previewView?.Dispose(); _cameraController?.Dispose(); @@ -156,7 +154,7 @@ private void DisposeView() }); } - private void Current_MainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e) + internal void Current_MainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e) { _ = Task.Run(async () => { @@ -175,4 +173,4 @@ private void Current_MainDisplayInfoChanged(object sender, DisplayInfoChangedEve }); }); } -} +} \ No newline at end of file diff --git a/BarcodeScanning.Native.Maui/Platforms/iOS/BarcodeView.cs b/BarcodeScanning.Native.Maui/Platforms/iOS/BarcodeView.cs index e4f1a46..3a73513 100644 --- a/BarcodeScanning.Native.Maui/Platforms/iOS/BarcodeView.cs +++ b/BarcodeScanning.Native.Maui/Platforms/iOS/BarcodeView.cs @@ -59,4 +59,13 @@ public override void LayoutSubviews() if (_previewLayer.Connection is not null && _previewLayer.Connection.SupportsVideoOrientation) _previewLayer.Connection.VideoOrientation = videoOrientation; } + + protected override void Dispose(bool disposing) + { + _previewLayer?.RemoveFromSuperLayer(); + _shapeLayer?.RemoveFromSuperLayer(); + + _shapeLayer?.Dispose(); + base.Dispose(disposing); + } } diff --git a/BarcodeScanning.Native.Maui/Platforms/iOS/CameraViewHandler.cs b/BarcodeScanning.Native.Maui/Platforms/iOS/CameraViewHandler.cs index 4011d90..b10cc05 100644 --- a/BarcodeScanning.Native.Maui/Platforms/iOS/CameraViewHandler.cs +++ b/BarcodeScanning.Native.Maui/Platforms/iOS/CameraViewHandler.cs @@ -229,8 +229,14 @@ private void CaptureDeviceLock(Action handler) } } + internal void Current_MainDisplayInfoChanged(object sender, DisplayInfoChangedEventArgs e) + { + } + private void DisposeView() { + this.Stop(); + _barcodeView?.Dispose(); _uITapGestureRecognizer?.Dispose(); _videoPreviewLayer?.Dispose(); @@ -241,4 +247,4 @@ private void DisposeView() _barcodeAnalyzer?.Dispose(); _queue?.Dispose(); } -} +} \ No newline at end of file diff --git a/BarcodeScanning.Native.Maui/Shared/Extensions.cs b/BarcodeScanning.Native.Maui/Shared/Extensions.cs index 7efbfb8..c5c6251 100644 --- a/BarcodeScanning.Native.Maui/Shared/Extensions.cs +++ b/BarcodeScanning.Native.Maui/Shared/Extensions.cs @@ -6,7 +6,7 @@ public static MauiAppBuilder UseBarcodeScanning(this MauiAppBuilder builder) { return builder.ConfigureMauiHandlers(handlers => { - handlers.AddHandler(typeof(CameraView), typeof(CameraViewHandler)); + handlers.AddHandler(); }); } } \ No newline at end of file diff --git a/README.md b/README.md index 30fd409..17eba14 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This library was inspired by existing MAUI barcode scanning libraries: [BarcodeS 5. Transformed barcode bounding box for on-screen positioning, 6. From version 1.2.0 implemented `ViewfinderMode` - detect only barcodes present in camera preview on screen and `AimMode` - detect only the barcode that is overlapped with the red dot centred in camera preview, 7. Code-behind and MVVM compatibility, -8. Android ony - Abillity to invert source image to scan natively unsupported inverted barcodes, but at a performance cost. +8. Android only - Ability to invert source image to scan natively unsupported inverted barcodes, but at a performance cost. ## Usage 1. Install [Nuget package](https://www.nuget.org/packages/BarcodeScanning.Native.Maui), @@ -50,11 +50,28 @@ This library was inspired by existing MAUI barcode scanning libraries: [BarcodeS ```xaml xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui" ``` -5. Set the `CameraEnabled` property to `true` in XAML, code behind or ViewModel to start the camera. +5. Set the `CameraEnabled` property to `true` in XAML, code behind or ViewModel to start the camera. As a best practice set it in `OnAppearing()` method override in your ContentPage. 6. Listen to `OnDetectionFinished` event in Code-behind or bind `OnDetectionFinishedCommand` property to a Command in your ViewModel. -7. As a best practice set the `CameraEnabled` property to `false` in `OnDisappearing()` method override in your Page. +7. As a best practice set the `CameraEnabled` property to `false` in `OnDisappearing()` method override in your ContentPage. +8. From version 1.2.2 automatic disposing of `CameraView` is disabled! If a page gets regullary disposed, to prevent memory leaks add a listener to `Unloaded` event on your `ContentPage`. -An example can be found in [BarcodeScanning.Test](https://github.com/afriscic/BarcodeScanning.Native.Maui/tree/master/BarcodeScanning.Test) project. + **This mainly applies to a page registered as "details page" using `Routing.RegisterRoute()` method! Do not do this for pages registered in `AppShell.xaml` ``, Shell Tabs or Flyout, or you will get a error when navigating back to the page!** + + For example: + ```xaml + + ... + + ``` + ```csharp + private void ContentPage_Unloaded(object sender, EventArgs e) + { + BarcodeView.Handler?.DisconnectHandler(); + } + ``` ## Supported barcode symbologies #### Android @@ -66,4 +83,4 @@ An example can be found in [BarcodeScanning.Test](https://github.com/afriscic/Ba A list of bindable properties with descriptions can be found in [CameraView.cs](https://github.com/afriscic/BarcodeScanning.Native.Maui/blob/master/BarcodeScanning.Native.Maui/CameraView.cs) source file. ## TODO Windows and macOS support -Windows and macOS are currently unsupported, but support can be added in the future. Vision framework is compatible with macOS so this implementation wouldn't be difficult. For Windows, barcode detection could be supported through [Zxing.Net](https://github.com/micjahn/ZXing.Net) project. +Windows and macOS are currently unsupported, but support can be added in the future. Vision framework is compatible with macOS so this implementation wouldn't be difficult. For Windows, barcode detection could be supported through [Zxing.Net](https://github.com/micjahn/ZXing.Net) project. \ No newline at end of file