【问题标题】:Android Bluetooth LE Scan how to check if device is out of range?Android蓝牙LE扫描如何检查设备是否超出范围?
【发布时间】:2020-05-06 16:40:04
【问题描述】:

我使用BluetoothLeScannerstartScan 方法遇到了问题,找到了一个BLE 设备,但是当我关闭BLE 设备时,我的手机仍然显示此设备已打开!!

我试过用:

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 {
            ...
        }
    }
    ...
};

伙计,我还没有找到解决方案如何检测 BLE 设备在其他资源中丢失,例如(Android SDK 参考、论坛、stackoverflow 等)(:

任何帮助将不胜感激!

【问题讨论】:

标签: android bluetooth bluetooth-lowenergy


【解决方案1】:

在谷歌搜索和探索 Android 文档期间,我想出了如何检测设备是否超出范围。我想分享我的解决方案:

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

解释:

  1. 如您所见,我在每个扫描周期都添加了mInRangeBtDevices 集合,该集合将保留当前扫描期间找到的所有设备。
  2. 当我停止扫描时,我还会使用一个额外的帮助程序集合outOfRangeDevices 从以前的列表中删除不再可用的超出范围的设备

我认为这个例子会很有用,你可以将它集成到你自己的代码中

【讨论】:

    【解决方案2】:

    这个one 看起来不错(JAVA):

    据我了解,您需要实现 startLeScan()。

    查找 BLE 设备

    要查找 BLE 设备,请使用 startLeScan() 方法。此方法将 BluetoothAdapter.LeScanCallback 作为参数。您必须实现此回调,因为这是返回扫描结果的方式。由于扫描会消耗大量电量,因此您应遵守以下准则:

    找到所需设备后,立即停止扫描。 切勿循环扫描,并为扫描设置时间限制。以前可用的设备可能已超出范围,继续扫描会耗尽电池电量。 以下 sn -p 显示了如何开始和停止扫描:

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

    考虑检查this 教程。 还有this一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-04
      • 2015-02-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 1970-01-01
      • 1970-01-01
      • 2015-06-08
      相关资源
      最近更新 更多