7

我需要对周围区域的蓝牙设备进行 6 到 12 秒的扫描。在此之后,我需要停止发现新设备。

以下代码应:

  • 开始扫描蓝牙设备
  • 打印出找到的任何内容
  • 6秒后,取消所有发现并重复过程

问题是蓝牙发现永远不会被取消。这段代码运行一两分钟后,onReceive 将在同一秒内被调用数十次......

public void startTrackingButton(View view) {
        Log.d("MAIN", "Track button pressed, isTracking: " + !isTracking);
        if (isTracking) {
            isTracking = false;
        } else {
            isTracking = true;

            Thread keepScanning = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (isTracking) {
                        if (mBluetoothAdapter.isDiscovering()) {
                            Log.d("MAIN", "Cancelling discovery!");
                            Log.d("MAIN", String.valueOf(mBluetoothAdapter.cancelDiscovery() + ":" + mBluetoothAdapter.getState()));
                            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                        }
                        startTracking();
                        try {
                            Thread.sleep(6000);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            });
            keepScanning.start();
        }
    }

private void startTracking() {

    Log.d("MAIN", "Starting Discovery...");
    mBluetoothAdapter.startDiscovery();
    // Create a BroadcastReceiver for ACTION_FOUND
    BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            Log.d("MAIN", "Device Found...");
            String action = intent.getAction();
            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device = intent
                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // Add the name and address to an array adapter to show in a
                // ListView
                Log.d("MAIN:",
                        device.getName() + "\n" + device.getAddress());
            }
        }
    };

    // Register the BroadcastReceiver
    IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
    registerReceiver(mReceiver, filter); // Don't forget to unregister
                                            // during onDestroy
}

这是我的 logcat 输出:

//onReceive gets called many times in the same second???
05-01 22:09:56.949: D/MAIN(3757): Cancelling discovery!
05-01 22:09:56.969: D/MAIN(3757): false:12              ///THIS SHOULD BE TRUE
05-01 22:09:56.969: D/MAIN(3757): Starting Discovery...
05-01 22:10:03.009: D/MAIN(3757): Starting Discovery...
05-01 22:10:03.579: D/MAIN(3757): Device Found...
05-01 22:10:03.579: D/MAIN:(3757): TOMSELLECK
05-01 22:10:03.579: D/MAIN:(3757): 06:07:08:09:A1:A1
05-01 22:10:03.579: D/MAIN(3757): Device Found...
05-01 22:10:03.579: D/MAIN:(3757): TOMSELLECK
05-01 22:10:03.579: D/MAIN:(3757): 06:07:08:09:A1:A1
05-01 22:10:03.589: D/MAIN(3757): Device Found...
05-01 22:10:03.589: D/MAIN:(3757): TOMSELLECK
05-01 22:10:03.589: D/MAIN:(3757): 06:07:08:09:A1:A1
05-01 22:10:03.589: D/MAIN(3757): Device Found...
05-01 22:10:03.589: D/MAIN:(3757): TOMSELLECK
05-01 22:10:03.589: D/MAIN:(3757): 06:07:08:09:A1:A1
05-01 22:10:03.589: D/MAIN(3757): Device Found...
05-01 22:10:03.589: D/MAIN:(3757): TOMSELLECK
05-01 22:10:03.589: D/MAIN:(3757): 06:07:08:09:A1:A1

有人知道我如何正确取消所有当前和未决的蓝牙发现吗?

谢谢你的帮助!

PS 我需要重复该过程的原因是从附近的设备获取新的信号强度值。

4

2 回答 2

8

每次调用时startTracking(),您都会创建并注册另一个BroadcastReceiver。因此,在您呼叫startTracking()十次之后,您有十个接收器在等待设备。找到设备后,所有这些接收器都会收到通知,这就解释了为什么您会收到如此多的日志条目。

关于cancelDiscovery返回false,Android的蓝牙代码可能是它最有漏洞的部分。看看我发现了什么。永远不要假设任何与 Android 上的蓝牙相关的东西都可以在不同的版本和设备上正常工作。出于调试目的,您可以为BluetoothAdapter.ACTION_DISCOVERY_FINISHED. 取消后可能isDiscovering()会返回 false,但我可以想象取消请求和isDiscovering()返回 false 之间会有短暂的延迟。

您的个人错误建议遇到此错误的客户还喜欢:

  • 某些设备会忽略EXTRA_DISCOVERABLE_DURATION并且只能启用 120 秒的可发现性。这应该由 2.3.6 修复,但我看到它发生在带有 2.3.6 的三星 Galaxy Ace 上,所以三星可能破坏了它,或者它根本没有修复。但不会发生在我的 4.x 设备上。
  • 如果您实际创建连接,某些 Android 版本即使在不安全的连接上也会导致配对对话框。尝试连接到 4.2 上的未知服务也会这样做
  • 有时,蓝牙只是中断,导致无法连接,直到重新启动(可能与应用程序崩溃或在测试期间被杀死时没有干净地关闭连接有关,我的直觉是它耗尽了某种文件描述符样式资源)。
  • 服务发现可能不可靠

另请注意:由于您使用Thread.sleep,线程可能会暂停超过 6 秒的实时时间,因为Thread.sleep当 CPU 睡眠时停止测量时间。根据扫描时设备的行为方式,这可能会超过6 秒。如果你想使用基于实时的计时,你将不得不使用一个 AlarmManager,不幸的是这很麻烦——你可能想为它写一个瘦包装器。

于 2013-05-05T12:49:28.067 回答
2

我不建议取消发现。这在 Android 中是错误的。在我拥有的 Nexus 4 上,取消有时会导致蓝牙被禁用,直到重新启动,在某些最坏的情况下,直到恢复出厂设置。我建议让发现完成,然后在它结束后立即重新启动。

无论如何,发现并不需要很长时间,尽管它会根据发现期间看到的设备数量而有所不同。这是使用 8 台设备进行的扫描:

05-07 16:47:53.655: I/MANAGER:BluetoothManager(22019): Bluetooth Discovery Starting...
05-07 16:48:13.687: I/MANAGER:BluetoothManager(22019): Bluetooth Discovery Finished...

请注意,如果您一直运行发现,您将很快耗尽电池电量。

于 2013-05-08T00:13:36.370 回答