我有一个使用蓝牙从其他设备接收一些数据(字节)的应用程序。一切进展顺利,但我在接收所有字节时遇到了一个小问题。收到字节后,我在Toast上显示它们只是为了测试它们。当另一个设备一起发送10个字节时(例如:“ABCDEFGHIJ”),程序将仅采用第一个字节“A”并在Toast上显示,然后转到第二个迭代并读取其他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;
// ...
}
}
};
如何一起收到所有字节?!
答案 0 :(得分:7)
嗯,最有可能的罪魁祸首就在于你发送邮件的方式。您的接收没有问题,它将收到与写入的字节数(最多1024个)。
如果您无法控制消息的发送方式,您可以一次读取一个字节,然后在达到预定义的终结符时发送处理程序消息。例如:“ABCDEFGHIJ#”,其中#是终止符。
String msg = "";
byte ch;
while((ch=mInStream.read())!='#') {
bytes++;
msg+=ch;
}
答案 1 :(得分:5)
蓝牙连接是基于流的,而不是基于数据包的。无法保证或尝试保留打包。因此,任何数量的写入都可以导致任意数量的读取,只保证字节流是正确的。如果需要检测数据包,则需要提供自己的数据包结构来包装数据。例如,在每个数据包之前添加一个长度字段,以便您可以在接收方重建。
答案 2 :(得分:4)
@broody接受的回答是正确的。但如果数据本身包含“#”,则可能很难获取数据。因此,根据我的最佳方法是在设备中附加'\ n'后跟'\ n'(或不太可能作为数据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++;
}
希望它有所帮助 此致
答案 3 :(得分:1)
要一起读取所有字节,您需要在代码中用“\ n”或“\ r”或“\ r \ n”分隔数据。
例如:如果您想通过蓝牙将数据从Arduino发送到Android应用程序:
(Arduino代码):
int count =0;
int sensorPin = 0;
void setup()
{
Serial.begin(9600);
}
void loop()
{
int val= analogRead(sensorPin);
if(val<threshold){
a++;
}
else{
delay(2);
count = count + 1;
Serial.print(count);
Serial.print("\n");
}
现在,要读取发送的数据(变量'count'的值),这里是Android Studio的代码:
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
// Get the input streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream(); // opens the input stream in order to retrieve InputStream objects
} catch (IOException e) {
}
mmInStream = tmpIn;
}
public void run() {
int bytes; // bytes returned from read()
int availableBytes = 0;
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
availableBytes = mmInStream.available();
if(availableBytes>0){
byte[] buffer = new byte[availableBytes]; // buffer store for the stream
// Read from InputStream
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
if (bytes>0){
h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
}
}
} catch (IOException e) {
break;
}
}
}
这个:(在onCreate()方法中):
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
// The Handler that gets information back
h = new Handler() { // Handler-->used to communicate b/w UI & BG Thread
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECEIVE_MESSAGE:// if receive message
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length());// and clear
Toast.makeText(ledControl.this,sbprint,Toast.LENGTH_SHORT).show();
footSteps.setText(sbprint); // update TextView
}
break;
}}};
答案 4 :(得分:0)
以上答案对我都不起作用。 Thread.sleep(1000)给了我解决方案
答案 5 :(得分:-1)
一种处理长于缓冲区消息的方法(可能很危险,因为如果从未清除就会占用你的内存)是以块的形式处理它们:
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;
}
}