I'm developing an application for Android that connects to my nRF52832-based product. I'm using the Nordic Android-BLE-Library. I don't believe this issue has as much to do with the Nordic chip specifically as Android BLE in general.
Has anyone else run in to Gatt client leaks when developing an Android application? After a certain period of using my application, I start getting messages about "Max gatt client reached: 32", and then pretty much every BLE operation (scanning, connecting) fails after that -- connection with that mysterious error 133. The phone I'm developing on is a Google Pixel 3, but I think this issue might affect other phones as well.
My usage of BLE might be somewhat nontraditional. My app is continuously scanning in the background for BLE devices and connecting to them. In some circumstances, it may repeatedly connect to a device, read a serial number, and then disconnect. Assuming I'm doing something wrong in cleaning up those connections, that would explain the "max gatt client reached" issue.
One note about my usage of the Nordic library that might affect things is I'm re-using BleManagers. I maintain a BleManager for a specific device, and if a link loss occurs I maintain that BleManager in memory. If I then pick that device up again in a scan, I'll re-use the BleManager and reconnect to it. I'm using the connect method -- specifically, connect().retry(2, 1500).useAutoConnect(false).timeout(10 * 1000L). I'm using the context.getBluetoothAdapter().getRemoteDevice(address) method to get a BluetoothDevice to pass to this method, based on a String bluetooth address I receive from my scanning. Initially I re-used this BluetoothDevice between connections, but I found that was causing issues to I get a fresh BluetoothDevice object on each connection attempt.
Referring to my usage pattern of connecting to a device, reading a serial number, and possibly disconnecting -- the way I'm doing that is in my BleManagerGattCallback initialize() method, I read device information characteristics and then call the BleManager.disconnect() method.
Another note about my usage: I've wrapped most of the BleManager methods with Kotlin coroutine wrappers, so I can write my code in a coroutine style. I don't think this should affect anything though, given my understanding of how the BleManager class executes everything serially in the UI thread anyway.
I hope these are enough details that someone with more experience can perhaps point out a flaw in my methodology our give me some debugging tips here.
Thanks very much!