为什么`ACTION_GATT_DISCONNECTED`确实花了这么多时间来更新状态?

时间:2016-10-25 02:25:44

标签: android bluetooth-lowenergy

我正在使用Bluetooth Low Energy连接我的星系S4。连接后,连接状态将在函数

中更新
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        String intentAction;
        if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
            Log.d(TAG,"Connected");                

        } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
            Log.d(TAG,"Disconnected");                
        }
    }
}

其中,状态来自

// Implements callback methods for GATT events that the app cares about.  For example,
    // connection change and services discovered.
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG, "Connected to GATT server.");
                // Attempts to discover services after successful connection.
                Log.i(TAG, "Attempting to start service discovery:" +
                        mBluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction);
            }
        }

但是,当BLE设备与手机之间的连接丢失时,ACTION_GATT_DISCONNECTED需要10秒钟才能更新。在ACTION_GATT_CONNECTED的情况下,它会快速更新约1秒。是否可以减少BLE中的断开状态?谢谢所有

2 个答案:

答案 0 :(得分:3)

存在一个'链接监督超时',这被定义为在放弃之前必须保持链接的时间量。这就是外围设备停止通信需要很长时间的原因。

// Link supervision timeout is measured in N * 10ms
int timeout = 2000; // 20s

您可以在com.android.bluetooth.gatt.GattService

中找到从第1646行开始的相关代码。

https://android.googlesource.com/platform/packages/apps/Bluetooth/+/2b42a4906be952d3761d8b47134fba5a277a7765/src/com/android/bluetooth/gatt/GattService.java

----编辑----

更大的问题似乎是棒棒糖和橱柜中的一个已知错误,其中bluedroid在发现期间缓存设备,当它不应该时,请参阅问题https://code.google.com/p/android/issues/detail?id=81130&q=BLE&sort=-stars&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened

除非您可以编译自己的aosp系统rom并闪存到设备,否则无法编辑超时。

有一个可能的 hack 可以解决这个问题,但不建议这样做,因为它正在访问一个隐藏的内部API,它可能从marshmallow开始不存在(因为bluez的bluedroid掉线)。

黑客攻击:

调用disconnect并关闭后,通过反向调用refresh方法强制刷新发现缓存。

BluetoothGatt localBluetoothGatt = gatt;
Method localMethod = localBluetoothGatt.getClass().getMethod("refresh", new Class[0]);
if (localMethod != null) {
    localMethod.invoke(localBluetoothGatt, new Object[0])).booleanValue();
}

答案 1 :(得分:1)

您使用哪种BLE设备来测试连接?有可能该设备实际上在一段时间后关闭了连接。在某些情况下,BLE设备会在一段时间后关闭连接,因为它可能必须写出您请求的某些特性。在某些情况下,它实际上取决于设备嵌入式代码来确定何时关闭连接。

在我的情况下,我的BLE设备将在5秒后关闭连接。那个5秒就像一个缓冲器,让设备向我发送任何待处理的写入,读取我要求的特性。

我们已将BLE设备配置为在广播广播结束时通知我用来通知用户连接已关闭但在后台BLE设备仍然打开5秒以便它可以写出一些特征或用户可能想要重新获得连接。