Android BLE GATT disconnection taking longer time and hence Re-connection fails or get stuck in BluetoothSocket.connect()

huangapple go评论72阅读模式
英文:

Android BLE GATT disconnection taking longer time and hence Re-connection fails or get stuck in BluetoothSocket.connect()

问题

嗨,我正在开发 Android BLE,使用 GATT 连接。

由于 Android 负责创建配对,我们不调用 createBond() 方法。

我面临的问题是,在一些 Android 12 设备上,首次配对和连接成功进行,但当我们尝试从设备上移除配对(通过反射方法 "removeBond")并重新连接时失败。

重新配对成功,但当我们尝试再次进行 BluetoothSocket.connect() 以进行第二次连接时,连接失败,并且程序卡在 connect() 方法中。

我们知道 connect() 是一个阻塞函数,没有任何回调,因此我无法进行重新连接。

尝试了多种重新连接和重新配对的方法,但都失败了。

我从这些文档中得到了一些参考,这些文档很好地解释了这个特定问题。

链接:https://medium.com/classy-code-blog/a-short-story-about-android-ble-connection-timeouts-and-gatt-internal-errors-fa89e3f6a456

但没有提供任何解决方案。

根据文档,Android 12 AOSP Stack 代码在这里:

链接:http://aospxref.com/android-12.0.0_r3/xref/packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java#3042

监管时间已更改为 5 秒。问题仍然存在。

**注意:**相同的情景在 Android 13 设备上运行正常(Pixel 7 Pro/Samsung S21 Ultra),但在一些 Android 12 设备上无法正常工作(主要是 Samsung A 系列(One UI 版本 4.1)和一些 Pixel 设备)

fun createL2CapChannel(bluetoothDevice: BluetoothDevice, psmInt: Int): BluetoothSocket 
{
    if (socket == null) {
        Log.d(TAG, "Creating L2Cap channel")
        socket = bluetoothDevice.createL2capChannel(psmInt)
    }
    return socket as BluetoothSocket
}


fun connectToBluetoothSocket() {
    if (socket!!.isConnected) {
        Log.d(TAG, "L2Cap Socket connected")
    } else {
        Log.d(TAG, "L2Cap Socket connecting")
        socket!!.connect()
    }
}

重新连接卡在 socket.connect()

第一次成功连接后的断开连接代码:

fun disconnectGattServer() {
    if (bleGatt != null) {
        Log.d(TAG, "Closing Gatt")
        bleGatt?.disconnect()
        bleGatt?.close()
        bleGatt = null
    }
}

我陷入了这个问题,需要一些支持。谢谢。

英文:

Hi am working on Android BLE, with GATT connections.

As Android is responsible for creating the bonding and we do not call createBond().

The problem what i am facing is with few Android 12 devices, where the Pairing and connection is happening successfully for the first time, but it fails when we try to remove the bonding from the device(via reflection method "removeBond") and re-connect again.

Re-pairing happen, but when we are trying to do a BluetoothSocket.connect() again for the second tiome connection, the connection fails and program is stuck in the connect() method.

As we know connect() is a blocker function and does not have any callbacks, thus i am not able to make a re-connect.

Tried multiple ways of re-connection and re-bonding but FAILED.

I have got some reference from this documents which excellently explains this particular issue.

https://medium.com/classy-code-blog/a-short-story-about-android-ble-connection-timeouts-and-gatt-internal-errors-fa89e3f6a456

but does not provide any solution.

As per the document the Android 12 AOSP Stack code here:

http://aospxref.com/android-12.0.0_r3/xref/packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java#3042

The supervision time is has been changed to 5 sec. Still the issue remains the same.

NOTE: The same scenario works on Android 13 devices(Pixel 7 Pro/Samsung S2@ ultra) but fails to work on few Android 12 devices( majorly Samsung A Series(One UI version 4.1) and few Pixel devices)

   fun createL2CapChannel(bluetoothDevice: BluetoothDevice, psmInt: Int): BluetoothSocket 
       {
        if (socket == null) {
            Log.d(TAG, "Creating L2Cap channel")
            socket = bluetoothDevice.createL2capChannel(psmInt)
        }
        return socket as BluetoothSocket
    }


   fun connectToBluetoothSocket() {
       if (socket!!.isConnected) {
           Log.d(TAG, "L2Cap Socket connected")
       } else {
           Log.d(TAG, "L2Cap Socket connecting")
           socket!!.connect()
       }
   }

The Re-Connection stuck at socket.connect()

Disconnection code after first successful connection

fun disconnectGattServer() {
    if (bleGatt != null) {
        Log.d(TAG, "Closing Gatt")
        bleGatt?.disconnect()
        bleGatt?.close()
        bleGatt = null
    }
}

