BLE Android - 未调用onConnectionStateChange

avm*_*tte 18 java android bluetooth-lowenergy android-bluetooth

我在尝试连接外围设备时遇到问题.有时回调onConnectionStateChange(...)不会被调用BluetoothDevice#connectGatt(...).我想要实现的是用户操作触发的快速和短连接.

这种情况大约发生在10次,没有特定的事先行动.它持续约20至30秒,或直到应用程序被杀死并重新打开.我遵循的正常步骤顺序是:

  1. 扫描设备以查找外围设备.
  2. 打电话BluetoothDevice#connectGatt(...).如果连接时间超过1秒,则表示连接"卡住",因此无法连接,因此BluetoothDevice#connectGatt(...)再次调用.这是在5次尝试的限制下完成的.
  3. onConnectionStateChange(...)使用newStateCONNECTED 调用并开始服务发现.
  4. 其余的操作没有问题.
  5. 断开连接后BluetoothGatt#close()调用.

发生的问题是在第3点.有时onConnectionStateChange(...)不会被调用.我注意到大多数时候问题都是从特定的行为开始的.之后BluetoothDevice#connectGatt(...),onConnectionStateChange(...)使用newStateCONNECTED 调用,但几乎立即(~40毫秒)再次使用newStatusDISCONNECTED 调用.由于状态改变的时间很短,我可以推断设备甚至没有尝试建立连接并将状态更改为DISCONNECTED.问题在以下时间结束:

  1. 20-30秒过去了.在此期间onConnectionStateChange(...)永远不会被召唤.问题结束时,onConnectionStateChange(...)称为应用尝试连接的次数.例如,如果BluetoothDevice#connectGatt(...)被调用15次,onConnectionStateChange(...)则被调用15次,newState等于DISCONNECTED.这很奇怪,因为在任何连接尝试中都没有将状态更改为CONNECTED.
  2. 该应用程序被杀死并重新开始.

SDK18和SDK 21中发生此错误.

@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
    String deviceName = device.getName();
    if (deviceName == null) return;
    Log.d("BLUETOOTH CONNECTION", "Device found: " + device.getName());
    if (mMode == SCAN_MODE) {
        mListener.deviceFound(device, rssi, scanRecord);
    }
    else {
        mDevices.put(device.hashCode(), device);
        stopScan();
        // Samsung devices with SDK 18 or 19 requires that connectGatt is called in main thread.
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Log.d("BLUETOOTH CONNECTION", "Executing first device.connectGatt()");
                BluetoothGatt gatt = device.connectGatt(mContext, false, mGattCallback);
                retryIfNecessary(device, gatt);
                mTryingToConnect = true;
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)
private void retryIfNecessary(final BluetoothDevice device, final BluetoothGatt gatt) {
    if (isRetryLimitReached()) {
        Log.d("BLUETOOTH CONNECTION", "Try count limit reached");
        finishConnection(gatt);
        mRetryCount = 0;
        mListener.error(TIMEOUT);
        return;
    }
    mRetryCount++;
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.d("BLUETOOTH CONNECTION", "Check if it is frozen.");
            if (isWorking()) {
                Log.d("BLUETOOTH CONNECTION", "Frozen, create new connection.");
                BluetoothGatt gatt = device.connectGatt(mContext, false, mGattCallback);
                retryIfNecessary(device, gatt);
            }
        }
    }, RETRY_INTERVAL_MS);
}
Run Code Online (Sandbox Code Playgroud)
    @Override
    public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
        Log.d("BLUETOOTH CONNECTION", "On connection state changed. Device: "+ gatt.getDevice().getAddress());
        if (!mConnected && BluetoothGatt.STATE_CONNECTED == newState) {
            Log.d("BLUETOOTH CONNECTION", "Connected");
            mTryingToConnect = false;
            mTryingToDiscoverServices = true;
            mConnected = true;
            gatt.discoverServices();
        }
        else if(BluetoothGatt.STATE_DISCONNECTED == newState) {
            Log.d("BLUETOOTH CONNECTION", "Disconnected and closing gatt.");
            mConnected = false;
            gatt.close();
            if (!mConnectionFinished && mRetryCount == 0) {
                finishConnection(gatt);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我认为外围设备不相关,因为iOS应用程序可以始终连接没有这个问题.

有任何想法吗?提前致谢.

编辑!

这个答案说:

直接连接的间隔为60ms,窗口为30ms,因此连接完成得更快.此外,一次只能有一个直接连接请求待处理,并且在30秒后超时.使用state = 2,status = 133调用onConnectionStateChange()以指示此超时.

所以在这个30秒的时间间隔内有一个挂起的连接请求,并在第二个30点超时.这不太可能但是,有什么办法可以缩短这个时间吗?或者可能有一个我没有看到的连接失败的解释.谢谢.

编辑02/03/2016

可能有所帮助的新事物.当问题开始时,就是在调用等于CONNECTED 约40ms后onConnectionStateChange(...)调用newState等于DISCONNECTED时newState,状态为62 = 0x03E.看这里是状态代码表示GATT_CONN_FAIL_ESTABLISH.当我检测到这种状态时,我正在关闭gatt连接,但问题仍然存在.我也试过断开连接.想法?谢谢.

avm*_*tte 5

如果有人遇到类似问题,最终通过更改外围设备使用的BLE芯片(arduino)来解决问题.在此更改之前,我发现一个解决方法是在每次连接后关闭并打开BLE.解决方案并不完美,但提高了连接速度.