如何通过蓝牙一起读取所有字节?
我有一个使用蓝牙接收来自其他设备的一些数据(字节)的应用程序。一切进展顺利,但我在收到所有字节时遇到了一个小问题。收到字节后,我会在Toast上显示它们,以便测试它们。当其它设备发送10个字节一起(例如:“ABCDEFGHIJ”),程序将采取的第一个字节的“A”仅,并显示在一个吐司,然后去第二次迭代和读出的其他9个字节,并显示“ BCDEFGHIJ“在吐司上。这里是我的代码:如何通过蓝牙一起读取所有字节?
byte[] buffer = new byte[1024]; // Read 1K character at a time.
int bytes = 0; // Number of bytes.
while(true)
{
try
{
// Read from the InputStream.
bytes = bInStream.read(buffer);
// Send the obtained bytes to the MainActivity.
mainActivityHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
}
catch(IOException e)
{
connectionLost();
break;
}
}
在MainActivity,我有:
// The Handler that gets information back from the BluetoothManager.
private final Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer.
String readMessage = new String(readBuf, 0, msg.arg1);
Toast.makeText(MainActivity.this, readMessage, Toast.LENGTH_SHORT).show();
break;
// ...
}
}
};
我怎样才能收到所有字节在一起?
嗯最有可能的罪魁祸首是在你发送消息的方式。您的接收没有问题,它将接收到写入的字节数(最多1024)。
如果你有在邮件发送你也许可以一次读取一个字节,然后当你打一个预定义的终止给你一个处理消息的方式没有控制。例如:“ABCDEFGHIJ#”,其中#是终结符。
String msg = "";
byte ch;
while((ch=mInStream.read())!='#') {
bytes++;
msg+=ch;
}
+1好的解决方案。我会使用这个解决方案,直到我找到解决问题的另一种方法。谢谢! – 2012-02-10 17:41:28
如果我传输二进制数据会怎么样?我如何确定终止符不是数据流的一部分? – stoefln 2015-05-14 14:49:01
蓝牙连接是基于流的,而不是基于分组。没有保证或试图保持分组化。所以任何数量的写入都会导致任意数量的读取,只是字节流保证是正确的。如果您需要检测数据包,则需要提供自己的数据包结构来包装数据。例如,在每个数据包前添加一个长度字段,以便您可以在接收端进行重构。
+1这也是一个很好的解决方案。谢谢! – 2012-02-10 19:38:39
@TJD我怎么知道长度字段的长度? – stoefln 2015-05-14 14:47:38
处理时间长于缓冲区的信息(可能是危险的,如果从来没有清零,因为会占用你的内存)的一种方法是处理它们在大块:
String inString = "";
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
while (true) {
try {
bytes = mmInStream.read(buffer);
String chunk = new String(buffer, 0, bytes);
if(chunk.contains(";"))
{
inString += chunk.substring(0,chunk.indexOf(';'));
Message msg = new Message();
msg.obj = inString;
handler.sendMessage(msg);
inString = chunk.substring(chunk.indexOf(';'));
}
else
{
inString += chunk;
}
} catch (IOException e) {
break;
}
}
它不能帮助我读取缓冲区内的所有消息 – 2014-08-13 02:58:03
该代码假定';'是消息分隔符。代码是一个示例实现,并且不是通用的 - 你不能复制粘贴它,并期望在没有修改的情况下工作,但是显示了一个背后的概念。它读取所有消息。一旦消息结束,handler.sendMessage(msg);被调用来处理完整的消息,并继续处理缓冲区。您必须实现处理程序来处理/读取消息。这是概念 – 2014-08-13 08:16:24
从@broody接受的答案是正确的。但是,如果数据本身包含'#',则可能难以获取数据。所以,根据我的是附加的最佳方法“\ n”,然后“\ r”(或任何其他字符,这是不太可能拥有数据Refer ASCII Table),其中将数据发送到您的Android应用设备。它只是用作换行并标记数据结束。
如:ABCDEFGH \ n \ r
然后你的代码可以是这样的:
byte[] buffer = new byte[1024];
while (true) {
// Read from the InputStream
buffer[bytes] = (byte) mmInStream.read();
// Send the obtained bytes to the UI Activity
if ((buffer[bytes] == '\n')||(buffer[bytes]=='\r'))
{
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
bytes=0;
}
else
bytes++;
}
希望它可以帮助 问候
**辉煌**!这解决了我的问题,而无需在Arduino端添加额外的'#'字符。我只是跳过了检查'\ r'(我只检查'\ n'),它的作用就像一个魅力。 – 2015-06-12 08:13:36
我可以看到你是如何发送邮件?你在做类似bOutStream.write(“ABCDEFGHIJ” .getBytes()),或者是你写出来的人物之一,在一个时间? – broody 2012-02-10 17:03:11
蓝牙模块连接到arduino,所以我使用arduino软件的串行监视器发送消息。 – 2012-02-10 17:12:37