Jacopo Tosi
Jacopo Tosi

Reputation: 752

BluetoothLeScanner.startScan with Android 6.0 does not discover devices

I'm trying to use the function BluatoothLeScanner.startScan instead of the deprecated one BluetoothAdapter.startLeScan. Yesterday I updated my Nexus 5 to Android 6.0 and since that moment my app does not work anymore. I firstly add the preferences required ACCESS_COARSE_LOCATION as found here, https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id. Then I added the permission as described here: https://developer.android.com/training/permissions/requesting.html. But at the end it seems not working, it does not send back the ble devices.

This is my code:

manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.stm.sensitronapp">
          <uses-sdk android:maxSdkVersion="23"/>
          <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

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

DeviceScanActivity

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
...

if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED){
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.ACCESS_COARSE_LOCATION)) {
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                    MY_PERMISSIONS_REQUEST_ACCESS_COARSE);
        }
    }

// Device scan callback.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            mScanCallback = new ScanCallback() {
                @Override
                public void onScanResult(int callbackType, ScanResult result) {
                    super.onScanResult(callbackType, result);
                    mLeDeviceListAdapter.addDevice(result.getDevice());
                    mLeDeviceListAdapter.notifyDataSetChanged();
                }
            };
        }
    } 
}
final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();

if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
        mSwipeRefreshLayout.setRefreshing(true);
        mLeDeviceListAdapter.clear();
        mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
        if(ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED) {
                mBluetoothLeScanner.startScan(mScanCallback);
            }
        }

EDIT: to solve this problem I only turned on the GPS. It is easy to do it programmatically in this way.

Upvotes: 27

Views: 23304

Answers (6)

Rest
Rest

Reputation: 17

Set your 'minSdkVersion' to 18 targetSdkVersion 22

Upvotes: -3

Andromer
Andromer

Reputation: 123

It's an old question, but I will answer to help someone.
Unfortunately, the combination of ACCESS_COARSE_LOCATION and targetSdkVersion 22 does not work on some devices.
This is not a good method, but I have solved it in the following way without using runtime permissions (ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION)

  1. Set your 'targetSdkVersion' to 19 (I think maybe api19 ~ api22 will be possible)
  2. Add the following permission to your manifest file

    <uses-permission android:name="android.permission.READ_OWNER_DATA" />
    <uses-permission android:name="android.permission.WRITE_OWNER_DATA" />
    

tested to Android 4.4 ~ 7.1.1

Upvotes: 0

qinmiao
qinmiao

Reputation: 5789

if permissions granted, have a try: turn ON the GPS.

Upvotes: 27

Brian Reinhold
Brian Reinhold

Reputation: 2475

Using the solutions provided above works but the side effect is that you have to have location services turned on for something that doesn't need it. An ugly and unsatisfying work around is to specify the target version in your manifest to

android:targetSdkVersion="21"

It allows scanning on my Nexus 7 even though the installed version is 6.0.1. I do not know what the side effects are of targeting a lower version than the installed version but at least scanning works. Might be the only solution for GPS-less devices (if such devices exist).

Google should be crucified for this.

Upvotes: 4

aiden_fry
aiden_fry

Reputation: 304

One - not perfect answer, is that you can still use the same old method BT scan method, once you have the new runtime Location permission enabled.

            mBluetoothAdapter.startDiscovery();

.......

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                mDeviceList.add(device);


            }
        }
    };

Upvotes: 0

Kamal Kishore
Kamal Kishore

Reputation: 399

Is you app prompting for Location permission on startup? If it's not, handle the code somewhere else so that it is being prompted.

Also you can check this to test if your app is working fine:

Open Settings > Apps > YourApplication > Permissions and enable Location and then try to scan for results.

Location will be listed under permissions only if you have provided ACCESS_COARSE_LOCATION on manifest.

Upvotes: 10

Related Questions