BLE Android - 未调用onConnectionStateChange [英] BLE Android - onConnectionStateChange not being called

查看:1884
本文介绍了BLE Android - 未调用onConnectionStateChange的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a problem trying to connect to a peripheral. Sometimes the callback onConnectionStateChange(...) is not called after BluetoothDevice#connectGatt(...). What I'm trying to achieve is fast and short connections triggered by user action.

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

This situation occurs about 1 in 10 times without specific prior action. It lasts about 20 to 30 seconds or until the application is killed and reopened. The normal sequence of steps I follow is:


  1. 扫描设备以查找外围设备。

  2. 呼叫 BluetoothDevice类#connectGatt(...)。如果连接时间超过1秒,则表示连接卡住,因此无法连接,因此 BluetoothDevice #connectGatt(...)是又叫了一遍。这样做的次数限制为5次。

  3. 使用 newState调用onConnectionStateChange(...) 已连接并开始服务发现。

  4. 其余操作无故障执行。

  5. 断开连接后<$ li c $ c>调用BluetoothGatt #close()。

  1. Scan devices to find the peripheral.
  2. Call BluetoothDevice#connectGatt(...). If it takes longer than 1 second to connect, it means that the connection is "stuck" and therefore it won't connect, so BluetoothDevice#connectGatt(...) is called again. This is done with a limit of 5 attempts.
  3. onConnectionStateChange(...) is called with newState CONNECTED and begins the services discovery.
  4. The rest of the operations are performed without problems.
  5. After disconnection BluetoothGatt#close() is called.

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

The problem that occurs is at point 3. Sometimes onConnectionStateChange(...)is not called. I have noticed that most of the times the problem starts with a specific behavior. After BluetoothDevice#connectGatt(...), onConnectionStateChange(...) is called with newState CONNECTED, but almost immediately afterwards (~40 milliseconds) is called again with newStatus DISCONNECTED. Due to the short time of the status change, I can deduce that the device does not even tried to make the connection and changed the state to DISCONNECTED. The problem ends when:


  1. 已经过了20-30秒。在此期间,永远不会调用 onConnectionStateChange(...)。问题结束时, onConnectionStateChange(...)被称为应用尝试连接的次数。例如,如果 BluetoothDevice #connectGatt(...)被调用15次, onConnectionStateChange(...)是调用15次, newState 等于DISCONNECTED。这很奇怪,因为在任何连接尝试中都没有将状态更改为CONNECTED。

  2. 应用程序被终止并重新启动。

  1. 20-30 seconds have passed. During this time onConnectionStateChange(...) is never called. When the problem ends, onConnectionStateChange(...) is called the number of times that the app tried to connect. For example, if BluetoothDevice#connectGatt(...) is called 15 times, onConnectionStateChange(...) is called 15 times with newState equal to DISCONNECTED. This is curious because never in any of those connection attempts the status changed to CONNECTED.
  2. The app is killed and started again.

SDK18和SDK中出现此错误21 。

This error occurs in SDK18 and 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;
            }
        });
    }
}





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);
}





    @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);
            }
        }
    }

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

I think that the peripheral is not relevant, because the iOS app can always connect without this problem.

任何想法?提前致谢。

编辑!

这个回答说:


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

Direct connection has interval of 60ms and window of 30ms so connections complete much faster. Additionally there can only be one direct connection request pending at a time and it times out after 30 seconds. onConnectionStateChange() gets called with state=2, status=133 to indicate this timeout.

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

So in this 30 seconds interval there is a pending connection request and times out at the second 30. It's unlikely but, is there anything I can do to make this time shorter? Or maybe there is an explanation for the connection failure that I am not seeing. Thanks.

编辑02/03/2016

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

New thing that may help. When the problem starts, that's it when onConnectionStateChange(...) is called with newState equal to DISCONNECTED after ~40ms that is called with newState equal to CONNECTED, the status is 62 = 0x03E. Looking here that status code means GATT_CONN_FAIL_ESTABLISH. When I detect this status I'm closing the gatt connection, but the problem persists. I also tried disconnecting and closing. Ideas? Thanks.

推荐答案

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

If someone is having a similar issue, the problem was finally solved by changing the BLE chip used by the peripheral (arduino). Before that change, a workaround I found was turning off and on the BLE after each connection. The solution was not perfect, but improved the connection rate a lot.

这篇关于BLE Android - 未调用onConnectionStateChange的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