1

我正在尝试从蓝牙模块扫描、连接和接收数据。如果我只使用 android 应用程序,一切正常。我可以扫描并找到附近的所有设备,连接到任何人(我只对我的蓝牙模块感兴趣)并且我能够读取从蓝牙模块发送的测试数据。

问题是应用程序是使用 Flutter 开发的。我在我的 Android 应用程序中使用了相同的代码,并通过 EventsChannel 将其与 Dart 链接,但现在我只能在 Flutter 应用程序中看到更少的蓝牙设备,而且它们都不是我感兴趣的蓝牙模块。我是新手Flutter 和特定于平台的编码,我无法理解为什么相同的代码在相同硬件上的不同应用程序中表现不同。

我已经在三星 S4 和 S8 手机上测试了我的代码,结果是一样的。

这是发现部分的 EventChannel 的代码:

new EventChannel(flutterEngine.getDartExecutor(), DISCOVER_CHANNEL).setStreamHandler(
        new EventChannel.StreamHandler() {
          @Override
          public void onListen(Object args, EventChannel.EventSink events) {
            Log.w(TAG, "Registering receiver");
            discoverReceiver = DiscoverReceiver(events);
            IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            registerReceiver(discoverReceiver, filter);
          }

          @Override
          public void onCancel(Object args) {
            Log.w(TAG, "Unregistering receiver");
            unregisterReceiver(discoverReceiver);
            discoverReceiver = null;
          }
        }
);

现在我的discoverReceiver 是一个全局BroadcastReceiver。以下是广播接收器的代码:

private BroadcastReceiver DiscoverReceiver(final EventSink events) {
  return new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if (BluetoothDevice.ACTION_FOUND.equals(action)) {
        // Discovery has found a device. Get the BluetoothDevice
        // object and its info from the Intent.
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        String deviceName = device.getName();

        if (deviceName == null){
          deviceName = "No Device Name";
        }

        events.success(deviceName);
        Log.w(TAG, "Sending " + deviceName);
      } 
    }
  };
}

**我使用 (Log.w(TAG, "Sending " + deviceName);) 语句查看事件是否丢失/丢弃。以下是我在 Dart 中接收它的方式:

@override
  void initState() {
    super.initState();
    devices.add(selectDevice);
    discoverChannel.receiveBroadcastStream().listen(onEvent);
  }

  void onEvent(Object event) {
    setState(() {
      devices.add(event);
    });
  }

以下是我的 Android 应用程序中的代码,它可以扫描并查找所有设备,以防您想与上述设备进行比较:

private BroadcastReceiver DiscoverReceiver() {
    return new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            // Discovery has found a device. Get the BluetoothDevice
            // object and its info from the Intent.
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            String deviceName = device.getName();

            if (deviceName == null){
                deviceName = "No Device Name";
            }
            devicelist.add(device);
            devNames.add(deviceName);
            arrayAdapter.add(deviceName);
            arrayAdapter.notifyDataSetChanged();
            Log.w(TAG, "Sending " + deviceName);
            }
        }
    };
}

我不关心最后一个片段,但我只是想我会展示完整的流程。Snippet 2 是我在独立 Android 应用程序中的副本,它会扫描并查找所有设备,但是一旦我在 Flutter 应用程序中将它用作 Android 的本机代码,它就会停止查找相同数量的设备,仍然可以找到一些虽然并且非常不可靠。

我已经尝试了大多数 Flutter 蓝牙包,但没有一个是我想要的,所以我最终选择了特定于平台的代码,它在插入 Flutter 之前运行良好。我已经阅读了 Android 开发的文档,上面的代码大部分是来自 Android 示例的修改代码。我只是想不通为什么相同的代码可以找到更多设备作为独立应用程序而不是使用它作为颤振应用程序的本机代码,如果最后它在相同的硬件上进行测试。

任何输入将不胜感激!

4

1 回答 1

0

好的,所以我终于找到了解决方案。这与蓝牙的 startDiscovery() 运行并正常工作有关,但稍后会捕获事件,这是调试器无法显示的。

所以在我的例子中,所有设备都被“发现”了,但颤振应用程序稍后开始捕获事件,所以它只显示在发现过程中发现的最后 1 或 2 个设备。

我搬家了:

discoverChannel.receiveBroadcastStream().listen(onEvent);

从 initState() 到按下按钮后调用的函数,确保在注册本机端的广播接收器和 Dart 的广播流接收器之前所有内容都已加载。

我仍然不确定如何表达这一点,但它是关于在本机端注册 BroadcastReceiver 和在 Dart 端注册 receiveBroadcastStream 的时间。

现在它开始发现并正确捕获事件,这显示了在 Android 独立应用程序中找到的相同数量的设备。

希望这对将来可能面临这个奇怪问题的人有所帮助。

于 2020-05-06T21:27:47.327 回答