Android 7.0 ble scan no result

2019-02-19 00:59发布

问题:

When I start ble(Bluetooth Le) scan for seconds, then stop scan. Then start, then stop... after about 5-8 Loops, the start action will be No effect ,this means no scan record can be received. 1.This condition only appears on Android 7.0 or above(7.1.1); 2.I have tried two scan method: BluetoothAdapter.startLeScan() and Scanner.startScan(), no difference .

private void scanToggle(final boolean enable) {
    mScanHandler.removeCallbacks(scanTask);
    if (enable) {
        TelinkLog.i("ADV#scanner#startScan");
        scanner = mBluetoothAdapter.getBluetoothLeScanner();
        scanner.startScan(null, settings, scanCallback);
        mScanning = true;
        mDeviceList.clear();
        mListAdapter.notifyDataSetChanged();
       //mBluetoothAdapter.startLeScan(leScanCallback);
        mScanHandler.postDelayed(scanTask, SCAN_PERIOD);
    } else {
        TelinkLog.i("ADV#scanToggle#stopScan");
        mScanning = false;
        //mBluetoothAdapter.stopLeScan(leScanCallback);
        scanner.stopScan(scanCallback);
    }
    invalidateOptionsMenu();
}


private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
        TelinkLog.d("scan:" + device.getName());
        for (AdvDevice advDevice : mDeviceList) {
            if (device.getAddress().equals(advDevice.device.getAddress())) return;
        }
        mDeviceList.add(new AdvDevice(device, rssi, scanRecord));
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mListAdapter.notifyDataSetChanged();
            }
        });
    }
};

private ScanCallback scanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);
        for (AdvDevice advDevice : mDeviceList) {
            if (result.getDevice().getAddress().equals(advDevice.device.getAddress())) return;
        }
        mDeviceList.add(new AdvDevice(result.getDevice(), result.getRssi(), result.getScanRecord().getBytes()));
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mListAdapter.notifyDataSetChanged();
            }
        });
    }

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

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

回答1:

You are probably running into the new and undocumented behavior changes in Android 7 that prevent apps from scanning too often.

I wrote a blog post about it: https://blog.classycode.com/undocumented-android-7-ble-behavior-changes-d1a9bd87d983



回答2:

I had also this kind of problem. It is solved by enabling Location. In android, we need to enable Location for scan near by devices. So please check location is enable or not. Below code is useful. I hope it works, in my case it works good.

LocationManager manager = (LocationManager) mainActivity.getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    buildAlertMessageNoGps(mainActivity);
}else{ //scanning part}


public void  buildAlertMessageNoGps(MainActivity mainActivity){
    final AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
    builder.setMessage("Your GPS seems to be disabled, do you want to enable it? It is required for this application.")
            .setCancelable(false)
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, final int id) {
                    mainActivity.startActivityForResult(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS), MainActivity.LOCATION_ENABLE);
                }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, final int id) {
                    dialog.cancel();
                    mainActivity.finishAffinity();
                }
            });
    final AlertDialog alert = builder.create();
    alert.show();
}

After on location start scanning and get scanning result.



回答3:

You need to make sure that you stop and re-start your scan only after 6 seconds for all devices with Android N and above.

This is as per the introduced restriction where apps are allowed to scan a maximum of 5 times in 30 seconds.

We’ve changed the BLE Scanning behavior starting in DP4. We’ll prevent applications from starting and stopping scans more than 5 times in 30 seconds. For long running scans, we’ll convert them into opportunistic scans.

Refer to this discussion here



回答4:

You will also have to include location permissions in your Manifest or else your search will not return anything. This is mandatory i would say for Bluetooth and Wifi searches.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

As the in the develoepr section for BLE in Android.