Repository navigation
missing serviceUUIDs on android 12 #254
Description
Activity
@ray007 you are welcome to create a PR for the doc
as for the rest without more details i cant really help you we are using native apis to getserviceUUIDsfrom advertisment data https://developer.android.com/reference/android/bluetooth/le/ScanRecord#getServiceUuids().
as we are to set the filter https://developer.android.com/reference/android/bluetooth/le/ScanFilter.Builder#setServiceUuid(android.os.ParcelUuidYou can add console logs to the android file of the ble plugin to see where it is failing
Anyone any idea what needs to be done to read serviceUUIDs again or filter by some on android 12+ ?
@ray007 maybe debug it , add logs to see what s happening and where it fails ;)
Hmm, I followed things down to
ScanCallBackImpl.prototype.onScanResult(around line 475 in bluetooth.android.js).The property
mServiceUuidsof the ScanRecord isnull.Ignoring this and trying to read the characteristic anyway also does not work:
[BluetoothError]:error_function_call, readCharacteristic, [B@e4a57a1, {"peripheralUUID":"EB:38:0B:BE:FD:D7","serviceUUID":"78a90000-26ce-4367-bfeb-7e3c1d217561","characteristicUUID":"78a90001-26ce-4367-bfeb-7e3c1d217561","timeout":1000}Yes, but when dumping a
ScanRecordwithconsole.log, you can see themServiceUuidsproperty.The funny things also is, I can see a serviceUUID there from one garmin device.
Talking to our sensor developer, it seems there's the advertisement and then a second 'scan response' message?
And since the serviceUuids of our sensors are in the second message they seem to be missing after setting the target api level to 31...@ray007 something bugs me in what you are saying.
ScanRecordis a native object (android.bluetooth.le.ScanRecord) so themServiceUuidsshould not be printed. even if it shows you amServiceUuidsyou should (to debug) try to console log using native methods https://developer.android.com/reference/android/bluetooth/le/ScanRecord#getServiceUuids()Now about your double message thing i didnt know it was possible. Now the thing is the ble plugin does not send duplicate events for discovery. which might be your issue
Line 475 in 384afba
if (!stateObject) {
You can try to remove the if test. If it works you are welcome to create a PR for a scanning parameter to allow duplicate events (default to false to be retro compatible).Looking at https://docs.particle.io/reference/device-os/api/bluetooth-le-ble/blepeerdevice/#blescanresult, there seems to be a
scanResponseseparate from theadvertisingData, which needs an extra request but no connect.And starting with api level 31 on android, this extra data apparently does not get retrieved anymore.
It's much harder to read in the Bluetooth Core Specification 5.2, but
Volume 3, Part C, Chapter 11 Advertising and Scan Response Data Format (page 1392)
and
Volume 4, Part E, Chapter 7.8.8 LE Set Scan Response Data command (page 2489)
should hold the relevant information.@ray007 good catch! Have you tried to remove the if i talked about to see if there was not a second "event" with the extra data?
Edit : we can continue that discussion on discord until we find the solutionUnfortunately no.
But on my test device, the code path does not seem to go through thisonLeScanfunction, but through a similar method ScanCallBackImpl#onScanResult.
ThestateObjectcheck there is only a get or create.Since the problem only happened upon increasing the targetApi level with the same ble module code, I suspect, that the problem is somewhere on a lower level in the java api.
I had hoped that it might just need an extra flag/option/... to be set somewhere, but looking at android docs I have found nothing so far.@ray007 yes it depends on the OS version. It uses one or the user if os version is pre or post lolippop
Yes it is an issue in android itself but we might be able to fix it. You need to be able to test on android 31 or more though
My question on stackoverflow hasn't got any responses so far.
Maybe we need to file a bugreport somewhere with the android project...This might help
I'm reading without a problem on Android 12 (API 31) now. I'm using nativescript-vue, and to debug, I output the JSON with:
<TextView class="theDevice" editable="false" maxLines="3"> {{ currentDevice.json }} </TextView>Where I populate the json property with "json: JSON.stringify(perip)". So, I can see all the service UUIDs on the device after populating perip.services from a call to discoverServices. Note that I do not get them on connect, per my original issue.
@erik777 Thanks for trying, but no luck so far.
But I tried to call
discoverServices({peripheralUUID:peripheral.UUID})in myonDiscoveredcallback during the scan, not inonConnectedlike you did.Calling
discoverServiceslike this on the bluetooth instance I'm also using to callstartScanning(args)on results in an error:[BluetoothError]:Cannot read property 'discoverServices' of undefined, discoverServices, undefined, {"peripheralUUID":"F2:D7:ED:2E:D9:80"}Note: I also checked with
nRF Connect, and there I also can only see the services when I do a connect, not before.
Did something get broken in Android with newer API levels?Update: trying to ignore the problem at scan-time and just trying to connect and read the characteristic does not work either:
[BluetoothError]:error_function_call, readCharacteristic, [B@9abe29b, {"peripheralUUID":"EB:38:0B:BE:FD:D7","serviceUUID":"78a90000-26ce-4367-bfeb-7e3c1d217561","characteristicUUID":"78a90001-26ce-4367-bfeb-7e3c1d217561","timeout":1000}@ray007 if you want to check it out, I got it all working in this app
https://github.com/erik777/fun/tree/main/nativescript/osBT-ts
Runs on Android 12 and 11. Note I had to do things with permissions in the beginning, which can be your issue. There were definitely major permission changes in BLE in Android 12. I've seen a lot of app devs struggle with this in other discussions. But, I did finally get it where you just have to accept the popups on first run and no longer have to navigate to settings to explicitly give it permission. I think other devs had a hard time figuring that one out so they throw up an upset dialog then send the user to the system settings lol.
You can run the app, but the part where it reads/writes it is specific to my RoboSmart lightbulbs. I debug by appending to text boxes. That's how I reverse engineer what it returns as I develop, and how I got services working.
Note that I never discover characteristics because I knew them in advance. So, can't verify if that query works. But, have no trouble reading/writing to them.
Here's where I defined characteristic IDs for my light bulbs.
https://github.com/erik777/fun/blob/main/nativescript/osBT-ts/app/shared/RoboSmart.ts
I did have to discover services, though, even though I had them in advance, as well. That does work.
@erik777 thanks for trying to help.
I don't think permissions are the problem. I know those have changed but updating for that was quite easy.
I also do find our sensors and other devices during a scan, but not if I try to filter byserviceUUID.Question: does your hardware send the
serviceUUIDsin theadvertisingData, or in an extrascanResponse?@ray007 so far I have only seen in the discoverServices response. I have yet to see advertisingData populated, but also haven't considered it, so not sure when it is supposed to populate.
I was now forced by google to increase my target api level for android to 31 (android 12).
After fixing the permission problems (with help from 2 closed issues, a readme update would be nice), the scan started like before but didn't yield any results.
Removing the filter by serviceUUID from scan options did get me results again, but trying to read the service uuid list gets me an empty array.
All this with the latest versions of nativescript, ble module, ...