无法取消蓝牙发现过程

时间:2013-05-01 21:21:42

标签: android bluetooth android-broadcast

我需要在周围区域扫描蓝牙设备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

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

感谢您的帮助!

P.S我需要重复这个过程的原因是从附近的设备获得新的信号强度值。

2 个答案:

答案 0 :(得分:8)

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

关于cancelDiscovery返回false,Android的蓝牙代码可能是其中最多的错误部分。 Look what I found。永远不要假设任何与Android上的蓝牙相关的内容都能在不同版本和设备上正常运行出于调试目的,您可以为BluetoothAdapter.ACTION_DISCOVERY_FINISHED添加侦听器。取消后,isDiscovering()可能会返回false,但我可以想象取消请求和isDiscovering()返回false之间会有短暂的延迟。

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

  • 某些设备会忽略EXTRA_DISCOVERABLE_DURATION,并且只能启用120秒的可发现性。这应该由2.3.6修复,但我看到它发生在2.3.6的三星Galaxy Ace上,所以也许三星打破它或者它毕竟没有修复。但是我的4.x设备上不会发生这种情况。
  • 如果您实际创建连接,某些Android版本将导致pairing dialogs even on insecure connections。尝试在4.2 will do this上连接到未知服务。
  • 有时候,蓝牙只会中断,直到重新启动才能连接(可能与应用程序崩溃或在测试期间被杀死时没有干净地关闭连接有关,我的直觉是它用完了某种文件 - 描述符风格的资源)。
  • 服务发现may be unreliable

另请注意:由于您使用Thread.sleep,因此线程可能暂停超过6秒的实时,因为Thread.sleep测量的时间会在CPU休眠时停止。根据设备在扫描时的行为方式,这可能超过6秒。如果你想使用基于实时的计时,你将不得不使用AlarmManager,不幸的是它是pain in the ass - 你可能想要为它编写一个薄的包装器。

答案 1 :(得分: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...

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