1

I have faced with the issue using startScan method of BluetoothLeScanner a BLE device was found, but when I turned off BLE device my phone still shows this device as turned on !!

I have tried to use:

private ScanCallback mScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        Log.i("ScanCallback", String.format("onScanResult(int callbackType[%d], ScanResult result)", callbackType));
        final BluetoothDevice btDevice = result.getDevice();
        if (btDevice == null){
            Log.e("ScanCallback", "Could not get bluetooth device");
            return;
        }

        final String macAddress = btDevice.getAddress();
        if (callbackType == ScanSettings.CALLBACK_TYPE_MATCH_LOST) {
            // NOTE: I've never got here
            final BluetoothDevice outOfRangeDevice = mBtDevices.get(macAddress);
            ...
        } else {
            ...
        }
    }
    ...
};

Guy, I have not found solution how to detect that BLE device is lost in other resources like (Android SDK reference, forums, stackoverflow and etc) (:

Any help will be appreciated !!

Denis Kotov
  • 857
  • 2
  • 10
  • 29
  • Possible duplicate of [Proper way to find if a paired Android Bluetooth device is in range?](https://stackoverflow.com/questions/11415791/proper-way-to-find-if-a-paired-android-bluetooth-device-is-in-range) – Daniel Reyhanian Feb 06 '19 at 21:34
  • @DanielReyhanian No, I asked about any BT device in range not only paired. It will not work in my case – Denis Kotov Feb 06 '19 at 21:38
  • Can't you get into the system properties and check that? Isn't there any attribute with all the ranged devices? Weird. – Daniel Reyhanian Feb 06 '19 at 21:38
  • What about [this](https://stackoverflow.com/questions/3170805/how-to-scan-for-available-bluetooth-devices-in-range-in-android)? – Daniel Reyhanian Feb 06 '19 at 21:39
  • Another [possibility](https://code.tutsplus.com/tutorials/create-a-bluetooth-scanner-with-androids-bluetooth-api--cms-24084). – Daniel Reyhanian Feb 06 '19 at 21:39
  • @DanielReyhanian Post https://stackoverflow.com/questions/3170805/how-to-scan-for-available-bluetooth-devices-in-range-in-android relates to the general Bluetooth Protocol also known as Bluetooth "Classic" not for Bluetooth Low-Energy – Denis Kotov Feb 06 '19 at 21:41
  • @DanielReyhanian Seems like https://code.tutsplus.com/tutorials/create-a-bluetooth-scanner-with-androids-bluetooth-api--cms-24084 also relates to Bluetooth "Classic" – Denis Kotov Feb 06 '19 at 21:43

2 Answers2

0

This one is looking good (JAVA):

As I understood, you need to implement startLeScan().

Find BLE devices

To find BLE devices, you use the startLeScan() method. This method takes a BluetoothAdapter.LeScanCallback as a parameter. You must implement this callback, because that is how scan results are returned. Because scanning is battery-intensive, you should observe the following guidelines:

As soon as you find the desired device, stop scanning. Never scan on a loop, and set a time limit on your scan. A device that was previously available may have moved out of range, and continuing to scan drains the battery. The following snippet shows how to start and stop a scan:

public class DeviceScanActivity extends ListActivity {

    private BluetoothAdapter mBluetoothAdapter;
    private boolean mScanning;
    private Handler mHandler;

    // Stops scanning after 10 seconds.
    private static final long SCAN_PERIOD = 10000;
    ...
    private void scanLeDevice(final boolean enable) {
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                }
            }, SCAN_PERIOD);

            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
        ...
    }
...}

Consider checking this tutorial as well. Also this one.

Mohamad Mousheimish
  • 1,641
  • 3
  • 16
  • 48
Daniel Reyhanian
  • 579
  • 4
  • 26
0

During googling and exploring the Android Documentations I have figured out how to detect if device is out of range. I would like to share my solution how I did it:

...
public void scanBLEDevices(final boolean enable) {
    if(mLeScanner == null) {
        Log.d(TAG, "Could not get LEScanner object");
        throw new InternalError("Could not get LEScanner object");
    }

    if (enable) {
        startLeScan();
    } else {
        stopLeScan(false);
    }
}

private void startLeScan() {
    Log.i(TAG, "startLeScan(BluetoothLeScanner mLeScanner)");
    mScanning = true;
    mInRangeBtDevices.clear();
    if (mStartScanCallback != null) {
        mHandler.removeCallbacks(mStartScanCallback);
    }
    if (Build.VERSION.SDK_INT < 21) {
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
        mLeScanner.startScan(mScanFilters, mScanSettings, mScanCallback);
    }
    mStopScanCallback = new Runnable() {
        @Override
        public void run() {
            stopLeScan(true);
        }
    };
    mHandler.postDelayed(mStopScanCallback, SCAN_PERIOD);
}

private void stopLeScan(final boolean isContinueAfterPause) {
    Log.i(TAG, "stopLeScan(BluetoothLeScanner mLeScanner)");
    mScanning = false;
    if (mStopScanCallback != null) {
        mHandler.removeCallbacks(mStopScanCallback);
    }
    removeOutOfRangeDevices();
    if (Build.VERSION.SDK_INT < 21) {
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    } else {
        mLeScanner.stopScan(mScanCallback);
    }
    if (isContinueAfterPause) {
        mStartScanCallback = new Runnable() {
            @Override
            public void run() {
                startLeScan();
            }
        };
        mHandler.postDelayed(mStartScanCallback, SCAN_PAUSE);
    }
}

private void removeOutOfRangeDevices() {
    final Set<String> outOfRangeDevices = new HashSet<>();
    for (String btAddress : mBtDevices.keySet()) {
        if (!mInRangeBtDevices.contains(btAddress)) {
            outOfRangeDevices.add(btAddress);
        }
    }
    for (String btAddress : outOfRangeDevices) {
        final BluetoothDevice outOfRangeDevice = mBtDevices.get(btAddress);
        mBtDevicesRSSI.remove(btAddress);
        mBtDevices.remove(btAddress);
    }
}
...

Explanation:

  1. As you can see I have added on each scanning period mInRangeBtDevices collection that will keep all devices found during the current scanning.
  2. When I stop scanning, I am also removing out of range device from previous lists that is not available anymore using one additional helper collection outOfRangeDevices

I think this example would be usefull and you will be able to integrate it in your own code

Denis Kotov
  • 857
  • 2
  • 10
  • 29