Since a few days I try to implement an BLE connection in my APP. I know that the Device, I try to connect with, is full functional, so the problem must be my code.
I use the BluetoothLeScanner.startScan()
method.
But the callback Method is never called.
public void startScan() {
if (bluetoothAdapter != null && bluetoothAdapter.isEnabled()) {
isScanning = true;
Handler mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mainActivityHandler.setMSG("Scan stopped");
isScanning = false;
leScanner.stopScan(scanCallback);
}
}, SCAN_TIME);
mainActivityHandler.setMSG("Start scan");
try {
leScanner.startScan(scanCallback);
} catch (Exception e) {
mainActivityHandler.catchError(e);
}
} else mainActivityHandler.catchError(new Exception("Bluetooth not activated"));
}
My CallbackMethod (dont know if I use gatt correctly, but this is a other question):
private ScanCallback scanCallback = new ScanCallback() {
@Override
public void onBatchScanResults(List<ScanResult> results) {
mainActivityHandler.setMSG("Callback");
isScanning = false;
try {
mainActivityHandler.setMSG("Connected to " + results.get(0).getDevice().getName());
gatt = results.get(0).getDevice().connectGatt(mainActivity, true, bluetoothGattCallback);
BluetoothGattDescriptor descriptor;
for (int i = 0; i < charIDs.length; i++) {
gatt.setCharacteristicNotification(gatt.getService(serviceID[0]).getCharacteristic(charIDs[i]), true);
descriptor = gatt.getService(serviceID[0]).getCharacteristic(charIDs[0]).getDescriptor(charIDs[i]);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
} catch (Exception e) {
mainActivityHandler.catchError(e);
}
}
};
The problem is that you are only overriding the onBatchScanResults
method and not onScanResult
method. onBatchScanResults
will only get triggered if:
ScanSettings
mode to ScanSettings.SCAN_MODE_LOW_POWER
(this is the default) using the ScanSettings.Builder
.setReportDelay(long reportDelayMillis)
in your ScanSettings.Builder
.reportDelayMillis - Delay of report in milliseconds. Set to 0 to be notified of results immediately. Values > 0 causes the scan results to be queued up and delivered after the requested delay or when the internal buffers fill up.
For example:
public void startScan(BluetoothLeScanner scanner) {
ScanFilter filter = new ScanFilter.Builder().setDeviceName(null).build();
ArrayList<ScanFilter> filters = new ArrayList<ScanFilter>();
filters.add(filter);
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.setReportDelay(1l)
.build();
Log.i(TAG,"The setting are "+settings.getReportDelayMillis());
scanner.startScan(filters,settings,BLEScan);
}
However, you probably just want to get the results once at a time and not a batch of results. To accomplish that, you don't have to modify the ScanSettings, you just need to override the onScanResult
method in your ScanCallback
and that will do the trick.
private ScanCallback mScanCallback =
new ScanCallback() {
public void onScanResult(int callbackType, ScanResult result) {
System.out.println(result.getDevice().getName())
// Do whatever you want
};
...
};
Anyway, I highly recommend using the library RxAndroidBle. It is very well maintained and it solves many of the BLE issues out of the box (scanning is maybe the less complicated part in BLE).
Using that library, the scanning can be done like this:
Disposable scanSubscription = rxBleClient.scanBleDevices(
new ScanSettings.Builder()
// .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // change if needed
// .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // change if needed
.build()
// add filters if needed
)
.subscribe(
scanResult -> {
// Process scan result here.
},
throwable -> {
// Handle an error here.
}
);
// When done, just dispose.
scanSubscription.dispose();