【问题标题】:Writing data to BluetoothSocket on the UI thread在 UI 线程上将数据写入 BluetoothSocket
【发布时间】:2016-06-10 11:45:37
【问题描述】:

我正在查看来自 Google 的 Bluetooth Chat sample application,他们在 UI 线程上写信给 BluetoothSocketOutputStream。那是对的吗?通常,流会阻塞,直到数据发送出去。

在我的测试中(使用那个应用程序),只要设备足够近,通信就会很及时。当他们走得更远时,连接断开了。这是通过蓝牙发送数据的正确方法吗?我的消息大小将增加 100-500 字节。

【问题讨论】:

  • 你确定他们是在 main(ui) 线程上做的吗? "private class ConnectedThread extends Thread {" 复制自你的 github 链接
  • 当他们走得更远时,连接被断开 - 这是正常行为,Android 根据 RSSI 参数自动处理它,有时使用握手包。有时它在硬件模块上实现,但在驱动程序级别的现代设备中实现。
  • 是的,我确定它在 UI 线程上。从发送按钮的onClick 处理程序调用ConnectedThread.write() 方法。我在调试器中检查了这个。
  • 奥利夫是正确的。虽然写入是在 ConnectedThread 上的方法中执行的,但它不在 run() 方法中,这需要使用单独的线程进行写入。

标签: android android-bluetooth


【解决方案1】:

https://developer.android.com/guide/topics/connectivity/bluetooth#ManageAConnection

当然,还有一些实现细节需要考虑。在 特别是,您应该使用专用线程从 流并写入它。这很重要,因为 read(byte[]) 和 write(byte[]) 方法是阻塞调用。这 read(byte[]) 方法阻塞,直到有东西可以从 溪流。 write(byte[]) 方法通常不会阻塞,但它可以 如果远程设备未调用 read(byte[]),则阻止流控制 足够快,结果中间缓冲区变满。 所以,你在线程中的主循环应该专门用于读取 输入流。线程中的一个单独的公共方法可用于 启动对 OutputStream 的写入。

【讨论】:

    【解决方案2】:

    我也想知道这一点,因为据我所知,BluetoothChat 在 UI 线程上写入蓝牙数据,就像我发现的所有其他 Android 蓝牙示例一样 - 所有这些似乎都基于 BluetoothChat。

    我已经按照 Oliv 所做的方式进行了更多测试。使用运行 4.4.4 的三星 T113,我发现写入 60 个字符串,写入一般需要 12-14ms。但是,在某些情况下,写入需要更长的时间 - 35-45ms。此外,如果正在写入的设备没有读取发送给它的消息,最终发送设备上的缓冲区将被填满,写入操作将无限期阻塞(请参阅Android BluetoothSocket OutputStream write blocks infinitely)。由于这些原因,我认为编写蓝牙的表现良好的应用程序需要在主线程之外执行此操作。

    (根据 Commonsware 的 Mark Murphy 所说,“主应用程序线程上的所有 I/O 都是一个坏主意”,BluetoothChat 使用主线程进行编写“可能只是一个错误。”)

    【讨论】:

    • 感谢您的回答,您已经很好地表明在 UI 线程上写入/读取是一个错误。即使发送少量数据也不能保护您免受这种情况的影响。顺便说一句,我没有完成我的蓝牙应用程序......
    【解决方案3】:

    由于文档没有说明这一点,我做了自己的测试:我尝试发送以下数据量并测量,写入持续多长时间。

            Old Android 2.3 device    Recent Android 5.0 device
    1kB           12ms                       2ms
    4kB         15-20ms                      2ms
    64kB        25-35ms                      7ms
    128kB       10-17ms                      6ms
    256kB     2000-3000ms                   3000ms
    

    由于我将发送小于 1kB 的数量,因此我将在 UI 线程上进行。他们在“官方”示例聊天应用程序中做同样的事情。

    Android 似乎有一些至少 128kB 的内部缓冲区,因此可以编写短消息而无需使用后台线程。

    但是,在另一台设备上读取 128kB 需要一两秒。我使用了 4kB 读取缓冲区。当我逐字节阅读时,可能是一分钟。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-28
      • 1970-01-01
      • 2012-09-03
      • 2015-04-17
      • 2011-06-19
      • 2012-12-09
      • 2020-01-31
      • 1970-01-01
      相关资源
      最近更新 更多