diff --git a/Laerdal.McuMgr.Bindings.Android.Native/settings.gradle b/Laerdal.McuMgr.Bindings.Android.Native/settings.gradle
index 52402747..e7dd3f2d 100644
--- a/Laerdal.McuMgr.Bindings.Android.Native/settings.gradle
+++ b/Laerdal.McuMgr.Bindings.Android.Native/settings.gradle
@@ -12,6 +12,6 @@ dependencyResolutionManagement {
mavenCentral()
}
}
-rootProject.name = "LaerdalMcuMgrWrapperAndSampleApp"
+rootProject.name = "LaerdalMcuMgrWrapper"
include ':app'
include ':mcumgr-laerdal-wrapper'
diff --git a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.cs b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.cs
index 9ef5745d..6c216d27 100644
--- a/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.cs
+++ b/Laerdal.McuMgr.Tests/FileDownloader/FileDownloaderTestbed.cs
@@ -66,6 +66,10 @@ public void FatalErrorOccurredAdvertisement(string resource, string errorMessage
public void FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(int progressPercentage, float averageThroughput)
=> _downloaderCallbacksProxy.FileDownloadProgressPercentageAndDataThroughputChangedAdvertisement(progressPercentage, averageThroughput); //raises the actual event
+
+ public void Dispose()
+ {
+ }
}
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.cs b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.cs
index f06ad9aa..c3d227a6 100644
--- a/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.cs
+++ b/Laerdal.McuMgr.Tests/FileUploader/FileUploaderTestbed.cs
@@ -74,6 +74,14 @@ public void FileUploadProgressPercentageAndDataThroughputChangedAdvertisement(in
public bool TrySetContext(object context) => throw new NotImplementedException();
public bool TrySetBluetoothDevice(object bluetoothDevice) => throw new NotImplementedException();
public bool TryInvalidateCachedTransport() => throw new NotImplementedException();
+
+ public void Dispose()
+ {
+ }
+
+ public void CleanupResourcesOfLastUpload()
+ {
+ }
}
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr.Tests/FirmwareInstaller/FirmwareInstallerTestbed.cs b/Laerdal.McuMgr.Tests/FirmwareInstaller/FirmwareInstallerTestbed.cs
index 901029ae..bf282a08 100644
--- a/Laerdal.McuMgr.Tests/FirmwareInstaller/FirmwareInstallerTestbed.cs
+++ b/Laerdal.McuMgr.Tests/FirmwareInstaller/FirmwareInstallerTestbed.cs
@@ -74,6 +74,14 @@ public void FatalErrorOccurredAdvertisement(EFirmwareInstallationState state, EF
public void FirmwareUploadProgressPercentageAndDataThroughputChangedAdvertisement(int progressPercentage, float averageThroughput)
=> _firmwareInstallerCallbacksProxy.FirmwareUploadProgressPercentageAndDataThroughputChangedAdvertisement(progressPercentage, averageThroughput); //raises the actual event
+
+ public void CleanupResourcesOfLastInstallation()
+ {
+ }
+
+ public void Dispose()
+ {
+ }
}
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Droid/FileDownloader/FileDownloader.cs b/Laerdal.McuMgr/Droid/FileDownloader/FileDownloader.cs
index a6a075b4..a69ffc2d 100644
--- a/Laerdal.McuMgr/Droid/FileDownloader/FileDownloader.cs
+++ b/Laerdal.McuMgr/Droid/FileDownloader/FileDownloader.cs
@@ -57,7 +57,39 @@ internal AndroidFileDownloaderProxy(INativeFileDownloaderCallbacksProxy fileDown
_fileDownloaderCallbacksProxy = fileDownloaderCallbacksProxy ?? throw new ArgumentNullException(nameof(fileDownloaderCallbacksProxy));
}
+ // public new void Dispose() { ... } dont there is no need to override the base implementation
+
+ private bool _alreadyDisposed;
+ protected override void Dispose(bool disposing)
+ {
+ if (_alreadyDisposed)
+ {
+ base.Dispose(disposing); //vital
+ return;
+ }
+
+ if (disposing)
+ {
+ CleanupInfrastructure();
+ }
+
+ _alreadyDisposed = true;
+
+ base.Dispose(disposing);
+ }
+ private void CleanupInfrastructure()
+ {
+ try
+ {
+ Disconnect();
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+
#region commands
public new EFileDownloaderVerdict BeginDownload(string remoteFilePath)
@@ -66,7 +98,6 @@ internal AndroidFileDownloaderProxy(INativeFileDownloaderCallbacksProxy fileDown
}
#endregion commands
-
#region android callbacks -> csharp event emitters
diff --git a/Laerdal.McuMgr/Droid/FileUploader/FileUploader.cs b/Laerdal.McuMgr/Droid/FileUploader/FileUploader.cs
index ce6c4723..c1b75c5c 100644
--- a/Laerdal.McuMgr/Droid/FileUploader/FileUploader.cs
+++ b/Laerdal.McuMgr/Droid/FileUploader/FileUploader.cs
@@ -58,7 +58,45 @@ internal AndroidFileUploaderProxy(INativeFileUploaderCallbacksProxy fileUploader
{
_fileUploaderCallbacksProxy = fileUploaderCallbacksProxy ?? throw new ArgumentNullException(nameof(fileUploaderCallbacksProxy));
}
+
+ // public new void Dispose() { ... } dont there is no need to override the base implementation
+
+ private bool _alreadyDisposed;
+ protected override void Dispose(bool disposing)
+ {
+ if (_alreadyDisposed)
+ {
+ base.Dispose(disposing); //vital
+ return;
+ }
+ if (disposing)
+ {
+ CleanupInfrastructure();
+ }
+
+ _alreadyDisposed = true;
+
+ base.Dispose(disposing);
+ }
+
+ private void CleanupInfrastructure()
+ {
+ try
+ {
+ Disconnect();
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+
+ public void CleanupResourcesOfLastUpload()
+ {
+ //nothing to do in android
+ }
+
#region commands
public new EFileUploaderVerdict BeginUpload(string remoteFilePath, byte[] data)
diff --git a/Laerdal.McuMgr/Droid/FirmwareInstaller/FirmwareInstaller.cs b/Laerdal.McuMgr/Droid/FirmwareInstaller/FirmwareInstaller.cs
index a1979a65..64d19e07 100644
--- a/Laerdal.McuMgr/Droid/FirmwareInstaller/FirmwareInstaller.cs
+++ b/Laerdal.McuMgr/Droid/FirmwareInstaller/FirmwareInstaller.cs
@@ -58,6 +58,46 @@ internal AndroidFirmwareInstallerProxy(INativeFirmwareInstallerCallbacksProxy fi
{
_firmwareInstallerCallbacksProxy = firmwareInstallerCallbacksProxy ?? throw new ArgumentNullException(nameof(firmwareInstallerCallbacksProxy));
}
+
+ // public new void Dispose() { ... } dont there is no need to override the base implementation
+
+ private bool _alreadyDisposed;
+ protected override void Dispose(bool disposing)
+ {
+ if (_alreadyDisposed)
+ {
+ base.Dispose(disposing); //vital
+ return;
+ }
+
+ if (disposing)
+ {
+ CleanupInfrastructure();
+ }
+
+ _alreadyDisposed = true;
+
+ base.Dispose(disposing);
+ }
+
+ private void CleanupInfrastructure()
+ {
+ try
+ {
+ Disconnect();
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+
+ public void CleanupResourcesOfLastInstallation()
+ {
+ //nothing to do here for android only ios needs this
+ }
+
+ #region commands
public EFirmwareInstallationVerdict BeginInstallation(
byte[] data,
@@ -83,6 +123,10 @@ public EFirmwareInstallationVerdict BeginInstallation(
return TranslateFirmwareInstallationVerdict(nativeVerdict);
}
+
+ #endregion
+
+ #region callbacks -> events
public override void FatalErrorOccurredAdvertisement(EAndroidFirmwareInstallationState state, EAndroidFirmwareInstallerFatalErrorType fatalErrorType, string errorMessage)
{
@@ -164,6 +208,8 @@ public override void FirmwareUploadProgressPercentageAndDataThroughputChangedAdv
progressPercentage: progressPercentage
);
}
+
+ #endregion
static private EAndroidFirmwareInstallationMode TranslateFirmwareInstallationMode(EFirmwareInstallationMode mode) => mode switch
{
diff --git a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/IFileDownloader.cs b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/IFileDownloader.cs
index 979093fb..ad030e3b 100644
--- a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/IFileDownloader.cs
+++ b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/IFileDownloader.cs
@@ -1,11 +1,17 @@
// ReSharper disable UnusedMember.Global
// ReSharper disable EventNeverSubscribedTo.Global
+using System;
+
namespace Laerdal.McuMgr.FileDownloader.Contracts
{
/// Downloads a file on a specific Nordic-chip-based BLE device
/// For the file-downloading process to even commence you need to be authenticated with the AED device that's being targeted.
- public interface IFileDownloader : IFileDownloaderCommandable, IFileDownloaderQueryable, IFileDownloaderEventSubscribable
+ public interface IFileDownloader :
+ IFileDownloaderCommandable,
+ IFileDownloaderQueryable,
+ IFileDownloaderEventSubscribable,
+ IDisposable
{
}
}
diff --git a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderProxy.cs b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderProxy.cs
index 00f05f0c..6d18d82c 100644
--- a/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderProxy.cs
+++ b/Laerdal.McuMgr/Shared/FileDownloader/Contracts/Native/INativeFileDownloaderProxy.cs
@@ -1,6 +1,12 @@
-namespace Laerdal.McuMgr.FileDownloader.Contracts.Native
+using System;
+
+namespace Laerdal.McuMgr.FileDownloader.Contracts.Native
{
- internal interface INativeFileDownloaderProxy : INativeFileDownloaderQueryableProxy, INativeFileDownloaderCommandableProxy, INativeFileDownloaderCallbacksProxy
+ internal interface INativeFileDownloaderProxy :
+ INativeFileDownloaderQueryableProxy,
+ INativeFileDownloaderCommandableProxy,
+ INativeFileDownloaderCallbacksProxy,
+ IDisposable
{
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/FileDownloader/FileDownloader.cs b/Laerdal.McuMgr/Shared/FileDownloader/FileDownloader.cs
index abeb0fe7..aaf1a99d 100644
--- a/Laerdal.McuMgr/Shared/FileDownloader/FileDownloader.cs
+++ b/Laerdal.McuMgr/Shared/FileDownloader/FileDownloader.cs
@@ -28,6 +28,13 @@ internal FileDownloader(INativeFileDownloaderProxy nativeFileDownloaderProxy)
_nativeFileDownloaderProxy = nativeFileDownloaderProxy ?? throw new ArgumentNullException(nameof(nativeFileDownloaderProxy));
_nativeFileDownloaderProxy.FileDownloader = this; //vital
}
+
+ public void Dispose()
+ {
+ _nativeFileDownloaderProxy?.Dispose();
+
+ GC.SuppressFinalize(this);
+ }
public string LastFatalErrorMessage => _nativeFileDownloaderProxy?.LastFatalErrorMessage;
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/IFileUploader.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/IFileUploader.cs
index 3b8718be..f416653e 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/Contracts/IFileUploader.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/IFileUploader.cs
@@ -1,11 +1,18 @@
// ReSharper disable UnusedMember.Global
// ReSharper disable EventNeverSubscribedTo.Global
+using System;
+
namespace Laerdal.McuMgr.FileUploader.Contracts
{
/// Uploads a file on a specific Nordic-chip-based BLE device
/// For the file-uploading process to even commence you need to be authenticated with the AED device that's being targeted.
- public interface IFileUploader : IFileUploaderCommandable, IFileUploaderQueryable, IFileUploaderEventSubscribable
+ public interface IFileUploader :
+ IFileUploaderCommandable,
+ IFileUploaderQueryable,
+ IFileUploaderEventSubscribable,
+ IFileUploaderCleanupable,
+ IDisposable
{
}
}
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/IFileUploaderCleanupable.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/IFileUploaderCleanupable.cs
new file mode 100644
index 00000000..7c6b4927
--- /dev/null
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/IFileUploaderCleanupable.cs
@@ -0,0 +1,7 @@
+namespace Laerdal.McuMgr.FileUploader.Contracts
+{
+ public interface IFileUploaderCleanupable
+ {
+ void CleanupResourcesOfLastUpload();
+ }
+}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderCleanupProxy.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderCleanupProxy.cs
new file mode 100644
index 00000000..37ef88c0
--- /dev/null
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderCleanupProxy.cs
@@ -0,0 +1,7 @@
+namespace Laerdal.McuMgr.FileUploader.Contracts.Native
+{
+ internal interface INativeFileUploaderCleanupProxy
+ {
+ void CleanupResourcesOfLastUpload();
+ }
+}
diff --git a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderProxy.cs b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderProxy.cs
index 9d80cc98..fdbafb62 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderProxy.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/Contracts/Native/INativeFileUploaderProxy.cs
@@ -1,6 +1,13 @@
-namespace Laerdal.McuMgr.FileUploader.Contracts.Native
+using System;
+
+namespace Laerdal.McuMgr.FileUploader.Contracts.Native
{
- internal interface INativeFileUploaderProxy : INativeFileUploaderQueryableProxy, INativeFileUploaderCommandableProxy, INativeFileUploaderCallbacksProxy
+ internal interface INativeFileUploaderProxy :
+ INativeFileUploaderQueryableProxy,
+ INativeFileUploaderCommandableProxy,
+ INativeFileUploaderCallbacksProxy,
+ INativeFileUploaderCleanupProxy,
+ IDisposable
{
}
}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/FileUploader/FileUploader.cs b/Laerdal.McuMgr/Shared/FileUploader/FileUploader.cs
index 9cc8a83c..3ba3fb68 100644
--- a/Laerdal.McuMgr/Shared/FileUploader/FileUploader.cs
+++ b/Laerdal.McuMgr/Shared/FileUploader/FileUploader.cs
@@ -31,6 +31,13 @@ internal FileUploader(INativeFileUploaderProxy nativeFileUploaderProxy)
_nativeFileUploaderProxy.FileUploader = this; //vital
}
+ public void Dispose()
+ {
+ _nativeFileUploaderProxy?.Dispose();
+
+ GC.SuppressFinalize(this);
+ }
+
public bool TrySetContext(object context) => _nativeFileUploaderProxy?.TrySetContext(context) ?? false;
public bool TrySetBluetoothDevice(object bluetoothDevice) => _nativeFileUploaderProxy?.TrySetContext(bluetoothDevice) ?? false;
public bool TryInvalidateCachedTransport() => _nativeFileUploaderProxy?.TryInvalidateCachedTransport() ?? false;
@@ -49,6 +56,7 @@ public EFileUploaderVerdict BeginUpload(string remoteFilePath, byte[] data)
public void Cancel() => _nativeFileUploaderProxy?.Cancel();
public void Disconnect() => _nativeFileUploaderProxy?.Disconnect();
+ public void CleanupResourcesOfLastUpload() => _nativeFileUploaderProxy?.CleanupResourcesOfLastUpload();
private event EventHandler _cancelled;
private event EventHandler _logEmitted;
@@ -265,6 +273,8 @@ ex is not ArgumentException //10 wops probably missing native lib symbols!
Cancelled -= UploadAsyncOnCancelled;
StateChanged -= UploadAsyncOnStateChanged;
FatalErrorOccurred -= UploadAsyncOnFatalErrorOccurred;
+
+ CleanupResourcesOfLastUpload(); //vital
}
void UploadAsyncOnCancelled(object sender, CancelledEventArgs ea)
diff --git a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/IFirmwareInstaller.cs b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/IFirmwareInstaller.cs
index 0e4f1936..829c93e3 100644
--- a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/IFirmwareInstaller.cs
+++ b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/IFirmwareInstaller.cs
@@ -1,10 +1,16 @@
// ReSharper disable UnusedMember.Global
// ReSharper disable EventNeverSubscribedTo.Global
+using System;
+
namespace Laerdal.McuMgr.FirmwareInstaller.Contracts
{
/// Upgrades the firmware on a specific Nordic-chip-based BLE device
- public interface IFirmwareInstaller : IFirmwareInstallerQueryable, IFirmwareInstallerEventSubscribable, IFirmwareInstallerCommandable
+ public interface IFirmwareInstaller :
+ IFirmwareInstallerQueryable,
+ IFirmwareInstallerEventSubscribable,
+ IFirmwareInstallerCommandable,
+ IDisposable
{
}
}
diff --git a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Native/INativeFirmwareInstallerCleanupableProxy.cs b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Native/INativeFirmwareInstallerCleanupableProxy.cs
new file mode 100644
index 00000000..9a93e1c4
--- /dev/null
+++ b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Native/INativeFirmwareInstallerCleanupableProxy.cs
@@ -0,0 +1,7 @@
+namespace Laerdal.McuMgr.FirmwareInstaller.Contracts.Native
+{
+ internal interface INativeFirmwareInstallerCleanupableProxy
+ {
+ void CleanupResourcesOfLastInstallation();
+ }
+}
\ No newline at end of file
diff --git a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Native/INativeFirmwareInstallerProxy.cs b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Native/INativeFirmwareInstallerProxy.cs
index 80120e2a..1338115a 100644
--- a/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Native/INativeFirmwareInstallerProxy.cs
+++ b/Laerdal.McuMgr/Shared/FirmwareInstaller/Contracts/Native/INativeFirmwareInstallerProxy.cs
@@ -1,6 +1,13 @@
+using System;
+
namespace Laerdal.McuMgr.FirmwareInstaller.Contracts.Native
{
- internal interface INativeFirmwareInstallerProxy : INativeFirmwareInstallerCommandableProxy, INativeFirmwareInstallerQueryableProxy, INativeFirmwareInstallerCallbacksProxy
+ internal interface INativeFirmwareInstallerProxy :
+ INativeFirmwareInstallerCommandableProxy,
+ INativeFirmwareInstallerQueryableProxy,
+ INativeFirmwareInstallerCleanupableProxy,
+ INativeFirmwareInstallerCallbacksProxy,
+ IDisposable
{
string Nickname { get; set; }
}
diff --git a/Laerdal.McuMgr/Shared/FirmwareInstaller/FirmwareInstaller.cs b/Laerdal.McuMgr/Shared/FirmwareInstaller/FirmwareInstaller.cs
index b97d8e06..0ffc949d 100644
--- a/Laerdal.McuMgr/Shared/FirmwareInstaller/FirmwareInstaller.cs
+++ b/Laerdal.McuMgr/Shared/FirmwareInstaller/FirmwareInstaller.cs
@@ -30,6 +30,13 @@ internal FirmwareInstaller(INativeFirmwareInstallerProxy nativeFirmwareInstaller
_nativeFirmwareInstallerProxy.FirmwareInstaller = this; //vital
}
+ public void Dispose()
+ {
+ _nativeFirmwareInstallerProxy?.Dispose();
+
+ GC.SuppressFinalize(this);
+ }
+
public EFirmwareInstallationVerdict BeginInstallation(
byte[] data,
EFirmwareInstallationMode mode = EFirmwareInstallationMode.TestAndConfirm,
@@ -61,6 +68,7 @@ public EFirmwareInstallationVerdict BeginInstallation(
public void Cancel() => _nativeFirmwareInstallerProxy?.Cancel();
public void Disconnect() => _nativeFirmwareInstallerProxy?.Disconnect();
+ public void CleanupResourcesOfLastUpload() => _nativeFirmwareInstallerProxy?.CleanupResourcesOfLastInstallation();
private event EventHandler _cancelled;
private event EventHandler _logEmitted;
@@ -229,6 +237,8 @@ ex is not ArgumentException //10 wops probably missing native lib symbols!
Cancelled -= FirmwareInstallationAsyncOnCancelled;
StateChanged -= FirmwareInstallationAsyncOnStateChanged;
FatalErrorOccurred -= FirmwareInstallationAsyncOnFatalErrorOccurred;
+
+ CleanupResourcesOfLastUpload();
}
return;
@@ -324,22 +334,30 @@ void FirmwareInstallationAsyncOnFatalErrorOccurred(object sender, FatalErrorOccu
private void OnStateChanged(StateChangedEventArgs ea)
{
- _stateChanged?.Invoke(this, ea);
-
- switch (ea)
+ try
{
- case { NewState: EFirmwareInstallationState.Idle }:
- _fileUploadProgressEventsCount = 0; //its vital to reset the counter here to account for retries
- break;
+ switch (ea)
+ {
+ case { NewState: EFirmwareInstallationState.Idle }:
+ _fileUploadProgressEventsCount = 0; //its vital to reset the counter here to account for retries
+ break;
- case { NewState: EFirmwareInstallationState.Testing } when _fileUploadProgressEventsCount <= 1: //works both on ios and android
- OnIdenticalFirmwareCachedOnTargetDeviceDetected(new(ECachedFirmwareType.CachedButInactive));
- break;
+ case { NewState: EFirmwareInstallationState.Testing } when _fileUploadProgressEventsCount <= 1: //works both on ios and android
+ OnIdenticalFirmwareCachedOnTargetDeviceDetected(new(ECachedFirmwareType.CachedButInactive));
+ break;
- case { NewState: EFirmwareInstallationState.Complete } when _fileUploadProgressEventsCount <= 1: //works both on ios and android
- OnIdenticalFirmwareCachedOnTargetDeviceDetected(new(ECachedFirmwareType.CachedAndActive));
- break;
+ case { NewState: EFirmwareInstallationState.Complete } when _fileUploadProgressEventsCount <= 1: //works both on ios and android
+ OnIdenticalFirmwareCachedOnTargetDeviceDetected(new(ECachedFirmwareType.CachedAndActive));
+ break;
+ }
}
+ finally
+ {
+ _stateChanged?.Invoke(this, ea); //00 must be dead last
+ }
+
+ //00 if we raise the state-changed event before the switch statement then the calling environment will unwire the event handlers of
+ // the identical-firmware-cached-on-target-device-detected event before it gets fired and the event will be ignored altogether
}
private int _fileUploadProgressEventsCount;
diff --git a/Laerdal.McuMgr/iOS/FileDownloader/FileDownloader.cs b/Laerdal.McuMgr/iOS/FileDownloader/FileDownloader.cs
index 3407520a..427eaede 100644
--- a/Laerdal.McuMgr/iOS/FileDownloader/FileDownloader.cs
+++ b/Laerdal.McuMgr/iOS/FileDownloader/FileDownloader.cs
@@ -33,7 +33,7 @@ static private INativeFileDownloaderProxy ValidateArgumentsAndConstructProxy(CBP
//ReSharper disable once InconsistentNaming
private sealed class IOSNativeFileDownloaderProxy : IOSListenerForFileDownloader, INativeFileDownloaderProxy
{
- private readonly IOSFileDownloader _nativeFileDownloader;
+ private IOSFileDownloader _nativeFileDownloader;
private readonly INativeFileDownloaderCallbacksProxy _nativeFileDownloaderCallbacksProxy;
internal IOSNativeFileDownloaderProxy(CBPeripheral bluetoothDevice, INativeFileDownloaderCallbacksProxy nativeFileDownloaderCallbacksProxy)
@@ -45,6 +45,41 @@ internal IOSNativeFileDownloaderProxy(CBPeripheral bluetoothDevice, INativeFileD
_nativeFileDownloaderCallbacksProxy = nativeFileDownloaderCallbacksProxy; //composition-over-inheritance
}
+ // public new void Dispose() { ... } dont there is no need to override the base implementation
+
+ private bool _alreadyDisposed;
+ protected override void Dispose(bool disposing)
+ {
+ if (_alreadyDisposed)
+ {
+ base.Dispose(disposing); //vital
+ return;
+ }
+
+ if (disposing)
+ {
+ CleanupInfrastructure();
+ }
+
+ _alreadyDisposed = true;
+
+ base.Dispose(disposing);
+ }
+
+ private void CleanupInfrastructure()
+ {
+ try
+ {
+ Disconnect();
+ }
+ catch
+ {
+ // ignored
+ }
+
+ _nativeFileDownloader?.Dispose();
+ _nativeFileDownloader = null;
+ }
#region commands
diff --git a/Laerdal.McuMgr/iOS/FileUploader/FileUploader.cs b/Laerdal.McuMgr/iOS/FileUploader/FileUploader.cs
index a47cde44..1b99a5fe 100644
--- a/Laerdal.McuMgr/iOS/FileUploader/FileUploader.cs
+++ b/Laerdal.McuMgr/iOS/FileUploader/FileUploader.cs
@@ -33,7 +33,7 @@ static private INativeFileUploaderProxy ValidateArgumentsAndConstructProxy(CBPer
//ReSharper disable once InconsistentNaming
private sealed class IOSNativeFileUploaderProxy : IOSListenerForFileUploader, INativeFileUploaderProxy
{
- private readonly IOSFileUploader _nativeFileUploader;
+ private IOSFileUploader _nativeFileUploader;
private readonly INativeFileUploaderCallbacksProxy _nativeFileUploaderCallbacksProxy;
internal IOSNativeFileUploaderProxy(CBPeripheral bluetoothDevice, INativeFileUploaderCallbacksProxy nativeFileUploaderCallbacksProxy)
@@ -51,15 +51,70 @@ internal IOSNativeFileUploaderProxy(CBPeripheral bluetoothDevice, INativeFileUpl
public string LastFatalErrorMessage => _nativeFileUploader?.LastFatalErrorMessage;
public void Cancel() => _nativeFileUploader?.Cancel();
-
public void Disconnect() => _nativeFileUploader?.Disconnect();
+
+ // public new void Dispose() { ... } dont there is no need to override the base implementation
+
+ private bool _alreadyDisposed;
+ protected override void Dispose(bool disposing)
+ {
+ if (_alreadyDisposed)
+ {
+ base.Dispose(disposing); //vital
+ return;
+ }
+
+ if (disposing)
+ {
+ CleanupInfrastructure();
+ CleanupResourcesOfLastUpload(); // shouldnt be necessary but just in case
+ }
+
+ _alreadyDisposed = true;
+
+ base.Dispose(disposing);
+ }
+ private void CleanupInfrastructure()
+ {
+ try
+ {
+ Disconnect();
+ }
+ catch
+ {
+ // ignored
+ }
+
+ _nativeFileUploader?.Dispose(); //order
+ _nativeFileUploader = null;
+ }
+
+ public void CleanupResourcesOfLastUpload() //00
+ {
+ _nsDataOfFileInCurrentlyActiveUpload?.Dispose();
+ _nsDataOfFileInCurrentlyActiveUpload = null;
+
+ //00 the method needs to be public so that it can be called manually when someone uses BeginUpload() instead of UploadAsync()!
+ }
+
+ private NSData _nsDataOfFileInCurrentlyActiveUpload;
public EFileUploaderVerdict BeginUpload(string remoteFilePath, byte[] data)
{
- var nsData = NSData.FromArray(data); //todo should nsdata be tracked in a private variable and then cleaned up properly?
- var verdict = TranslateFileUploaderVerdict(_nativeFileUploader.BeginUpload(remoteFilePath, nsData));
+ var nsDataOfFileToUpload = NSData.FromArray(data);
- return verdict;
+ var verdict = TranslateFileUploaderVerdict(_nativeFileUploader.BeginUpload(
+ data: nsDataOfFileToUpload,
+ remoteFilePath: remoteFilePath
+ ));
+ if (verdict != EFileUploaderVerdict.Success)
+ {
+ nsDataOfFileToUpload.Dispose();
+ return verdict;
+ }
+
+ _nsDataOfFileInCurrentlyActiveUpload = nsDataOfFileToUpload;
+ return EFileUploaderVerdict.Success;
}
public bool TrySetContext(object context)
diff --git a/Laerdal.McuMgr/iOS/FirmwareInstaller/FirmwareInstaller.cs b/Laerdal.McuMgr/iOS/FirmwareInstaller/FirmwareInstaller.cs
index 09f29051..e062c398 100644
--- a/Laerdal.McuMgr/iOS/FirmwareInstaller/FirmwareInstaller.cs
+++ b/Laerdal.McuMgr/iOS/FirmwareInstaller/FirmwareInstaller.cs
@@ -33,7 +33,7 @@ static private INativeFirmwareInstallerProxy ValidateArgumentsAndConstructProxy(
// ReSharper disable once InconsistentNaming
private sealed class IOSNativeFirmwareInstallerProxy : IOSListenerForFirmwareInstaller, INativeFirmwareInstallerProxy
{
- private readonly IOSFirmwareInstaller _nativeFirmwareInstaller;
+ private IOSFirmwareInstaller _nativeFirmwareInstaller;
private readonly INativeFirmwareInstallerCallbacksProxy _nativeFirmwareInstallerCallbacksProxy;
public string Nickname { get; set; }
@@ -47,7 +47,51 @@ internal IOSNativeFirmwareInstallerProxy(CBPeripheral bluetoothDevice, INativeFi
_nativeFirmwareInstallerCallbacksProxy = nativeFirmwareInstallerCallbacksProxy; //composition-over-inheritance
}
+ // public new void Dispose() { ... } dont there is no need to override the base implementation
+ private bool _alreadyDisposed;
+ private NSData _nsDataForFirmwareOfCurrentlyActiveInstallation;
+ protected override void Dispose(bool disposing)
+ {
+ if (_alreadyDisposed)
+ {
+ base.Dispose(disposing); //vital
+ return;
+ }
+
+ if (disposing)
+ {
+ CleanupInfrastructure();
+ CleanupResourcesOfLastInstallation(); // shouldnt be necessary but just in case
+ }
+
+ _alreadyDisposed = true;
+
+ base.Dispose(disposing);
+ }
+
+ private void CleanupInfrastructure()
+ {
+ try
+ {
+ Disconnect();
+ }
+ catch
+ {
+ // ignored
+ }
+
+ _nativeFirmwareInstaller?.Dispose();
+ _nativeFirmwareInstaller = null;
+ }
+
+ public void CleanupResourcesOfLastInstallation() //00
+ {
+ _nsDataForFirmwareOfCurrentlyActiveInstallation?.Dispose();
+ _nsDataForFirmwareOfCurrentlyActiveInstallation = null;
+
+ //00 the method needs to be public so that it can be called manually when someone uses BeginUpload() instead of UploadAsync()!
+ }
#region commands
@@ -67,22 +111,27 @@ public EFirmwareInstallationVerdict BeginInstallation(
int? byteAlignment = null
)
{
- //todo nsdata might have to be tracked in a private variable and then cleaned up properly we suspect that it could
- //todo potentially be getting disposed ahead of time taking down with it the underlying native byte array on the ios side
- //todo
- //todo https://stackoverflow.com/questions/77461311/should-i-keep-the-c-sharp-reference-to-an-nsdata-object-around-until-i-know-for
- var nsData = NSData.FromArray(data);
-
- var verdict = _nativeFirmwareInstaller.BeginInstallation(
+ var nsDataOfFirmware = NSData.FromArray(data);
+
+ var verdict = TranslateFirmwareInstallationVerdict(_nativeFirmwareInstaller.BeginInstallation(
mode: TranslateFirmwareInstallationMode(mode),
- imageData: nsData,
+ imageData: nsDataOfFirmware,
eraseSettings: eraseSettings ?? false,
pipelineDepth: pipelineDepth ?? -1,
byteAlignment: byteAlignment ?? -1,
estimatedSwapTimeInMilliseconds: estimatedSwapTimeInMilliseconds ?? -1
- );
+ ));
+
+ if (verdict != EFirmwareInstallationVerdict.Success)
+ {
+ nsDataOfFirmware.Dispose();
+ }
+ else
+ {
+ _nsDataForFirmwareOfCurrentlyActiveInstallation = nsDataOfFirmware;
+ }
- return TranslateFirmwareInstallationVerdict(verdict);
+ return verdict;
}
#endregion commands
diff --git a/README.md b/README.md
index 24e5537a..a86b432a 100644
--- a/README.md
+++ b/README.md
@@ -90,6 +90,7 @@ to the device.**
- **At the time of this writing the generated ios-nugets are built based on the iphoneos16.2 sdk**
+- **For the time being Nordics' Android/Java libs are compiled in a way that emits Java1.8 bytecode so as to keep the libraries backwards compatible with versions of Android all the way back to 7. Our Java "glue-code" under 'Laerdal.McuMgr.Bindings.Android.Native' is compiled in the same fashion.**
## 🚀 Using the Nugets in your Projects
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index a8df4b6c..360c3923 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -12,7 +12,8 @@ trigger:
pool:
name: 'Azure Pipelines'
- vmImage: 'macOS-13'
+ vmImage: 'macOS-13' # to future maintainers if you ever want to switch back to azure be warned that you will need to first make sure that macos14 is available on azure if macos14
+ # to future maintainers is not available on azure you will run into trouble making the build work for the latest versions of ios sdks (17+) and maccatalyst sdks
variables:
- group: shared-variables # needed for the github access token which is used to create new releases in github