nordicsemiconductor / android-scanner-compat-library Goto Github PK
View Code? Open in Web Editor NEWA compat library for Bluetooth Low Energy scanning on Android.
License: BSD 3-Clause "New" or "Revised" License
A compat library for Bluetooth Low Energy scanning on Android.
License: BSD 3-Clause "New" or "Revised" License
I was able to solve this with the following scanning options, just thought i'll open a ticket in case someone is looking for options to test when the scanning fails on a phone:
ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setReportDelay(1000)
.setUseHardwareBatchingIfSupported(false)
.setUseHardwareFilteringIfSupported(false);
I got this crash, I've check BT is on by mBluetoothAdapter.isEnabled()
.
It's seems like sometimes mBluetoothAdapter.isEnabled()
not the same mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON
.
Do you have any suggestions?
Thx!
Fatal Exception: java.lang.IllegalStateException: BT Adapter is not turned ON
at no.nordicsemi.android.support.v18.scanner.BluetoothLeUtils.checkAdapterStateOn(BluetoothLeUtils.java:137)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerImplLollipop.startScanInternal(BluetoothLeScannerImplLollipop.java:64)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat.startScan(BluetoothLeScannerCompat.java:123)
Hi, I'm seeing these crashes in Google Play console
java.lang.IllegalArgumentException:
at android.bluetooth.le.BluetoothLeScanner.stopScan (BluetoothLeScanner.java:226)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerImplLollipop.stopScan (BluetoothLeScannerImplLollipop.java:98)
...
at android.os.Handler.dispatchMessage (Handler.java:98)
at android.os.Looper.loop (Looper.java:154)
at android.os.HandlerThread.run (HandlerThread.java:61)
I'm only seeing them on S8 and S3 devices, and only on Android 7.0, but we don't have that many users.
I can't see how stopScan can throw IllegalArgumentException (here's nougat's BluetoothLeScanner. I guess that's some Samsung fidling?
I've never been able to reproduce it, but I don't usually work with those devices
Hello,
If a scan is started too often it will fail silently, only printing a onScannerRegistered where you have to read the status code. Is there a way to catch this even? When a scan fails because user or app initiated the scan too often? The ScanCallback does not yeild a onScanFailed.
In my app a scan happens directly when a user enters a certain view, thus toggling in and out of the app (resume/pause) several times will cause the scan to start/stop several times. Sometimes the scan fails to start and thus user is unaware that the scan is not actually running because it fails silently.
The same issue can be found in the nRF Connect app and can be easily reproduced there, happily button mashing the Scan button will cause the app to show a state of scanning (button showing "STOP SCANNING") even though the starting of the scan failed.
I kept getting source code not matching byte code when trying to trace down the error so it was hard for me to research this issue further. Tried looking through the Android Source code but it seems like they are not propagating this information to layers above:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/bluetooth/le/BluetoothLeScanner.java#394
Is there any way to know if you are scanning to often and let the user know or just delay the scan until the module is ready?
Best regards
David
I have a low-power Bluetooth device that advertisement data like this:
[
02 01 05 08 09 61 6e 74 68 65 72 6f
09 ff 11 02 11 02 d9 21 a3 38
1e ff 11 02 11 02 d9 21 a3 38 21 43 01 d9 00 10 19 44 45 4c 20 68 73 65 4d 20 47 53 54 42
4a 00 00 00 00 00 00 00 00 00
]
// result.getScanRecord().getManufacturerSpecificData()
//or
//result.getScanRecord().getManufacturerSpecificData(0x0211)
The ManufacturerSpecificData I read sometimes is like this:
[ 11 02 d9 21 a3 38 ] (When the signal is weak, more is like this)
, sometimes it is like this:
[
11 02 d9 21 a3 38 21 43 01 d9 00 10 19 44 45 4c 20 68 73 65 4d 20 47 53 54 42
4a 00 00 00 00 00 00 00 00 00
]
And I want to get all the advertisement data, but I didn't find the relevant method.
I hope I can get your reply, thank you.
SCAN_MODE_OPPORTUNISTIC has been added in Android Marshmallow.
Currently the library declares this constant, and even use it on Android Marshmallow+ devices, but:
Although it is not possible to fully recreate the same behavior, this could be emulated as SCAN_MODE_LOW_POWER. With setPowerSave(...) method those settings would be applied for pre-Marshmallow devices just like they are when LOW_POWER mode is used. This would have to be documented.
The reason this mode should be supported on older platforms is that currently it is ignored.
Hi there,
I tried the background scanning and it works just perfectly except for devices running Android 7 or lower where this background scanning behavior is emulated as the battery drains really quickly.
On devices with O or P, I saw that the scanning is normally suspended by the OS some time after the device was locked. Is it possibly to do this too or (even better) to just throttle the background scanning then?
Regards
Max
Hi all,
this code for scanning BLE device:
if (mBluetoothLEScanner == null) {
// create bluetoothLE scanner if it is null
mBluetoothLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
}
// start scan bluetooth
mBluetoothLEScanner.startScan(
null,
buildScanSettings(),
mProxyScanCallback);
private ScanSettings buildScanSettings() {
ScanSettings.Builder builder = new ScanSettings.Builder();
builder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);
builder.setReportDelay(0);
return builder.build();
}
Setting:
I cannot found device android >= 6.0.1, but can scan other device
There are any problem?Thank you.
Hi.
Using this lib, I came across an unpleasant thing: if I set filter like as:
final List<ScanFilter> filters = new ArrayList<>();
filters.add(new ScanFilter.Builder().setDeviceName(KNOWN_DEV_NAME).build());
scanner.startScan(filters, settings, scanCallback);
then scanner do not return result and stop by timeout.
Any settings for "setScanMode" do not give a result.
When don`t use filter: all ok.
Code example:
final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
final ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setReportDelay(500)
.build();
final List<ScanFilter> filters = new ArrayList<>();
filters.add(new ScanFilter.Builder().setDeviceName(working_device_name).build());
scanner.startScan(filters, settings, scanCallback);
Hello!
We are trying to use AndroidScannerCompatLibrary in our Android application to scan BLE devices and measure its RSSI level. BLE devices is mounted on ceiling with distance approximately 1m.
There is implementation of StartScan() action (its uses Xamarin Binding Library from Nordic AndroidScannerCompatLibrary .aar file):
var scanner = BluetoothLeScannerCompat.Scanner;
ScanSettings settings = new ScanSettings.Builder()
.SetLegacy(false)
.SetScanMode(ScanSettings.ScanModeLowLatency)
.SetMatchMode(ScanSettings.MatchModeAggressive)
.SetNumOfMatches(ScanSettings.MatchNumMaxAdvertisement) использую
.SetReportDelay(0)
.SetUseHardwareBatchingIfSupported(false)
.Build();
List< ScanFilter > filters = new List<ScanFilter>();
scanner.StartScan(filters, settings, _signalsScanCallback);
_signalsScanCallback store signals in package. After some period of time application send package to server storage.
And this is our stored RSSI level data set (from two iBeacon devices):
It seems like we have data from “one-device-per-period-of-time”.
Should we StartScan() for each device separately with list of ScanFilters, or it’s ok to use one instance of Scanner for all of it? We try to compare our results with same measures from “nRf connect”, and it’s differing. Can someone explain what are we doing wrong?
Hi,
Has anyone ever tested the library with the latest version of Android P.
The library is working flawlessly on devices from Lollipop to Android Oreo but for some reasons, it doesn't work on my Pixel 2.
What trouble me is that the NRF connect app seems to be able to discover the device without any issue.
Thanks for the feedback !
private volatile boolean turnOnOff = false;
private void startTimer() {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
if (!turnOnOff) {
scanner.startScan(null, scanSettings, scanCallback);
Log.i("定时性", "扫描");
} else {
scanner.stopScan(scanCallback);
Log.i("定时性", "停止");
}
turnOnOff = !turnOnOff;
}
} ,0 , 1000);
}
override fun onBatchScanResults(results: List<ScanResult>?) {
// This callback will be called only if the report delay set above is greater then 0.
// If the packet has been obtained while Location was disabled, mark Location as not required
if (Utils.isLocationRequired(application) && !Utils.isLocationEnabled(application))
Utils.markLocationNotRequired(application)
var atLeastOneMatchedFilter = false
for (result in results!!)
atLeastOneMatchedFilter = mDevicesData.deviceDiscovered(result) || atLeastOneMatchedFilter
if (atLeastOneMatchedFilter) {
mDevicesData.applyFilter()
mScannerState.recordFound()
}
stopScan()
}
fun stopScan(){
val scanner = BluetoothLeScannerCompat.getScanner()
scanner.stopScan(scanCallback)
}
Hi, i have some weird behavior with ble scanning.
I implemented app that perform scanning and connection to ble devices with help of android scanner, the problem is i have some devices (for example samsung s8 android version 9) that the scan result not contains the device name, i checked from other android device i do see the name.
I downloaded the NrfConnect app from google play store and it seems that this app show the device name at 80 % of the time in the problematic device (samsung s8) , so i downloaded this library to see what is the 'magic' that helps to receive the name, but after building simple app that prints the name to log i seed that even with current library the names are null always.
The question is what can lead to this problem ? Do you use current library in the NrfConnect app ?
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 23);
}
}
final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
final ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setUseHardwareBatchingIfSupported(false)
//.setReportDelay(5000)
.build();
final List<ScanFilter> filters = new ArrayList<>();
filters.add(new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUID.fromString("XXXXXX-XXXX-0BAC-5241-XXXXXX"))).build());
startScanBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
scanner.startScan(filters, settings,listener);
}
});
stopScanBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
scanner.stopScan(listener);
}
});
}
private ScanCallback listener = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
String name = result.getDevice().getName();
Log.d("OnMyScanResult", "DeviceName: "+name);
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.d("ScanResult", "Scan failed code: "+errorCode);
}
@Override
public void onBatchScanResults(@NonNull List<ScanResult> results) {
super.onBatchScanResults(results);
for(ScanResult result : results){
String name = result.getDevice().getName();
Log.d("OnMyScanResult", "DeviceName: "+name);
}
}
};
Cannot find devices on SAMSUNG some times,but can find in system setting
hello,I can't get the scan result with Android 9.0. The callback result is empty. What's the solution?
Hi there,
as in the example code, I try to add an extra to a callback intent, but this leads to some interesting results:
First, only the added extra shows up in the intent, meaning that BluetoothLeScannerCompat.EXTRA_LIST_SCAN_RESULT
was removed.
But also I get massive stacktraces in logcat:
2019-09-17 10:33:02.790 1365-3432/? E/Parcel: Class not found when unmarshalling: no.nordicsemi.android.support.v18.scanner.ScanResult
java.lang.ClassNotFoundException: no.nordicsemi.android.support.v18.scanner.ScanResult
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
at android.os.Parcel.readParcelableCreator(Parcel.java:2811)
at android.os.Parcel.readParcelable(Parcel.java:2765)
at android.os.Parcel.readValue(Parcel.java:2668)
at android.os.Parcel.readListInternal(Parcel.java:3098)
at android.os.Parcel.readArrayList(Parcel.java:2319)
at android.os.Parcel.readValue(Parcel.java:2689)
at android.os.Parcel.readArrayMapInternal(Parcel.java:3037)
at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
at android.os.BaseBundle.unparcel(BaseBundle.java:232)
at android.os.Bundle.putAll(Bundle.java:288)
at android.content.Intent.fillIn(Intent.java:9433)
at com.android.server.am.PendingIntentRecord.sendInner(PendingIntentRecord.java:269)
at com.android.server.am.PendingIntentRecord.sendWithResult(PendingIntentRecord.java:245)
at com.android.server.am.ActivityManagerService.sendIntentSender(ActivityManagerService.java:10000)
at android.app.IActivityManager$Stub.onTransact$sendIntentSender$(IActivityManager.java:11540)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:3183)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3829)
at android.os.Binder.execTransact(Binder.java:752)
Caused by: java.lang.ClassNotFoundException: no.nordicsemi.android.support.v18.scanner.ScanResult
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:1346)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:1406)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
at android.os.Parcel.readParcelableCreator(Parcel.java:2811)
at android.os.Parcel.readParcelable(Parcel.java:2765)
at android.os.Parcel.readValue(Parcel.java:2668)
at android.os.Parcel.readListInternal(Parcel.java:3098)
at android.os.Parcel.readArrayList(Parcel.java:2319)
at android.os.Parcel.readValue(Parcel.java:2689)
at android.os.Parcel.readArrayMapInternal(Parcel.java:3037)
at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
at android.os.BaseBundle.unparcel(BaseBundle.java:232)
at android.os.Bundle.putAll(Bundle.java:288)
at android.content.Intent.fillIn(Intent.java:9433)
at com.android.server.am.PendingIntentRecord.sendInner(PendingIntentRecord.java:269)
at com.android.server.am.PendingIntentRecord.sendWithResult(PendingIntentRecord.java:245)
at com.android.server.am.ActivityManagerService.sendIntentSender(ActivityManagerService.java:10000)
at android.app.IActivityManager$Stub.onTransact$sendIntentSender$(IActivityManager.java:11540)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:3183)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3829)
at android.os.Binder.execTransact(Binder.java:752)
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
2019-09-17 10:33:02.790 1365-3432/? W/Bundle: Failed to parse Bundle, but defusing quietly
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: no.nordicsemi.android.support.v18.scanner.ScanResult
at android.os.Parcel.readParcelableCreator(Parcel.java:2839)
at android.os.Parcel.readParcelable(Parcel.java:2765)
at android.os.Parcel.readValue(Parcel.java:2668)
at android.os.Parcel.readListInternal(Parcel.java:3098)
at android.os.Parcel.readArrayList(Parcel.java:2319)
at android.os.Parcel.readValue(Parcel.java:2689)
at android.os.Parcel.readArrayMapInternal(Parcel.java:3037)
at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:288)
at android.os.BaseBundle.unparcel(BaseBundle.java:232)
at android.os.Bundle.putAll(Bundle.java:288)
at android.content.Intent.fillIn(Intent.java:9433)
at com.android.server.am.PendingIntentRecord.sendInner(PendingIntentRecord.java:269)
at com.android.server.am.PendingIntentRecord.sendWithResult(PendingIntentRecord.java:245)
at com.android.server.am.ActivityManagerService.sendIntentSender(ActivityManagerService.java:10000)
at android.app.IActivityManager$Stub.onTransact$sendIntentSender$(IActivityManager.java:11540)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:3183)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3829)
at android.os.Binder.execTransact(Binder.java:752)
I was testing my code on a OnePlus 5T running Android 9, scanner lib is at 1.4.3.
Does anyone know what's going on there?
Cheers,
Max
Hi,
Using your scanner compat library I've noticed that the scanner sometimes discovers devices where the record.device.name is null. Whenever the scanner identifies one of your boards like this I cannot connect to it - BleManager.connect(device) simply times out without providing any callbacks.
To resolve this problem I start nRF Connect which then causes the scanner to correctly find the friendly name of the devices as well as allowing me to connect to them.
It feels like I am missing something with the scanner, you seem to somehow reset the adapter. How is this done?
Thanks for some great products!
Hello,
SCAN_RESULT_TYPE_FULL and SCAN_RESULT_TYPE_ABBREVIATED are private but the method setScanResultType is public.
Mike
Issue initially reported here: https://stackoverflow.com/questions/47981327/scancallback-onbatchscanresults-is-getting-called-indefinitly (very long time ago).
I can confirm scanning started with the following settings does not stop when stopScan
is called in onBatchedScanResults
:
// Scanning settings
final ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setReportDelay(500)
.setUseHardwareBatchingIfSupported(false)
.build();
Logs from a sample app:
2019-01-18 16:28:56.831 29232-29232/no.nordicsemi.android.nrfblinky W/AA: callback used to start scan: no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerImplLollipop$ScanCallbackWrapperLollipop$1@f4e51ba
2019-01-18 16:28:57.331 29232-29232/no.nordicsemi.android.nrfblinky I/AA: onBatchScanResults: 16
2019-01-18 16:28:57.334 29232-29232/no.nordicsemi.android.nrfblinky W/AA: callback used to stop scan: no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerImplLollipop$ScanCallbackWrapperLollipop$1@f4e51ba
2019-01-18 16:28:57.837 29232-29232/no.nordicsemi.android.nrfblinky I/AA: onBatchScanResults: 0
2019-01-18 16:28:59.844 29232-29232/no.nordicsemi.android.nrfblinky I/AA: onBatchScanResults: 0
2019-01-18 16:29:00.346 29232-29232/no.nordicsemi.android.nrfblinky I/AA: onBatchScanResults: 0
2019-01-18 16:29:00.847 29232-29232/no.nordicsemi.android.nrfblinky I/AA: onBatchScanResults: 0
2019-01-18 16:29:01.349 29232-29232/no.nordicsemi.android.nrfblinky I/AA: onBatchScanResults: 0
[...]
Tested with version 1.2.0 on Pixel 2 with Android Pie.
getting an unusual RuntimeException in Android 6.0.1 API23 with targetSdkVersion 23 (build.gradle)
It was OK in Android 6.0.1 API23 with targetSdkVersion 22 (build.gradle)
`02-20 13:08:53.919 12379-12513/ D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
02-20 13:08:53.923 12379-12513/ W/Binder: Caught a RuntimeException from the binder stub implementation.
java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results
at android.os.Parcel.readException(Parcel.java:1627)
at android.os.Parcel.readException(Parcel.java:1579)
at android.bluetooth.IBluetoothGatt$Stub$Proxy.startScan(IBluetoothGatt.java:772)
at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper.onClientRegistered(BluetoothLeScanner.java:324)
at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:56)
at android.os.Binder.execTransact(Binder.java:453)
02-20 13:09:01.213 12379-12574/ V/RenderScript: 0x7f5fe7e000 Launching thread(s), CPUs 8
02-20 13:09:01.231 12379-12379/ I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@abbc528 time:42374438`
filters.add(new ScanFilter.Builder().setServiceUuid(mUuid).build());
I don't know this.mUUid what it is mean.please
I want it to keep scanning until I call a stop
Hello,
What do you think about calling ScanCallback methods in a worker thread? It would be useful for wrapping scanner in RxJava Observable class. Right now everything is invoked in the main thread. It is simple to implement, just add a Handler param in startScan method (like in Android SensorManager or LocationManager class).
i have logged (can't reproduce, now under heavy test) cases where scanner.stopScan(nordic_scanCallback); has been issued in API 18 (Android 4.3 HTC phone) but the onBatchScanResults (...) still continue receiving (something like that shown below) and NO D/BluetoothAdapter: onScanResult() - Device=B4:99:4C:1E:7C:32 RSSI=-88 logged.
@OverRide
public void onBatchScanResults(List results)
{
Log.d(TAG, "nordic_scanCallback -> onBatchScanResults sz = " + results.size());
}
D/BluetoothAdapter: stopLeScan()
...
....
D/BLE_com: nordic_scanCallback -> onBatchScanResults sz = 0
D/BLE_com: nordic_scanCallback -> onBatchScanResults sz = 0
D/BLE_com: nordic_scanCallback -> onBatchScanResults sz = 0
D/BLE_com: nordic_scanCallback -> onBatchScanResults sz = 0
...
...
...
Samsung S5, on Android 5.0.
new no.nordicsemi.android.support.v18.scanner.ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC)
.setUseHardwareBatchingIfSupported(false)
.build();
java.lang.IllegalArgumentException: invalid scan mode -1
at android.bluetooth.le.ScanSettings$Builder.setScanMode(ScanSettings.java:213)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerImplLollipop.toImpl(BluetoothLeScannerImplLollipop.java:186)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerImplLollipop.startScanInternal(BluetoothLeScannerImplLollipop.java:70)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat.startScan(BluetoothLeScannerCompat.java:112)
It should fallback to a mode that it does support, which would probably be SCAN_MODE_LOW_POWER
.
It would be good to have a scanning timeout to set a maximum of the process if desired. Something like this in the API would be nice:
@NonNull
public Builder setDuration(final long durationMillis) {
if (durationMillis < 0) {
throw new IllegalArgumentException("durationMillis must be > 0");
}
this.durationMillis = durationMillis;
return this;
}
and start a Handler
with that specific durationMillis
until it is reached to stop the scanning process. I guess that would require a new onStop
method in the ScanCallback
abstract class.
What do you think guys? Is it something the library could handle or it's just better to manage ourselves those timeouts?
I have using this library to scan and connect the Bluetooth devices to android app. Its working fine. Now once device is connect then i set Connected
text in ListAdapter textview in the app that user can see that device is connected. After if any device goes to out of range or disconnected then i need to update the state Connected
to Connecting.....
in the ListAdapter UI but how i know that device is connected or not?
One other thing is if device is connected and its state changed (means any kind of notify ) then how to know that ?
Help would be very appreciate and thanks
Hello,
I tested this case with Samsung S9 (Android 9.0) and Sony (Android 7.0). Same problem appears.
I also downloaded from Play Store "nRF Connect for Mobile" to make sure my implementation is not the real issue here. Same happens there.
then I procceed 1.-2. steps. But then, when I do "bonding" it says "bonding failed" and no PIN pop-up is shown. I tried to delete app, delete cache data on Bluetooth and restart device. At some point I made it possible to do the bonding once again. Followed the same path and then again after I unpaired device, I could not find a way to create bond with it.
My question is - is this supposed to be like that? Could it be, that my device is configurated somehow wrongly (after unpairing which is from user side, bonding data is not deleted or smth)?
I did try to refresh device cache ect., but nothing changed.
Hi,
I'm currently trying to set some ScanFilters when registering my BLEScanner to filter on service UUID and Manufacturer Data.
The thing is, while the ScanResults I get are properly filtered with service UUID, there is no filter applied on Manufacturer Data, resulting on inconsistent Scan Result filtering...
I tried the following:
filters.add(ScanFilter.Builder()
.setServiceUuid(ParcelUuid.fromString(serviceUUID.toString()))
.build())
filters.add(ScanFilter.Builder()
.setManufacturerData(manufacturerId, manufacturerData, mask)
.build())
or
filters.add(ScanFilter.Builder()
.setManufacturerData(manufacturerId, manufacturerData, mask)
.setServiceUuid(ParcelUuid.fromString(serviceUUID.toString()))
.build())
coupled with scanner.startScan(filters, settings, callback)
Scan Results only seem to be filtered on Service UUID.
My manufacturerId
is an int, manufacturerData
is a ByteArray and mask
is a ByteArray of the same size with full 1
.
Can you please help me on this issue ?
The new pendingIndent solution works great on Android >= Oreo.
I wrote a foreground service that handles the BLE stuff independently from the actual app. This service is the only place where startScan/stopScan
is called.
When I call scanner.startScan(filters, settings, mService, pendingIntent);
the scanning stops when i swipe the app out of the android "task-manager" (The foreground-service is still running). When I start the scan with scanner.startScan(filters, settings, scanCallback);
scanning didn't stop.
I think this is the normal background task behavior when the task is started from an activity in the app. I wonder why the background task get destroyed when I start the scan in the foreground service.
Not sure if I've configured this correctly, but I'm not seeing any scan results returned in my callback. It looks like the scanRecord byte[] is coming in as partial instead of complete when attempting to init a ScanRecord. When parseServiceUuid is called on line 224 inside ScanRecord.java, there is no data to parse, so I'm not seeing any returned scan results in my callback. I've implemented a different scanning service which returns the 128 bit complete data type from the same peripheral device. Am I missing some configuration settings that allows the scanner to return the completed byte[]?
I'm using the sample scanning code noted in your readme.
Hi,
Sometimes the device name is null on onBatchScanResults
, switching bluetooth on/off doesn't help, but after scanning with nRFConnect, and rescan with library the problem resolved. Is there any configuration that nRFConnect use? or is there any cache that I should clear before starting scan?
Hello,
On the Readme.md, you specify to add the following dependencie :
compile 'no.nordicsemi.android.support.v18:scanner:1.0.0'
How ever you don't specify on which repository. I found a version 0.1.1 available on :
https://mvnrepository.com/artifact/no.nordicsemi.android.support.v18/scanner/0.1.1
But no 1.0.0. Could you update the readme.md ?
Thanks.
Regards,
Clement.
Android 7.0 can be scanned,Android 6.0 can not scanned the device, why?
Its working fine in my current project. i am using Android Studio 3.2 and before 3.1. i have seen one warning message that change the compile
to implementation
. But when i change compile to implementation then this error is occur in android studio 3.2. As per google that compile is closed to end of the 2018 so i am trying to change it. So is there any update regarding this then its appreciate. I have checked this stack overflow link also.
Hello,
I am in the process of designing an app which listens for any BLE advertisements, and filters them according to their contents. Currently, I am testing the reliability of the nordic BluetoothLeScannerCompat - that is, I am seeing if it will receive all advertisement data. I have a peripheral emitting an advertisement on channels 37-39, once every 40ms.
In nRF connect, all of these advertisements are received with great consistency, as shown in the "History" tab of any device. However, when I use the nordic (and Android Standard) Scanner, I am much less consistent in receiving these advertisements. In a 15 second timespan, my application received about 40 advertisements from the peripheral, whereas nRF Connect received about 150.
My code for the scanner:
String desiredMacAddress = the peripherals mac address.
BluetoothAdapter mBTAdapter;
BluetoothLeScannerCompat mBleScanner;
ScanCallback scanCallback = new ScanCallback (){
@Override
public void onScanResult(int callbackType, ScanResult result){
if ( result.getDevice().getAddress().equals(desiredMacAddress )
appendMyTextView("\n You received me!");
});
}
};
public void init(){
final BluetoothManager btManager = (BluetoothManager)
scanActivity.getSystemService(Context.BLUETOOTH_SERVICE);
mBTAdapter = btManager.getAdapter();
mBleScanner = BluetoothLeScannerCompat.getScanner();
scanLeDevice(true)
}
private void scanLeDevice(final boolean enable){
if(enable) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//BLEDevice Scan has ended
stop()
}
}, 15000);
mLeScanner.startScan(scanCallback);
}
else{
mScanning = false;
mLeScanner.stopScan(scanCallback);
}
}
private void stop(){
scanLeDevice(false)
}
Any advice on how to improve scan reliability would be much appreciated!
Pending Intent callback doesn't provides the Scan result data. Can you provide an example for the same if it's already available?
This problem might manifest itself with can't Register GATT client, MAX client reached: 32
output in an unfiltered log.
Please also refer to my StackOverflow question and self-answer:
https://stackoverflow.com/q/57104535/252308
Basically, BluetoothLeScannerImplOreo startScanInternal
has the following code (I added the log line in my fork):
final PendingIntent pendingIntent = createStartingPendingIntent(nonNullFilters,
nonNullSettings, context, callbackIntent);
Log.v(TAG, "#GATT startScanInternal: pendingIntent=" + pendingIntent);
return scanner.startScan(nativeFilters, nativeSettings, pendingIntent);
stopScanInternal
has the following code (log line added in my fork):
final PendingIntent pendingIntent = createStoppingPendingIntent(context, callbackIntent);
Log.v(TAG, "#GATT stopScanInternal: pendingIntent=" + pendingIntent);
scanner.stopScan(pendingIntent);
Here is a log of my app starting and stopping a few scans:
2019-07-19 21:14:51.230 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.startScan(...)
2019-07-19 21:14:58.424 16905-16905/com.testapp V/BleScannerImplOreo: #GATT startScanInternal: pendingIntent=PendingIntent{1dfc67: android.os.BinderProxy@e560a14}
2019-07-19 21:14:58.468 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register 3c2e1fd9-d3fd-6897-a113-863aa50df781
2019-07-19 21:14:58.468 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=7
2019-07-19 21:14:58.478 16905-16905/com.testapp V/BleScannerManager: scan: #GATT bleScanner.startScan(...); result=SUCCESS(0)
2019-07-19 21:14:58.479 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.startScan(...)
2019-07-19 21:14:58.481 16905-16905/com.testapp E/BleScannerManager: #GATT bleScannerStartScanCount=1, elapsedMillisSinceBleScannerStartScanFirstTime=0
2019-07-19 21:15:03.521 1447-1447/? D/BtGatt.ScanManager: awakened up at time 614650173
2019-07-19 21:15:08.250 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.stopScan(...)
2019-07-19 21:15:08.255 16905-16905/com.testapp V/BleScannerImplOreo: #GATT stopScanInternal: pendingIntent=PendingIntent{dc4115f: android.os.BinderProxy@84087ac}
2019-07-19 21:15:08.259 1447-1982/? E/BtGatt.ContextMap: Context not found for info com.android.bluetooth.gatt.GattService$PendingIntentInfo@77d2d25
2019-07-19 21:15:08.260 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.stopScan(...)
2019-07-19 21:15:08.556 1447-1447/? D/BtGatt.ScanManager: awakened up at time 614655208
2019-07-19 21:15:08.570 1447-1554/? E/BtGatt.GattService: Exception: android.app.PendingIntent$CanceledException
2019-07-19 21:15:20.556 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.startScan(...)
2019-07-19 21:15:20.570 16905-16905/com.testapp V/BleScannerImplOreo: #GATT startScanInternal: pendingIntent=PendingIntent{2ce86d6: android.os.BinderProxy@84087ac}
2019-07-19 21:15:20.575 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register 6b444e39-d61a-1d92-52d6-afd6e901b56b
2019-07-19 21:15:20.575 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=8
2019-07-19 21:15:20.576 16905-16905/com.testapp V/BleScannerManager: scan: #GATT bleScanner.startScan(...); result=SUCCESS(0)
2019-07-19 21:15:20.576 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.startScan(...)
2019-07-19 21:15:20.576 16905-16905/com.testapp E/BleScannerManager: #GATT bleScannerStartScanCount=2, elapsedMillisSinceBleScannerStartScanFirstTime=22097
2019-07-19 21:15:23.264 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.stopScan(...)
2019-07-19 21:15:23.269 16905-16905/com.testapp V/BleScannerImplOreo: #GATT stopScanInternal: pendingIntent=PendingIntent{ebafcb0: android.os.BinderProxy@ebb6729}
2019-07-19 21:15:23.272 1447-1982/? E/BtGatt.ContextMap: Context not found for info com.android.bluetooth.gatt.GattService$PendingIntentInfo@3abaefa
2019-07-19 21:15:23.272 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.stopScan(...)
2019-07-19 21:15:24.968 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.startScan(...)
2019-07-19 21:15:24.980 16905-16905/com.testapp V/BleScannerImplOreo: #GATT startScanInternal: pendingIntent=PendingIntent{8b1626b: android.os.BinderProxy@ebb6729}
2019-07-19 21:15:24.990 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register 0bbb0b8f-2c63-dfc2-268d-fbfe39360ddf
2019-07-19 21:15:24.990 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=9
2019-07-19 21:15:24.990 16905-16905/com.testapp V/BleScannerManager: scan: #GATT bleScanner.startScan(...); result=SUCCESS(0)
2019-07-19 21:15:24.990 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.startScan(...)
2019-07-19 21:15:24.991 16905-16905/com.testapp E/BleScannerManager: #GATT bleScannerStartScanCount=3, elapsedMillisSinceBleScannerStartScanFirstTime=26511
2019-07-19 21:15:25.019 1447-1554/? E/BtGatt.GattService: Exception: android.app.PendingIntent$CanceledException
2019-07-19 21:15:25.795 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register 32a50296-06f2-ed4d-f83c-25da059a4a19
2019-07-19 21:15:25.795 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=10
2019-07-19 21:15:26.046 1447-1447/? D/BtGatt.ScanManager: awakened up at time 614672699
2019-07-19 21:15:27.000 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.stopScan(...)
2019-07-19 21:15:27.005 16905-16905/com.testapp V/BleScannerImplOreo: #GATT stopScanInternal: pendingIntent=PendingIntent{40e339d: android.os.BinderProxy@6340012}
2019-07-19 21:15:27.008 1447-1982/? E/BtGatt.ContextMap: Context not found for info com.android.bluetooth.gatt.GattService$PendingIntentInfo@96b43b4
2019-07-19 21:15:27.009 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.stopScan(...)
2019-07-19 21:15:28.679 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register f119757a-00ff-29b4-72e0-952c5e0db695
2019-07-19 21:15:28.679 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=10
2019-07-19 21:15:28.810 1447-1447/? D/BtGatt.ScanManager: awakened up at time 614675462
2019-07-19 21:15:28.822 1447-1554/? E/BtGatt.GattService: Exception: android.app.PendingIntent$CanceledException
Notice that the pendingIntent=
logged during a startScan
and stopScan
do not match.
This means that the code never actually stops any PendingIntent started scans.
The pendingIndent
passed to stopScan
must be the exact same one that was passed to startScan
.
You can usually only start about 28, max of 32, scans before the OS blocks all future scans.
This repros on every API >= 26 phone I have tried.
I can look in to a fix and send a PR, but I wanted to open this issue to see if there is anything else to discuss.
Hi,
I have used the Sample provided in the description, without any filter.
But still I am not getting callbacks. I have also referred to nrf-blinky example which uses this library.
My Scan code is exactly same as that provided in except filter part https://github.com/NordicSemiconductor/Android-nRF-Blinky. But still no callbacks are received.
Phone Model - Oneplus 3.
Note - I am trying to search and connect a non nordic BLE device. will that have any impact on this?
Please help I am stuck on this :(
Thanks,
sat
It would be a good idea to have tests to cover the classes.
Maybe some tests from the original implementation could be reused and adapted.
For example ScanFilterTest
When I use the scanner library to filter my Bluetooth LE devices ,I use the method "setServiceUuid " but doesn't work?
final String uuid = "0000fff0-0000-1000-8000-00805f9b34fb";
setServiceUuid(ParcelUuid.fromString(uuid))
Hi,
I have one problem in scan devices on Android Lollipop (5.1.1).
I have one device advertising constantly and sometimes the library don't return this device in advertisement results.
I was investigating the problem and I noted that when the lib don't return the advertisement anyone BLE app returns that advertisement.
It's like the Android has blocked that "device" and anyone app can't identify.
On newer Android versions I don't have this problem.
Someone knows what's happening?
PS: There is a fun fact that looking the LOG, I can see de BLE Address with and error, but I don't found any explanation about that.
09-15 15:09:01.268 4379-4579/? E/bt-btm: new address: 55:44:33:22:11:00
where my BLE Address is 55:44:33:22:11:00 but the result don't appear in the return scanned devices on the lib.
I have tried to filter by BLE Address, services, manufacturer data, etc etc, but I have the same problem.
Thanks in advanced.
hello. i'm using your library in my project. Its working perfectly in API 5, But when i test it on 6.0.1 ScanCallBack didn't called.
i'm using scanner.startScan(mScanCallback) method and onScanResult never triggered.
Hope you will reply soon and guide me through. thanks
Hi,
Thanks for your great library. I tried to find a heart rate monitor gadget, but unfortunately scanner.startScan(filter, settings, callback)
doesn't return any result. When I use scanner.startScan(callback)
it found the device. I tested with both service UUID and device name. I used complete 128bit service uuid 0000180D-0000-1000-8000-00805f9b34fb
.
Commit 8a20607 is nice, but I think will break my app.
My app already detects BT on/off and "pauses" or "resumes" scanning as necessary.
If Android-Scanner-Compat-Library automatically stops scanning then my app could see that has a hard stop and hard stop itself.
I haven't yet updated my dependency to confirm if you change breaks my app.
But, hear me out and please let me know if my opinion seems valid...
Again, nice change, but if you are going to automatically stop scanning then coolio, but that is only part of the story.
To make this a complete solution then you must also then detect when BT is turned on and automatically start scanning if the user of your library hasn't called stop.
Also, this auto-stop/start feature should be an option, which would be fine to default to on.
It is possible that this change doesn't break my code, but I think this library would benefit from a more complete solution.
I'd like to include Android-Scanner-Compat-Library in a project where min SDK < 18 so that if the device SDK is < 18, then I wouldn't use BLE capabilities, and otherwise I would use it per this library.
However, the manifest requires min SDK 18. Is there any way around this?
12-26 09:31:00.811 885-3257/? E/[email protected]_lock: Release wakelock is released
Great library! Encountered one problem.
With the normal ScanFilter object I can make this call to filter only advertisements that match the specific manufacturer ID (while not caring what the actual manufacturer data is).
private final ScanFilter mScanFilter = new ScanFilter.Builder()
.setManufacturerData(MFG_ID, null)
.build();
But making this call with this scanner compat library and running it on 5.0.1 (and possibly others) results in a crash due to the null byte array.
Here's the stack trace:
java.lang.NullPointerException: Attempt to get length of null array
at no.nordicsemi.android.support.v18.scanner.ScanFilter.matchesPartialData(ScanFilter.java:345)
at no.nordicsemi.android.support.v18.scanner.ScanFilter.matches(ScanFilter.java:302)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat$ScanCallbackWrapper.matches(BluetoothLeScannerCompat.java:298)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat$ScanCallbackWrapper.handleScanResult(BluetoothLeScannerCompat.java:248)
at no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerImplLollipop$ScanCallbackImpl.onScanResult(BluetoothLeScannerImplLollipop.java:131)
at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run(BluetoothLeScanner.java:347)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.