无法取消蓝牙发现过程

问题描述:

我需要在周围区域扫描蓝牙设备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我需要重复该过程的原因是从附近的设备获取新的信号强度值。

每当您拨打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,由Thread.sleep停止测量时的CPU休眠线程可能会暂停的实时超过6秒,因为时间。根据设备在扫描时的行为方式,这可能是多了多于6秒。如果你想使用基于实时的时间,你将不得不使用一个AlarmManager,这不幸是一个pain in the ass - 你可能会想写一个薄包装。

我不建议取消发现。这是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... 

请注意,如果你运行发现所有的时间,你会非常快耗尽电池。