Search code examples
iosxamarin.iosxamarin.formscore-bluetooth

Xamarin iOS app crashes when I try to access restored CoreBluetooth peripherals


I have a Xamarin Cross-Platform app that uses the bluetooth-central background mode on the iOS side to keep a connection to a bluetooth-to-serial dongle alive. Everything is working well, except I am trying to implement the CBCentralManagerDelegate.WillRestoreState method (see iOS Doc, and the useless Xamarin Doc for details).

From the iOS doc, I can see that the second argument has an element that contains restored peripherals in the CBCentralManager.RestoredStatePeripheralsKey, and that the element is an NSArray of CBPeripherals. So, I've written this method in my class that overrides CBCentralManagerDelegate:

// Handle state restoration if OS restores CoreBluetooth peripherals
public override void WillRestoreState(CBCentralManager central, NSDictionary state)
{
    NSObject restoredPeripherals = new NSObject();

    if (state.TryGetValue(CBCentralManager.RestoredStatePeripheralsKey, out restoredPeripherals))
    {
        Logger.Debug("Restoring CoreBluetooth Peripherals...");
        NSArray<CBPeripheral> peripherals = restoredPeripherals as NSArray<CBPeripheral>;
        foreach (CBPeripheral peripheral in peripherals)
        {
            Logger.Debug("Loading preexisting peripherals");
            discoveredPeripherals.Add(peripheral.Name, peripheral);
        }
    }

    base.WillRestoreState(central, state);
}

The problem is with the line that says: NSArray<CBPeripheral> peripherals = restoredPeripherals as NSArray<CBPeripheral>;

This line leads to a crash. In the extremely rare case that I'm able to catch this in the debugger (it's hard to keep the debugger connected while reproducing this), it says something about this line being an invalid cast.

Here's the log I get from the iPad:

Nov 15 14:22:58 iPad-Mini Warning 520 MyApp    [Debug]   Restoring CoreBluetooth Peripherals... (
Nov 15 14:22:58 iPad-Mini Warning 520 MyApp    
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   15  MyApp                    0x00083733 -[Messenger_iOS_TruConnectBLEFactory_ManagerDelegate centralManager:willRestoreState:] + 60
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   21  libdispatch.dylib                   0x20df3b93 <redacted> + 182
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   13  libmonosgen-2.0.dylib               0x08d4ff6b mono_runtime_invoke + 138
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   4   libxamarin-debug.dylib              0x08fa2360 xamarin_printf + 0
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   24  libsystem_pthread.dylib             0x20fadb29 _pthread_wqthread + 1024
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   1   libsystem_platform.dylib            0x20faa077 _sigtramp + 42
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   2   libsystem_pthread.dylib             0x20fb0733 pthread_kill + 62
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   19  libdispatch.dylib                   0x20df6423 <redacted> + 1758
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   8   libmonosgen-2.0.dylib               0x08cde29f handle_signal_exception + 42
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   12  libmonosgen-2.0.dylib               0x08d4ffd5 do_runtime_invoke + 78
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   14  MyApp                    0x0008393b _ZL31native_to_managed_trampoline_55P11objc_objectP13objc_selectorPP11_MonoMethodP16CBCentralManagerP12NSDictionaryj + 516
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   16  CoreBluetooth                       0x2637abe3 <redacted> + 2486
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   22  libdispatch.dylib                   0x20df85e9 <redacted> + 1560
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   9   ???                                 0x00000000 0x0 + 0
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   6   libmonosgen-2.0.dylib               0x08ce6235 mono_handle_exception_internal + 3162
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   11  libmonosgen-2.0.dylib               0x08cf10f5 mono_jit_runtime_invoke + 712
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    Unhandled managed exception:
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   25  libsystem_pthread.dylib             0x20fad718 start_wqthread + 8
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   7   libmonosgen-2.0.dylib               0x08ce55d7 mono_handle_exception + 30
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   5   libmonosgen-2.0.dylib               0x08d1d7cd mono_invoke_unhandled_exception_hook + 100
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   18  libdispatch.dylib                   0x20de9823 <redacted> + 10
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   3   libsystem_c.dylib                   0x20e9b0ad abort + 108
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   17  CoreBluetooth                       0x263869f3 <redacted> + 62
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   10  libmscorlib.dll.dylib               0x00d49520 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 256
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   0   libmonosgen-2.0.dylib               0x08ce6637 mono_handle_native_crash + 196
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical: Stacktrace:
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   23  libdispatch.dylib                   0x20df7fcd <redacted> + 96
Nov 15 14:22:59 iPad-Mini Warning 520 MyApp    critical:   20  libdispatch.dylib                   0x20df5a61 <redacted> + 284

Does anyone have ideas about why this is crashing? Also, if anyone has examples of implementing this method with Xamarin, please share the link. I haven't been able find any. :(


Solution

  • I guess it should be to converted to NSArray instead of NSArray<CBPeripheral>.

    Try the following:

    NSArray peripherals = (NSArray) restoredPeripherals;
    for (nuint i = 0; i < peripherals.Count; i++)
    {
        CBPeripheral peripheral = peripherals.GetItem<CBPeripheral>(i);
    
        Logger.Debug("Loading preexisting peripherals");
        discoveredPeripherals.Add(peripheral.Name, peripheral);
    }