Michał Witanowski
Michał Witanowski

Reputation: 622

BluetoothAdapter won't stop scanning for BLE devices

In my app i have start and stop button, when user press start i call startScan method

bluetoothAdapter.getBluetoothLeScanner().startScan(getLeScanCallback());

When user press stop i call stopScan however it doesn't seem to do anything. BluetoothAdapter keeps scanning for new devices.

bluetoothAdapter.getBluetoothLeScanner().stopScan(getLeScanCallback());

Here is my getLeScanCallback method:

private ScanCallback getLeScanCallback(){
    ScanCallback leScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            boolean duplicate = false;
            for(Device d : devices) {
                if(d.getAddress().equals(result.getDevice().getAddress()))
                    duplicate = true;
            }
            if(!duplicate) {
                Device device = new Device();
                device.setName(result.getDevice().getName());
                device.setAddress(result.getDevice().getAddress());
                device.setStatus(getString(R.string.disconnected));
                devices.add(device);
                deviceListAdapter.notifyDataSetChanged();
            }
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
        }
    };

    return leScanCallback;
}

It gets called even after stopScan() was called. What am I doing wrong or in other words, how to stop scanning for BLE devices?

Upvotes: 13

Views: 15359

Answers (4)

RadekJ
RadekJ

Reputation: 3063

Every time you call getLeScanCallback you create new instance of ScanCallback and lost reference to previous instance.

stopScan stops ongoing scan regardless what instance you pass BUT if it is a different instance (than the one you used to start) it will not remove old instance of callback so still some events will be delivered to it before it stops.

Upvotes: 28

spekary
spekary

Reputation: 438

Scan results will not stop immediately, but will eventually stop. There is a queue of pending results that you can flush with:

scanner.flushPendingScanResults();

But even then, the documentation is clear that it will send whatever it has found to the callback. This happens even if you have stopped scanning. Poor API design, but it is what it is.

The easiest I think is to set a flag to ignore the scan results after you have stopped them.

Upvotes: 8

Mark O&#39;Sullivan
Mark O&#39;Sullivan

Reputation: 10788

I haven't noticed any issues with your code, it seems to be fine. Perhaps there's an issue with your getLeScanCallback() method?

Instead of having a method to return your ScanCallback, you could declare it as a member variable so you would have leScanCallback = new ScanCallback() and then you could just refer to this member variable instead when trying to stop the scan.

bluetoothAdapter.getBluetoothLeScanner().stopScan(leScanCallback);

Depending on what version of Android you're supporting, it might be worthwhile adding the startLeScan and stopLeScan methods which Rajesh Panchal suggested for pre Lollipop Android devices.

Upvotes: 2

Rajesh Panchal
Rajesh Panchal

Reputation: 1170

replace

bluetoothAdapter.getBluetoothLeScanner().startScan(getLeScanCallback());
bluetoothAdapter.getBluetoothLeScanner().stopScan(getLeScanCallback());

with

bluetoothAdapter.getBluetoothLeScanner().startLeScan(getLeScanCallback()); 
bluetoothAdapter.getBluetoothLeScanner().stopLeScan(getLeScanCallback());

Upvotes: -1

Related Questions