Laerdal / Laerdal.Dfu

Xamarin binding library around @NordicSemiconductor's DFU library.
BSD 3-Clause "New" or "Revised" License
18 stars 16 forks source link

DfuInstallation.Start throws Cannot access a disposed object on iOS #20

Open Umer-Mahmood opened 1 year ago

Umer-Mahmood commented 1 year ago

Describe the bug Device firmware update works for android but fails for iOS as soon as I call Start() method on Laerdal.Dfu.DfuInstallation instance. To Reproduce Steps to reproduce the behavior:

  1. Add Laerdal.Dfu 1.25.2 in shared project, android project and iOS project
  2. Call StartDfu which is implemented as:
  public async Task StartDfu()
        {
            var updater = new Laerdal.Dfu.DfuInstallation(_deviceId, _embeddedDfuFile);
            updater.Start();
        }

Expected behavior The device firmware process should start successfully as it does in android.

Call stack

[0:] An error occurred: 'Cannot access a disposed object.
Object name: 'Laerdal.Dfu.iOS.DFUFirmware'.'. Callstack: '  at ObjCRuntime.ThrowHelper.ThrowObjectDisposedException (System.Object o) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/16.0.0.92/src/Xamarin.iOS/ObjCRuntime/ThrowHelper.cs:52 
  at ObjCRuntime.NativeObjectExtensions.GetNonNullHandle (ObjCRuntime.INativeObject self, System.String argumentName) [0x0001b] in /Library/Frameworks/Xamarin.iOS.framework/Versions/16.0.0.92/src/Xamarin.iOS/ObjCRuntime/INativeObject.cs:35 
  at Laerdal.Dfu.iOS.DFUServiceInitiator.WithFirmware (Laerdal.Dfu.iOS.DFUFirmware file) [0x00000] in /_/Laerdal.Dfu/obj/Release/xamarin.ios10/iOS/Laerdal.Dfu.iOS/DFUServiceInitiator.g.cs:139 
  at Laerdal.Dfu.DfuInstallation.SetInitiator () [0x00094] in /_/Laerdal.Dfu/iOS/DfuInstallation.cs:38 
  at Laerdal.Dfu.DfuInstallation.Start () [0x00013] in /_/Laerdal.Dfu/iOS/DfuInstallation.cs:102 
  at Config.Views.DfuTest.StartDfu () [0x000d5] in C:\sportident\six\config_app\Config\Views\DfuTest.xaml.cs:39 
  at Config.Views.DfuTest.Button_Clicked (System.Object sender, System.EventArgs e) [0x00020] in C:\sportident\six\config_app\Config\Views\DfuTest.xaml.cs:72 
  at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1021 
  at (wrapper delegate-invoke) <Module>.invoke_void_object(object)
  at Foundation.NSAsyncSynchronizationContextDispatcher.Apply () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/16.0.0.92/src/Xamarin.iOS/Foundation/NSAction.cs:178 
--- End of stack trace from previous location where exception was thrown ---

  at (wrapper managed-to-native) UIKit.UIApplication.xamarin_UIApplicationMain(int,string[],intptr,intptr,intptr&)
  at UIKit.UIApplication.UIApplicationMain (System.Int32 argc, System.String[] argv, System.IntPtr principalClassName, System.IntPtr delegateClassName) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/16.0.0.92/src/Xamarin.iOS/UIKit/UIApplication.cs:57 
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00013] in /Library/Frameworks/Xamarin.iOS.framework/Versions/16.0.0.92/src/Xamarin.iOS/UIKit/UIApplication.cs:82 
  at Config.iOS.Application.Main (System.String[] args) [0x00001] in C:\sportident\six\config_app\Config.iOS\Main.cs:12 
  at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
  at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/corlib/System.Reflection/RuntimeMethodInfo.cs:395 '
The app has been terminated.

Smartphone (please complete the following information):

Additional context The exception does not seem to depend on what I pass as device id and dfu file path.

ISSPRO-Eng commented 1 year ago

Try using this in your appdelgate.cs NativeDeviceIdHelper.GetIdFromNativeDevice = o => { if (o is CBPeripheral bt) { return bt.Identifier.ToString(); }

            return null;
        };
Umer-Mahmood commented 1 year ago

I already do this as:

public class NativeBluetoothDeviceInfoService : INativeBluetoothDeviceInfoService
    {
        public string GetDeviceAddress(Plugin.BLE.Abstractions.Contracts.IDevice device)
        {
            var nativeDevice = device.NativeDevice as CoreBluetooth.CBPeripheral;
            return nativeDevice.Identifier.ToString();
        }
    }

And before starting dfu I call it as:

            _deviceId = _nativeDeviceService.GetDeviceAddress(BleSubscriber.Instance.CurrentBleDevice.Device);
            var updater = new Laerdal.Dfu.DfuInstallation(_deviceId, dfuFilePath);
            updater.Start();

I looks like I get the right device Id back from the native service. It seems like it is not caused by the wrong device id or file path. Is there any sample for iOS implementation or xamarin forms implementation anywhere?

baddinosaur-kyle commented 1 year ago

@Umer-Mahmood did you get anywhere with this. I think we're hitting a similar issue but we're trying to do this with MAUI (net-6.0-ios) and not having much luck on iOS.

Umer-Mahmood commented 1 year ago

@baddinosaur-kyle Unfortunatly no progress on this mainly because I didn't get a chance to work further on this. I will definitly post here if I figure something out.