1

I am trying to detect nearby Bluetooth Low-Energy devices on a service. When the service is started, startLeScan() is called, and then stopLeScan() is called after 10 seconds. Even though startLeScan() returns true, and I didn't get any error, onLeScan on the LeScanCallback was not called. the Service:

    .
    .
    .
            // Device scan callback.
        private BluetoothAdapter.LeScanCallback mLeScanCallback =
                new BluetoothAdapter.LeScanCallback() {

                    public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
                        Log.i(TAG, "New LE Device: " + device.getName() + " @ " + rssi);
                        if (DEVICE_NAME.equals(device.getName()) && deviceAddress.equals(device.getAddress())) {
                            mDevice = device;
                            BleScan(false);
                            connectBluetoothDevice();
                        }
                    }
                };

    /**
     * Starts and stops Bluetooth LE scanning for BLE devices.
     *
     * @param enable true to start scanning, false to stop scanning.
     */
    public void scanLeDevice(final boolean enable) {
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (mScanning) {
                        BleScan(false);
                    }
                }
            }, SCAN_PERIOD);
            BleScan(true);
        } else {
            BleScan(false);
        }

    }

    /**
     * @param scan true to scan, and false to stop scanning for Bluetooth LE devices.
     */
    private void BleScan(boolean scan) {
        if (scan) {
            mScanning = true;
            boolean temp = mBluetoothAdapter.startLeScan(mLeScanCallback);
            Log.i(TAG, "Started LE scan: " + temp);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

I tried to use BluetoothLeScanner startScan() and stopScan(), and using ScanCallback instead, but it didn't help:

    ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            Log.i(TAG, "New LE Device: " + result.getDevice().getName() + " @ " + result.getRssi());
        }

        @Override
        public void onScanFailed(int errorCode) {
            Log.i(TAG, "Scan Faild!!");
        }
    };


    /**
     * Starts and stops Bluetooth LE scanning for BLE devices.
     *
     * @param enable true to start scanning, false to stop scanning.
     */
    public void scanLeDevice(final boolean enable) {
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (mScanning) {
                        BleScan(false);
                    }
                }
            }, SCAN_PERIOD);
            BleScan(true);
        } else {
            BleScan(false);
        }

    }

    /**
     * @param scan true to scan, and false to stop scanning for Bluetooth LE devices.
     */
    private void BleScan(boolean scan) {
        if (scan) {
            mScanning = true;
            mBluetoothLeScanner.startScan(mScanCallback);
            Log.i(TAG, "Started LE scan");
        } else {
            mScanning = false;
            mBluetoothLeScanner.stopScan(mScanCallback);
        }
    }

some say GPS needs to be turned on, so I turned on GPS. I tried rebooting the android device. Another BLE detection app can see the BLE device.

Why isn't the scan callback called?

Edit

I'm running this app on a nexus 5 device running Android 6.0.1 .

I tried adding location permission, but it didn't help:

( uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" )
  • Can you tell us, which phone and Android version you are using? Android 6 needs location permission in order to get scan results. – p2pkit Apr 29 '16 at 08:08
  • I'm running this app on a nexus 5 device running Android 6.0.1 . I tried adding location permission, but it didn't help. – Amitai Fensterheim Apr 30 '16 at 19:21
  • @AmitaiFensterheim What SDK are you targeting? If you're targeting >= 23, you have to explicitly ask for permission at runtime as well. – SJoshi May 01 '16 at 20:28
  • Just to add to SJoshis comment have a look at http://developer.android.com/training/permissions/requesting.html, this will explain how to request the appropriate permission – p2pkit May 02 '16 at 07:53
  • Thanks! It works! Why is the location permission needed for Bluetooth LE? Which BLE scan function should i use, **startLeScan** or **startScan**? – Amitai Fensterheim May 02 '16 at 17:00
  • The permission is needed, as you could easily track people based on known scan results, for example iBeacons. You should use BluetoothAdapter.startLeScan for pre Lollipop devices and the BluetoothLeScanner.startScan for Lollipop onwards. – p2pkit May 03 '16 at 13:49

3 Answers3

1

I have similar problem. Same code, one tablet not work but other does. I have no solution but when I reset my tablet and reinstall apk, it's can work fine again.

I found this onLeScan from BluetoothAdapter.LeScanCallback not called in Android Marshmallow when I open gps, it's work...

Community
  • 1
  • 1
Wachi
  • 21
  • 5
0

Try to switch on the access to location data in app settings (Settings -> Applications -> Your App -> Rules -> Location Data)

0

Follow by Google docs:

1.Add these line to Manifest

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

<!-- Required only if your app isn't using the Device Companion Manager. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

2.Check permission ACCESS_FINE_LOCATION before set up ble

private void checkPermission() {
    String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
    if (checkSelfPermission(permissions[0]) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(permissions, REQUEST_ENABLE_LOCATION);
    }
}
  1. If all not work check your app permission on Settings > App Management > Your app > Permission. Allow Location Access. Done.
duongvanthai
  • 1,518
  • 1
  • 11
  • 14