Android:捕获BLE连接失败/断开连接?

Mag*_*les 5 android bluetooth

所以我能够在正常情况下连接到BLE设备.我想要做的是处理异常情况,例如当与设备的连接失败或已建立的连接丢失时(可能是从悬崖上抛出或被公共汽车撞到)

我正在使用CyPress BLE模块对此进行测试,我正在做的其中一项测试是从模块上移除电源.但是,onConnectionStateChange永远不会被调用!我所看到的只是成功的联系.它将花费数小时尝试连接,并且永远不会放弃.我会延迟取消连接尝试,但是没有办法取消BluetoothDevice上的连接尝试(我知道)!据我所知,它会继续尝试,直到电池电量耗尽.

这就是我的onConnectionStateChange现在在Gatt回调中的样子.请注意,我正在尝试捕获并记录任何类型的回调涉及任何类型的连接状态更改...除非连接成功,否则永远不会被调用.请注意,这是代码不在活动本身.它在一个由单身人士持有的物体中.(我希望保持多个活动之间的连接)

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            mGatt = gatt;
            Logy.CallPrint(LOGY_ENABLE, CLASSNAME, "Status: "+status+ " Newstate: "+newState);
            switch(status)
            {
                case BluetoothGatt.GATT_SUCCESS:
                    mReconnectAttempts = MAX_ATTEMPTS;

                    if(newState == BluetoothGatt.STATE_CONNECTED)
                    {
                        DispatchEvent(Event.Type.BT_ON_CONNECT);
                        bIsConnected = true;
                        gatt.discoverServices();
                    } else if (newState == BluetoothGatt.STATE_DISCONNECTED)
                    {
                        DispatchEvent(Event.Type.BT_ON_DISCONNECT);
                        bIsConnected = false;
                    }
                    break;
                default:
                    if(newState == BluetoothGatt.STATE_DISCONNECTED)
                    {
                        bIsConnected = false;
                        if(mReconnectAttempts > 0)
                        { // if we have attempts left, auto attempt to reconnect
                            DispatchEvent(Event.Type.BT_RECONNECTING);
                            mReconnectAttempts--;
                            gatt.connect();
                            bIsConnected = false;
                        }
                        else
                        {
                            mReconnectAttempts = MAX_ATTEMPTS;
                            DispatchEvent(Event.Type.BT_ON_CONNECT_FAIL);
                            bIsConnected = false;
                        }
                    } else {
                        Logy.CallPrint(LOGY_ENABLE, CLASSNAME, "onConnectionStateChange: Failed?");
                    }
            }

            super.onConnectionStateChange(gatt, status, newState);
        }
Run Code Online (Sandbox Code Playgroud)

无法检测断开是我的代码中的其他问题,例如我显示进度对话框,指示应用程序正在连接到BLE设备.那个对话永远不会消失,因为事件"On Connect Fail"永远不会被抛出.

Ber*_*tel 9

我认为您正在寻找的是Bluetooth Supervision timeout符合蓝牙LE规范:

一个参数,定义在认为连接丢失之前两个接收的数据包PDU之间的最大时间

Supervision timeoout在Android上默认设置为20秒(取决于Android版本和设备).例如,Supervision TimeoutAndroid 5.1 的值.

没有API来设置此参数,因此您必须等待20秒(取决于您的Android版本和设备)才能在关闭BLE模块后 获得onConnectionStateChange状态回调BluetoothGatt.STATE_DISCONNECTED


小智 6

这个答案与埃米尔的答案一致.

我编写了一个测试应用程序,其中一个Activity在Moto G4 Play Android 6.0.1(Marshmellow:API23)和基于Laird BL600的外围设备上运行

我打算发布一些日志 - 但它们的格式不是很好 - 所以我只是描述结果.


像往常一样,Peripheral宣传和Central扫描,并获得了一个设备实例.

这个问题没有说明第一次连接的确切方式,但让我们假设它的形式为"autoconnect"为false

mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
Run Code Online (Sandbox Code Playgroud)

(这是测试App中使用的唯一连接方式)

这给出了一个实例,BluetoothGatt并且如问题所述,事件随后通过回调异步报告,但是在发生任何连接事件之前,还有一个BluetoothGatt要调用的实例disconnect().

状态的API文档disconnect()- 尤其是' , ' 之后的部分

BluetoothGatt.disconnect() 断开已建立的连接,或取消当前正在进行的连接尝试.

为了释放GATT资源,在断开连接后,测试应用程序也会随时调用

mBluetoothGatt.close();

以下是一些不同的场景

  1. device.connectGatt() - 外围广告 - 连接 - 然后是mBluetoothGatt.disconnect()和close().

    结果:这是正常成功连接,然后中央设备在代码中关闭连接.按预期收到回叫事件.当中央在代码中断开连接时,基础蓝牙服务断开连接,外围设备将发生断开连接事件.
    .

  2. device.connectGatt() - 外围广告 - 连接 - 然后关闭外围设备.

    结果:这是正常的成功连接,按预期回调事件,然后由外围设备断开连接.外设指示BleGapSvcInit中的首选连接监督超时,这在连接参数更新中由Central确认.在外围设备断开连接后,在连接监督超时后,中心发生断开连接事件.(重复8秒和4秒监督超时).
    .

  3. device.connectGatt() - 但外围设备已停止广告,允许连接尝试超时.

    结果:(这是问题的具体情况)30秒后,可能是手机上蓝牙服务的连接超时,有一个onConnectionStateChange事件表明新连接状态是已断开连接 - 具有(错误)状态133.必须仍然记得调用mBluetoothGatt.close()else发生接口泄漏,然后在下一个客户端接口上进行连接.
    .

  4. device.connectGatt() - 使用mBluetoothGatt.disconnect()和close()在200ms后取消外围设备广告但连接已取消.

    结果:(我发现这个案例最有趣,如果在实际应用程序中也是最不可能发生的事情)有时,(大约十分之一)基础蓝牙服务实际上连接到外围设备; 看到连接,然后断开连接; 即使应用程序在回叫中没有看到这些事件.有时,尽管就应用程序而言,应用程序已断开连接,基础蓝牙电话服务连接到外设 - 并且在我的测试中保持连接几分钟,直到我超时! - 关闭BT服务或外围设备.

  • #4 让我的生活非常艰难。我一次最多连接 7 台设备,当您使用这么多设备时,十分之一的设备总是会发生。我很高兴看到这里记录了所有这些类型。 (2认同)