【问题标题】:Android 7.0 ble scan no resultAndroid 7.0 ble扫描无结果
【发布时间】:2017-03-30 10:16:45
【问题描述】:

当我开始 ble(Bluetooth Le) 扫描几秒钟,然后停止扫描。然后开始,然后停止... 大约 5-8 次 Loops 后,开始动作将是 No effect ,这意味着无法接收到扫描记录。 1.此情况只出现在Android 7.0或以上(7.1.1); 2.我试过两种扫描方法:BluetoothAdapter.startLeScan()和Scanner.startScan(),没有区别。

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);
    }
};

【问题讨论】:

标签: android bluetooth-lowenergy android-7.0-nougat


【解决方案1】:

您可能会遇到 Android 7 中新的且未记录的行为更改,这些更改会阻止应用过于频繁地扫描。

我写了一篇关于它的博客文章: https://blog.classycode.com/undocumented-android-7-ble-behavior-changes-d1a9bd87d983

【讨论】:

    【解决方案2】:

    我也遇到过这种问题。它通过启用位置来解决。在 android 中,我们需要启用 Location 以在设备附近进行扫描。所以请检查位置是否启用。下面的代码很有用。我希望它有效,就我而言它运作良好。

    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();
    }
    

    定位后开始扫描并获得扫描结果。

    【讨论】:

    • 谢谢回复。但是我在打开的位置进行了测试。
    • 这是一种可能的原因,但在 Android 7 上,其他因素可能会发挥作用。在下面查看我的答案,也许您就是这种情况。
    • 你会在 Logcat 中看到这个:java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results。我不知道GPS_PROVIDER 在这里是否是正确的权限......开始bt 扫描看起来有点矫枉过正?和无证...
    【解决方案3】:

    对于所有搭载 Android N 及更高版本的设备,您需要确保仅在 6 秒后停止并重新开始扫描。

    这是根据引入的限制,即允许应用在 30 秒内最多扫描 5 次。

    我们从 DP4 开始更改了 BLE 扫描行为。我们会阻止 应用程序在 30 次中启动和停止扫描超过 5 次 秒。对于长时间运行的扫描,我们会将它们转换为机会性扫描 扫描。

    参考这个讨论here

    【讨论】:

      【解决方案4】:

      您还必须在您的清单中包含location permissions,否则您的搜索将不会返回任何内容。对于BluetoothWifi 搜索,这是强制性的。

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

      在 Android BLE 的开发者部分。

      【讨论】: