在 UI 线程上将数据写入 BluetoothSocket

Writing data to BluetoothSocket on the UI thread

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

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

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

        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 线程上进行。他们在 "official" 示例聊天应用程序中执行相同的操作。

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

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

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

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

(根据Commonsware的Mark Murphy的说法,"all I/O on the main application thread is a bad idea"和BluetoothChat使用主线程写的是"probably just a bug.")

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

There are, of course, implementation details to consider. In particular, you should use a dedicated thread for reading from the stream and writing to it. This is important because both the read(byte[]) and write(byte[]) methods are blocking calls. The read(byte[]) method blocks until there is something to read from the stream. The write(byte[]) method doesn't usually block, but it can block for flow control if the remote device isn't calling read(byte[]) quickly enough and the intermediate buffers become full as a result. So, your main loop in the thread should be dedicated to reading from the InputStream. A separate public method in the thread can be used to initiate writes to the OutputStream.