I am developing an application using the RxAndroidBle library that performs BLE scans regularly about every 30 seconds, and some BLE operations every minute or so. After a couple of hours, usually between 5 and 24h, the scan stops working. Every time a scan is supposed to be started, I get:
09-05 09:08:37.160 8160-8160/myapp D/BluetoothAdapter: startLeScan(): null
09-05 09:08:37.165 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.165 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.165 8160-8160/myapp D/BluetoothLeScanner: Start Scan
09-05 09:08:37.165 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.165 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.170 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.170 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:37.210 8160-12850/myapp D/BluetoothLeScanner: onClientRegistered() - status=133 clientIf=0
09-05 09:08:37.210 8160-12850/myapp D/BluetoothLeScanner: Registration failed, unregister clientIf = 0
09-05 09:08:37.215 8160-8160/myapp D/BluetoothLeScanner: Scan failed, reason app registration failed for UUID = 4c321920-a2b7-449a-bc24-ea4361f7a255
09-05 09:08:44.150 8160-8160/myapp V/myapp.debug: unsubscribing scan
09-05 09:08:44.150 8160-8160/myapp V/myapp.debug: Clearing scan subscription
09-05 09:08:44.150 8160-8160/myapp D/BluetoothAdapter: stopLeScan()
09-05 09:08:44.150 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:44.155 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:44.155 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:44.155 8160-8160/myapp D/BluetoothAdapter: STATE_ON
09-05 09:08:44.155 8160-8160/myapp D/BluetoothLeScanner: could not find callback wrapper
Does anyone have any idea of what causes this problem or what can be done to fix it?
On the older implementations of Android there seems to be a race condition between the time a bluetooth adapter is enabled and how quickly you can do a scan. You can trigger this error by either trying to scan with a disabled bluetooth adapter or one that is transitioning (or has open connections and is trying to read). The underlying issue that was causing it in my app was the inability of the bluetooth sub system to get a new bluetooth socket. The answer above (running out of GATT resources) could be part of it. The overall logic in an older Android device to avoid this issue is: 1. Make sure you disable/enable the bluetooth adapter about every 5 scans. This seems to help clear out older cached data. 2. Make sure you don't try to initiate a scan while the bluetooth adapter is not enabled (this is made possible if you are disabling/enabling on a regular basis). 3. Make sure you have a delay between disconnecting from GATT interfaces and doing your next scan. 4. Don't try to read the GATT characteristics of any more than about 3 devices at a time.
Overall, its somewhat unavoidable in an older Android device to completely avoid the problem but you can mitigate it by carefully timing your scan/stop scan/connect/disconnect/ cycle.
The problem is that after couple of connections you reach a maximal number of BluetoothGatt objects.
After you disconnect every device before you start a new scan call close() on your BluetoothGatt object.
Related
Use Case: I wrote a security app, which runs alongside a bluetooth Mesh. The mesh contains custom lights and alarms. To check the status of the mesh system, my app scans one of the nearest devices (by RSSI strength) to see what data the bluetooth light/alarm contains in it's scan response packet. Because this is a security app, my app scans every 15 seconds to ensure it has the latest info at all times. Security threats are reported to the police, so it is important to be as up to date as possible. Seconds matter. After a couple of weeks or so of the app running, the app is able to scan the data, but can no longer connect to a device. The only way to "clear" an alarm is by using the app, so it is necessary to be able to write to a device when needed.
My Question: Why does this happen? How is it possible that I can scan devices, but no longer write to a device?
Affected Device Logcat: I was able to locate a device that was in this problem-state and collected the logcat while trying to write to a device. As you can see, I am able to connect, see the services, and even update the MTU. But cannot write to the device. My app automatically tries 5 attempts, and this is the last attempt. Please note that I tried toggling bluetooth on and off. Restarting the tablet did seem to fix the issue. Unfortunately, I didn't try closing and restarting the app first....
E/Bluetooth LE: Best RSSI Position set
E/Bluetooth LE: Bluetooth Device saved
D/BluetoothGatt: connect() - device: 00:A0:50:E1:88:51, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=3b720df8-2e40-47bf-aa2c-99c0c1fba362
E/Bluetooth LE: Attempting To Connect to GATT
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=00:A0:50:E1:88:51
D/BluetoothGatt: discoverServices() - device: 00:A0:50:E1:88:51
D/BluetoothGatt: onConnectionUpdated() - Device=00:A0:50:E1:88:51 interval=6 latency=0 timeout=500 status=0
D/BluetoothGatt: onSearchComplete() = Device=00:A0:50:E1:88:51 Status=0
E/Bluetooth: GATT Services count: 3
E/Bluetooth: Service Found - UUID: 00001800-0000-1000-8000-00805f9b34fb
E/Bluetooth: Service Found - UUID: 00001801-0000-1000-8000-00805f9b34fb
E/Bluetooth: Service Found - UUID: 0000cbbb-0000-1000-8000-00805f9b34fb
D/BluetoothGatt: configureMTU() - device: 00:A0:50:E1:88:51 mtu: 50
D/BluetoothGatt: onConnectionUpdated() - Device=00:A0:50:E1:88:51 interval=39 latency=0 timeout=500 status=0
D/BluetoothGatt: onConfigureMTU() - Device=00:A0:50:E1:88:51 mtu=50 status=0
D/Surface: Surface::disconnect(this=0x74241f7000,api=1)
D/View: [Warning] assignParent to null: this = android.widget.LinearLayout{f04b3f V.E...... ......ID 0,0-333,75}
D/BluetoothManager: getConnectedDevices
D/BluetoothManager: getConnectedDevices
E/Bluetooth Gatt: Closing Gatt
D/BluetoothGatt: cancelOpen() - device: 00:A0:50:E1:88:51
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=6
D/BluetoothManager: getConnectedDevices
W/package.name: type=1400 audit(0.0:38806): avc: denied { search } for name="custom" dev="dm-0" ino=3890 scontext=u:r:untrusted_app:s0:c100,c256,c512,c768 tcontext=u:object_r:custom_file:s0 tclass=dir permissive=0
D/ViewRootImpl[Toast]: hardware acceleration = true , fakeHwAccelerated = false, sRendererDisabled = false, forceHwAccelerated = false, sSystemRendererDisabled = false
D/Surface: Surface::connect(this=0x74241f7000,api=1)
D/Surface: Surface::allocateBuffers(this=0x74241f7000)
D/BluetoothAdapter: isLeEnabled(): ON
D/BluetoothLeScanner: onScannerRegistered() - status=6 scannerId=-1 mScannerId=0
D/BluetoothAdapter: isLeEnabled(): ON
D/BluetoothLeScanner: could not find callback wrapper
Further Testing: To conduct some testing, I made a small app that can toggle a light on and off. I set the app to scan every 3 seconds for over an hour. The results were similar in that I could scan for devices, but not connect and toggle the light by writing data to it. After the issue occured in the new toggle-app, I swapped over to my main security app, which had been running the whole time, and it worked fine. Apparently, the issue only affects the app that is scanning too frequently. The difference in the logcat bothers me a bit though - after the problem occurred, the logcat shows the onClientRegistered status as 133, which makes some sense. The main app did not show that though. I wonder if these are two different issues?
D/BluetoothAdapter: STATE_ON
D/BluetoothAdapter: STATE_ON
D/BluetoothLeScanner: Start Scan with callback
D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=9 mScannerId=0
D/InputTransport: Input channel constructed: fd=88
D/ViewRootImpl#dc2b515[Toast]: setView = android.widget.LinearLayout{251b02a V.E...... ......I. 0,0-0,0} TM=true MM=false
V/Toast: Text: Uogg in android.widget.Toast$TN#af0fe1b
D/ViewRootImpl#dc2b515[Toast]: dispatchAttachedToWindow
D/ViewRootImpl#dc2b515[Toast]: Relayout returned: old=[0,63][1080,2094] new=[247,1810][832,1926] result=0x7 surface={valid=true 509882912768} changed=true
D/OpenGLRenderer: eglCreateWindowSurface = 0x76b4a19080, 0x76b763d010
D/BluetoothAdapter: STATE_ON
D/BluetoothGatt: connect() - device: 00:A0:50:DF:22:58, auto: false
D/BluetoothAdapter: isSecureModeEnabled
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=0241923a-48e6-426a-81c0-acbea6690766
D/BluetoothGatt: onClientRegistered() - status=133 clientIf=0
E/Bluetooth LE: Disconnected from GATT
E/Bluetooth Gatt: Closing Gatt
D/BluetoothGatt: cancelOpen() - device: 00:A0:50:DF:22:58
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=0
Airplane Mode: For some reason, toggling bluetooth on and off did nothing, but turning on Airplane mode solved the onClientRegistered() - status 133 issue. I have no idea why this would be. Does Airplane mode clear all bluetooth cache or similar? Currently, my attempt was to toggle bluetooth off/on every 6 hours, but that doesn't seem to work. I'm not clearing the cache though.
Other than having the clients turn their devices off nightly, which I can't guarantee they do, nothing seems to resolve the issue. Any thoughts are welcome here.
Edit: I turned off my device's bluetooth and noticed that my logcat shows D/BluetoothAdapter: isLeEnabled(): ON when trying to toggle one of the Bluetooth lights. I also saw this appear in my affected device's logcat after trying to scan and connect to a device. I'm wondering if I need to toggle bluetooth and Bluetooth LE both off to refresh everything. Toggling bluetooth on and off does nothing helpful at this point. I am using a BluetoothLE scanner, so it would make some sense. A little odd toggling bluetooth doesn't affect LE. Searching google shows the below (Full Code/Credit Here):
#SystemApi
public boolean isLeEnabled() {
final int state = getLeState();
if (DBG) {
Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
}
return (state == BluetoothAdapter.STATE_ON
|| state == BluetoothAdapter.STATE_BLE_ON
|| state == BluetoothAdapter.STATE_TURNING_ON
|| state == BluetoothAdapter.STATE_TURNING_OFF);
}
I think that you can use this code:
Future<void> scanPrinters() async {
// CHECK TO PUT INIT
flutterBlue.startScan(timeout: Duration(seconds: 4));
flutterBlue.scanResults.listen((results) {
for (blueB.ScanResult r in results) {
print('Device ${r.device.name} found!');
}
});
printerManager.startScan(Duration(seconds: 3));
printerManager.scanResults.listen((results) {
print("dipositi" + results.toString());
setState(() {
printers = results;
});
});
}
In my app I have tried everything to connec my BLE device and receive calls to onCharacteristicChanged. I have had success with initial connection where my console reads like this:
BluetoothGatt: onConnectionUpdated() - Device=B4:E6:2D:B3:D0:DB interval=6 latency=0 timeout=500 status=0
BluetoothGatt: setCharacteristicNotification() - uuid: 0a990c1f-0000-441c-8f7d-f775b6ff9400 enable: true
BluetoothGatt: setCharacteristicNotification() - uuid: f7c21d1c-0000-4b9b-ab7e-e1d8e7a51724 enable: true
Although I have no calls to onCharacteristicChanged?
I am not sure this is the proper way to check but I have used nRF Connect app to test if there is any activity between the BLE device and the Android phone. Using that app, it recoded no activity after connecting to the device. Just to be sure, I tested other BLE devices and saw the expected activity.
The BLE device has 8 characteristics that I read/get notified from, and another 8 that I write to (16 total). I have read that Android may only support 15, I could be wrong on how this works.
Does any of this seem like an issue? I can post code too.
I am developing an Android App that communicates with a BLE Peripheral. I am able to enable the notifications and receive data from the BLE Peripheral. However, a few seconds later, I receive the following message on my Android Terminal in Android Studio and the Notifications stop.
I noticed that Android phone is still connected to the BLE Peripheral as Status = 0, but after the BLE Connection Interval Change = 156, the Notifications stop.
Has anyone encountered a similar problem? I am using the BluetoothLEGatt example from Android Studio.
Thanks
Hani Abidi
D/BluetoothGatt: onClientConnParamsChanged() - Device=80:EA:CA:00:A8:77 interval=156 status=0enter code here
So I ran into this issue as well and although I don't 100% know the exact cause, I can at least relay how I "fixed" the problem and my experiences.
So I'm using a Samsung Galaxy Note 4 running 6.0.1 and using RxAndroidBle to ease the pain of having to deal with BLE on Android. My application connects to a PSoC4 BLE microprocessor and immediately does a back and forth data transfer with said microprocessor. What I was seeing was similar to the OP: more often than not the back and forth transmission would just stop dead in its tracks with the following messages:
03-15 16:06:39.989 27793-28784/application D/BluetoothGatt: onClientConnParamsChanged() - Device=00:A0:50:65:24:91 interval=6 status=0
03-15 16:06:40.289 6292-6754/? D/BtGatt.GattService: onClientConnParamsChanged() - clientIf=7 address=00:A0:50:65:24:91, interval=39status=0
03-15 16:06:40.289 27793-28561/application D/BluetoothGatt: onClientConnParamsChanged() - Device=00:A0:50:65:24:91 interval=39 status=0
03-15 16:06:54.989 6292-6754/? D/BtGatt.GattService: onClientConnParamsChanged() - clientIf=7 address=00:A0:50:65:24:91, interval=6status=0
03-15 16:06:54.989 27793-27823/application D/BluetoothGatt: onClientConnParamsChanged() - Device=00:A0:50:65:24:91 interval=6 status=0
03-15 16:06:55.259 6292-6754/? D/BtGatt.GattService: onClientConnParamsChanged() - clientIf=7 address=00:A0:50:65:24:91, interval=39status=0
03-15 16:06:55.259 27793-28784/application D/BluetoothGatt: onClientConnParamsChanged() - Device=00:A0:50:65:24:91 interval=39 status=0
It appeared to me at first that for some reason the phone was still negotiating the connection interval in the middle of the data transfer and, for some reason, would just completely get screwed up as a result.
Maybe this is what is happening, maybe it isn't, but what I found was the root cause of this was that I am (apparently) connecting and interfacing with my microprocessor over BLE before the BLE device scanner is completely done shutting down.
When the user taps on the table view cell to connect to the device, I was originally calling to stop subscribing to the RxAndroidBle observable that is scanning for devices, which should end the BLE scanning and then immediately launched into showing a new Activity for communicating with the PSoC4 which in turn immediately connects and starts interfacing with the microprocessor:
scanSubscription.unsubscribe();
Intent myIntent = new Intent(MainActivity.this, ConnectedActivity.class);
myIntent.putExtra("address", testdevice.getAddress());
myIntent.putExtra("name", testdevice.getName());
MainActivity.this.startActivityForResult(myIntent, CONNECTED_ACTIVITY);
It appears, however, that simply unsubscribing from the scan subscription does not immediately end the BLE scanning so my current strategy is to wait 500 ms before starting any communications with the other device. This is obviously not ideal - ideally you'd have a method callback when scanning actually was ceased, but I haven't figured out how to do that just yet.
Hopefully this helps someone.
Connection parameter update is unrelated to notification subscription status. Are you saying your onCharacteristicChanged are not being called although you send notifications from the peripheral? You should check your code again. If you think you've done everything correct you should check android's hci snoop log or use a BLE sniffer to see what really happens.
I am using th kontakt sdk along with radius beacon.
Here is the activity code:
http://pastebin.com/TQXdKwkX
But it isn't able to detect the beacon, what I see in logs is:
D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
How can this be possibly fixed ?
Thanks
I'm trying to write an app to connect to a BLE device (using a Cypress PSoC pioneer board) my team is working on. Right now I'm hung up on getting the app to detect any devices at all.
I'm testing the app on an HTC Desire 510, and the device I'm trying to detect is the PSoC board running Cypress's proximity sensor example.
After lots of frustration, I tried running the entire API-21 BluetoothLEGatt sample on my device and it detects (and can connect to) the board no problem.
I then tried copying the entire DeviceScanActivity into my project making only the following modifications:
I turned the toast messages into logcat messages
I removed the content of onListItemClick since that references an Activity I don't have
I changed a couple of labels to String values already in my project
My AndroidManifest has both BLUETOOTH and BLUETOOTH_ADMIN and is setup to launch the activity directly.
When I run it in my project the phone doesn't detect any devices, and I get the following logcat output when scanning:
04-13 17:51:25.350 3892-3892/com.fredwilby.chipper D/BluetoothAdapter﹕ startLeScan(): null
04-13 17:51:25.350 3892-3903/com.fredwilby.chipper D/BluetoothAdapter﹕ onClientRegistered() - status=0 clientIf=5
04-13 17:51:27.350 3892-3892/com.fredwilby.chipper I/Choreographer﹕ Skipped 120 frames! The application may be doing too much work on its main thread.
04-13 17:51:31.940 3892-3892/com.fredwilby.chipper D/BluetoothAdapter﹕ stopLeScan()
compared to the output when I scan from the Sample project:
04-13 18:05:36.750 6887-6887/com.example.android.bluetoothlegatt D/BluetoothAdapter﹕ startLeScan(): null
04-13 18:05:36.750 6887-6899/com.example.android.bluetoothlegatt D/BluetoothAdapter﹕ onClientRegistered() - status=0 clientIf=5
04-13 18:05:37.120 6887-6898/com.example.android.bluetoothlegatt D/BluetoothAdapter﹕ onScanResult() - Device=00:A0:50:00:00:69 RSSI=-59
04-13 18:05:37.120 6887-6898/com.example.android.bluetoothlegatt D/BluetoothDevice﹕ getService() entry
04-13 18:05:38.080 6887-6887/com.example.android.bluetoothlegatt D/BluetoothAdapter﹕ stopLeScan()
I don't get the message about skipped frames everytime I scan from my app, but it's quite frequent and was even more so when I was trying to make code I wrote work.
I've tried rebooting the device to no avail, and I really don't know what else I can try at this point. Does anyone have any insight into how I can get this to work?
I'm happy to post any other information that would be helpful. I've omitted the code here because, as I mentioned above, it's identical to the sample except for very minor cosmetic tweaks (nothing anywhere near the scanning code).
Well, I managed to fix it by removing <uses-sdk android:minSdkVersion="18" android:targetSdkVersion="21" /> from my AndroidManifest. Of course this is kind of an infuriating fix and I'd appreciate if anyone had any insight into why this happens.