Xamarin应用程序在发现BLE外围设备时崩溃

时间:2015-04-18 22:23:55

标签: xamarin xamarin.ios core-bluetooth

我正在Xamarin制作一个跨平台的应用程序,目前我一直试图让一个简单的BLE扫描启动并运行。该应用程序崩溃了,我已经将这个问题象征并将其问题追溯到文件" mini-exceptions.c",第2360行。

基本上,它说;

find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
{  
    int i;
    gpointer ip;
    FindHandlerBlockData *pdata = data;
    MonoJitInfo *ji = frame->ji;

    if (!ji)
        return FALSE;

所以,简而言之;我错过了" MonoJitInfo",返回false,这反过来又抛出一个异常而且我已经完成了。

但是 - 我不明白。为什么这个" mono" -stuff?我正在为新的Xamarin Unified开发,而AFAIK在项目中没有一个参考任何经典的MonoTouch东西?

我是一个Xamarin新手,所以我尽力把这个拼图放在一起......

至于我的应用程序,当我创建我的CBCentralManager以使用" DefaultGlobalQueue"时发生崩溃,但是当我使用MainQueue作为DispatchQueue时我没有遇到任何崩溃 - 但是我&# 39;我没有得到任何发现的外围设备,所以我猜测它与我的DispatchQueue相关的东西......?

我迷失了,我猜......任何提示都很有价值。 Xamarin.iOS中的CoreBluetooth是否需要Mono?

EDIT;

我在我的本机崩溃之前实际上遇到了一个严重的错误,我也看到了一些奇怪的单触式参考......;

critical: Stacktrace:
critical:   at <unknown> <0xffffffff>
critical:   at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <0xffffffff>
critical:   at UIKit.UIApplication.Main (string[],intptr,intptr) [0x00005] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:62
critical:   at UIKit.UIApplication.Main (string[],string,string) [0x0001c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:45
critical:   at iOSMyApp.Application.Main (string[]) [0x00008] in /Users/markus/Xamarin/MyApp/iOS/iOSMyApp/Main.cs:17
critical:   at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff> 

编辑 - 使用代码段

我的BLE实现是iOS本机类,它在共享项目设置中实现一个接口,其中管理所有业务逻辑。

我已尝试过两种lambda变体;

private CBCentralManager Central;

readonly AutoResetEvent stateChanged = new AutoResetEvent (false);
async Task WaitForState (CBCentralManagerState state)
{
    Console.WriteLine ("Waiting for state: " + state);

    while (Central.State != state) {
        await Task.Run (() => stateChanged.WaitOne ());
    }
}

internal NativeBleCentralTransport ()
{
    Central = new CBCentralManager (DispatchQueue.MainQueue);

    Central.DiscoveredPeripheral += (object sender, CBDiscoveredPeripheralEventArgs e) => {
        Console.WriteLine ("DiscoveredPeripheral: " + e.Peripheral.Name);
    };

    Central.UpdatedState += (object sender, EventArgs e) => {
        Console.WriteLine ("UpdatedState: " + Central.State);
        stateChanged.Set();
    };

    Central.ConnectedPeripheral += (object sender, CBPeripheralEventArgs e) => {
        Console.WriteLine ("ConnectedPeripheral: " + e.Peripheral.Name);
    };

    Central.DisconnectedPeripheral += (object sender, CBPeripheralErrorEventArgs e) => {
        Console.WriteLine ("DisconnectedPeripheral: " + e.Peripheral.Name);
    };

    Central.FailedToConnectPeripheral += (object sender, CBPeripheralErrorEventArgs e) => {
    };
}

public async Task<bool> SetupTransport ()
{
    //Wait for state...
    WaitForState(CBCentralManagerState.PoweredOn);

    //Scan for *any* peripheral at the moment...
    CBUUID[] uuids = null;
    Central.ScanForPeripherals (uuids);

    //Wait for things to happen...
    await Task.Delay (10000);

    return true;
}

...和另一个&#34;扩展CBCentralManagerDelegate类&#34; -approach;

internal class NativeBleCentralTransport : CBCentralManagerDelegate, ISessionTransport
{
    private CBCentralManager BleManager;

    internal NativeBleCentralTransport ()
    {
        //Create BLE manager and hook-up ourselves as delegate
        BleManager = new CBCentralManager(this, DispatchQueue.MainQueue);
    }

    public async Task<bool> SetupTransport ()
    {
        //The manager will automatically kick "UpdateState" for us to indicate the status of the native BLE-interface (e.g., enabled or disabled?),
        //so let's just sit back and await completion of discovery

        Task.Delay (10000);

        return true;
    }

    #region BLE delegate overrides

    override public void UpdatedState (CBCentralManager mgr)
    {
        //State change occured! Let's see if we should start 
        if (BleManager.State == CBCentralManagerState.PoweredOn) 
        {
            CBUUID[] uuids = null;
            BleManager.ScanForPeripherals (uuids);
        } 
    }

    public override void DiscoveredPeripheral (CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI)
    {
        Console.WriteLine ("Discovered: " + peripheral.Name);
    }

    #endregion
}

问题摘要

这个想法基本上是当设置传输 SetupTransport )时,BLE接口应该启动并通过阻止调用线程来发现/连接到外围设备直到它完成并准备采取行动。

但是 - 我的应用程序在iOS本机端发现外围设备时崩溃了。不在我的代码中 - 我从来没有在控制台上看到我的调试消息,但是在表示本机崩溃日志时我发现了它......

所以,基本上;我没有做任何奇怪的事情,我非常直截了当地说,但这是一个共享项目设置,它是我的第一个Xamarin项目,这使我对术语不太熟悉..我正在使用Unity API。我目前怀疑这实际上是一个项目设置/约束/参考 - 因此我正在重建一个新的测试项目,这个项目不是一个共享项目,而是一个原生iOS的东西,只是为了看到我可以在没有崩溃的情况下进行简单的BLE发现,然后我会从那里接受它。

任何见解和建议表示赞赏! /马库斯

结果

我在Xamarin做了一个测试解决方案,只有一个项目;一个单页的iOS模板的东西,只是在&#34; DidAppear&#34;中添加了我的课程。 View-controller中的方法,一切正常......

因此,这是 NOT 代码/语法问题(除非有我不知道共享项目设置的规则?),但共享项目问题/ Xamarin设置问题。有关如何设置共享项目的任何建议。通过查看碰撞痕迹可以找到经验丰富的眼睛找到的任何缺失参考文献?

1 个答案:

答案 0 :(得分:0)

问题解决了。是的,它与共享项目设置有关,更具体地说是 我的BLE本地传输类的创建。

事实证明, CBCentralManager 必须由主线程创建,并且我使用 async 属性从函数创建了一个实例。

因此,只需将我的 NativeBleCentralTransport 实例作为应用启动时创建的私有变量,并在我的 async 函数中使用该对象引用,一切正常(也就是为什么当我创建一个本机iOS项目时,一切都运行得很好,因为我只是直接从 ViewDidAppear 函数中使用 NativeBleCentralTransport 的实例进行暴力破解。