I am stuck in this issue and require some support on this issue

Thanks in advance.

答案1

得分: 0

经过多天的研究和辛勤工作,我找到了一些解决我所面临问题的方法。

测试使用的设备:

  1. 三星 S23+(Android 13)
  2. 三星 A53(Android 12)
  3. 三星 S23 Ultra(Android 13)
  4. Google Pixel 7 Pro
  5. OnePlus 10 Pro

从我的测试中,我得出了一些结论。

  1. Android 的 BLE 自行处理绑定,因此在创建 l2Capp 套接字时,绑定尚未完成(绑定未达到 BONDED 状态),而我们在此之前启动了套接字,没有对绑定进行检查。

  2. 我尝试使用 Android 提供的 createBond() API,但似乎该 API 在内部调用 TRANSPORT_AUTO 作为参数,对于 GATT,我需要 TRANSPORT_LE,因为连接需要使用 LE(而不是经典蓝牙或 TRANSPORT_AUTO),因此这个解决方案仍然不准确,因为绑定没有建立。

现在,问题是:

  1. 在 Android 12 中:与 GATT 连接时,BLE 会启动绑定,但在第一次实例中,绑定有时会启动较晚(来自堆栈本身)。
    因此,我在 onConnectionStateChange() 回调中保留了对 BONDED/BOND_NONE 的检查,然后开始发现。现在,在 Android 12 的 onCharacteristicsRead() 中,我检查了 Bonding 状态 BONDED,然后进行了 l2Capp 套接字连接。另一方面,如果绑定仍在进行中,我注册了一个 ACTION_BOND_STATE_CHANGED 的广播。在接收到 BONDED 条件后,我进行了 l2Capp 连接。确保您没有两次调用 l2capp 连接。

  2. 在 Android 13 中,做了同样的事情,但我注意到绑定通常在移动到 l2Capp 连接时已经完成。因此,流程保持不变,只是在读取后立即连接套接字。

  3. 还有一个观察结果是,有时候在 Android 12/13 中,BLE 不会发现服务。因此,在 BONDED 的接收器回调中,我检查了服务是否存在,如果不存在,则重新启动 discoverService()。

这解决了我的 Android 12 和 13 的问题。

我仍然在 Google Pixel 7 Pro 上遇到一个问题。有时在执行 Gatt 连接() 后会收到 GATT_INSUFFICIENT_AUTHORISATION。

但这可以重现,每10次中有2次。

如果我找到解决方法,将会更新。

谢谢。

英文:

After days of research and hard work, I found some workaround for the problem which I was facing.

Testing Devices used:

  1. Samsung S23+ (Android 13)
  2. Samsung A53 (Android 12)
  3. Samsung S23 Ultra (Android 13)
  4. Google Pixel 7 Pro
  5. One Plus 10 Pro

From my testing I came across few points.

  1. The BLE for android handles bonding on its own, so while creating the l2Capp socket the bonding was not completed (Bonding does not goes to BONDED state) and we were starting the socket before that, their were no check for bonding.

  2. I tried using the createBond() API provided by the Android, but it seems the API internally calls TRANSPORT_AUTO as the parameter, for the GATT, I require TRANSPORT_LE as the connect needs to be with LE itself(not with Classic Bluetooth or TRANSPORT_AUTO), So this solution was still not accurate as bonding didnt established.

Now, the problem:

  1. In Android 12: The bonding is started by BLE while you connect to GATT, but for the first instance the bonding sometimes start late(from the stack itself)
    So, I kept the check for the BONDED/BOND_NONE onConnectionStateChange() callback and than start the discovery. Now, In onCharacteristicsRead() for Android 12, i checked for Bonding state BONDED and than go for l2Capp socket connection. On the Other hand, if the bond is still in progress, I registered a Broadcast for ACTION_BOND_STATE_CHANGED. and After receiving the BONDED condition I went to l2Capp Connection. Make Sure you are not calling the l2capp connection twice.

  2. In Android 13, Did the same but i saw the bonding is generally finished while moving for the l2Capp connection. So the flow remains the same. just connecting for the socket as soon as i am reading.

  3. One more observation was sometimes for both Android 12/13 i saw the BLE does not discover the service. So in the receiver callback of BONDED I checked for the services and if it is not there i start the discoverService() again.

This solved my problem for Android 12 and 13.

I am still facing one issue with Goople Pixel 7 Pro. I am sometimes getting GATT_INSUFFICIENT_AUTHORISATION aftyer doing a Gatt connect().

But this is reproducible 2 out of 10 times.

Will update if I get any solution for the same.

Thanks

huangapple
  • 本文由 发表于 2023年6月13日 02:24:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76459352.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定