Bluetooth data sometimes corrupted

  • Antworten:11
  • OffenNicht stickyBentwortet

14.03.2012 16:48:59 via Website

hi,

i implemented an app that connects to an bluetooth device and collects data from the device.
The device sends data all 100 ms and faster. Most of the time all data received is correct but sometimes it is corrupted(the end of the data is copied in the middle of the data...) i tryed a lot and recogniced that this problem comes up more often when i'm debuging und the device.

doese someone know whats happening there?

my code:

private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;

public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
//ParcelUuid[] uuids = servicesFromDevice(device);

Method m = null;
try {
m = device.getClass().getMethod("createInsecureRfcommSocket",
new Class[] { int.class });
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
tmp = (BluetoothSocket)m.invoke(device, Integer.valueOf(1));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/* try {
tmp = device.createRfcommSocketToServiceRecord(my_uuid);
//Log.d(TAG, "uuids.length: "+ uuids.length);
//Log.d(TAG, "uuid: " + uuids[1].getUuid());
//tmp = device.createRfcommSocketToServiceRecord(uuids[0].getUuid());
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + "create() failed",e);
}*/
mmSocket = tmp;
}

public void run() {
Log.i(TAG, "BEGIN mConnectThread SocketType:" );
setName("ConnectThread" );

// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();

// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
run=true;
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " +
" socket during connection failure", e2);
}
Log.e(TAG, e.getMessage());
connectionFailed();
return;
}

// Reset the ConnectThread because we're done
synchronized (connection.this) {
mConnectThread = null;
}

// Start the connected thread
connected(mmSocket, mmDevice);
}

public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect " + " socket failed", e);
}
}
}

/**
* This thread runs during a connection with a remote device.
* It handles all incoming and outgoing transmissions.
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;

public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread: ");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;

// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}

mmInStream = tmpIn;
mmOutStream = tmpOut;
}




public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
int cnt=0;
String help="";
// Keep listening to the InputStream while connected
Log.i(TAG, "ConnectedThread run= "+ run);
while (run) {
try {
cnt++;
//Log.i(TAG, ""+cnt);
//Log.i(TAG, "Read from InputStream");
// Read from the InputStream
bytes = mmInStream.read(buffer);
Log.i(TAG, "data received: "+ bytes+ " bytes");
// Send the obtained bytes to the UI Activity
//recBytes=bytes;
//recData=buffer;
/*for (int i=0;i<bytes;i++)
{
help=help+" "+(int)buffer[i];
}
Log.i(TAG, help);
help="";*/
//Log.i(TAG,"timestamp: "+ ((((int)buffer[3]&0xFF)<<8)+((int)buffer[4]&0xFF)));
//mHandler.obtainMessage(main.MESSAGE_READ, 0, -1, "")
//.sendToTarget();
mHandler.obtainMessage(main.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
//connectionLost();
// Start the service over to restart listening mode
//connection.this.start();
break;
}
}

}

/**
* Write to the connected OutStream.
* @param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);

// Share the sent message back to the UI Activity
/* mHandler.obtainMessage(main.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();*/
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}

public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
}


would be nice if someone can help me =)

14.03.2012 17:14:39 via Website

if you are truly process your sendings in a transactional manner it should not be possible - but maybe there is a problem - you can also check your sending buffers (if you use them) maybe they get overwritten - or flushing the stream ..

sorry, there are very many possibilities which is hard to figure out because many people use different approaches to do networking

— geändert am 14.03.2012 17:15:01

15.03.2012 13:12:53 via Website

ok i found the error.

the bluetooth sent some data as fast that the handler message couldn#t send as quick so the data was overwritten and i lost some data.
solved the problem witch a Callback methode

27.03.2012 15:22:52 via Website

Hello Alex,

i have the same problem, data seen sometime lost or overwritten.

i have now an callback for writing:

1public interface MyCallback
2{
3 public void callbackCall(OutputStream outStream, byte[] buffer);
4}


1public class Callback implements MyCallback {
2 private static final String TAG = "Callback";
3
4 public void callbackCall(OutputStream outStream, byte[] buffer) {
5 try {
6 outStream.write(buffer);
7 } catch (IOException e) {
8 Log.e(TAG, "Exception during write", e);
9 }
10 }
11}

and in my bluetooth send service i do this:

1public void write(byte[] buffer) {
2 callback = new Callback();
3 callback.callbackCall(mmOutStream, buffer);
4
5 }

but i have still the problem, that the buffer seems to be overwritten..

has anybody an idea what can it be?

the rest of the code is like the Bluetooth chat exsample.

Sending is in an extra thread. i think i camm the send funktion to often, so that the buffer is not jet send. how can i solve this problem? has anybody an idea?

thanks

i think i found the problem:
http://stackoverflow.com/questions/9270965/bluetooth-spp-receive-some-the-package-frame-can-lost-or

— geändert am 27.03.2012 15:31:51

27.03.2012 15:48:04 via Website

well i never had problems while sending data only while receiving.

but here is the code how i solved my problem:

part of the read methode where i call the callback:
try {

bytes = mmInStream.read(buffer);

if (connection.btCallback != null)
{
connection.btCallback.getData(buffer,bytes);
}
}

Callback:
public interface BTCallback
{
public abstract void getData(byte[] bytes, int len);
}

part of my main activity whitch implements the BTCallback:
public void getData(byte[] bytes, int len)
{
// do something with the data
}

28.03.2012 09:57:23 via Website

i have traced out now direct after reading the input stream:

1bytes = mmInStream.read(buffer);
2 String readMessage = new String(buffer, 0, bytes);
3 if (D) Log.v(TAG, "readMessage:" + readMessage );

and direcly before writing in the send service:

1String writeMessage = new String(buffer, 0, bytes);
2 Log.v(TAG, String.valueOf(bytes) + " writeMessage:" + writeMessage );
3 outStream.write(buffer);

writing seens to be ok, but when i get the input stream, it seems to be corrupted :-(

but i think i can not solve it with a callback, because it is to late at this point, the data is already overwriten :-(

is that someting with overlapping?

— geändert am 28.03.2012 09:58:10

28.03.2012 10:14:32 via Website

with one app i only send and with the other app i only read.

ah ok i have an idea... maybe this is the problem, maybe i have to use different output streams vor different send events...

i will try to seperate the output buffer and test this...

ok, thats not possible...

— geändert am 28.03.2012 10:33:06

28.03.2012 11:00:18 via Website

now i inserted

Thread.sleep(20);
and
mmOutStream.flush();

after
outStream.write(buffer);

it looks like this:
1outStream.write(buffer);
2Thread.sleep(20);
3mmOutStream.flush();

now the recieving seems ok, not perfect but usable...


but now the ui thread from sending hangs and not react and after short time and ANR occures :-(

If i change to Thread.sleep(5) then i have no ANR but the recieveing stream is corrupted again.

maybe i send to much data for bluetooth... or maybe to often....
maybe i have the chance to fill a biger buffer first with more then one message and at the recieve side i seperate the messages first.

— geändert am 28.03.2012 13:59:01

29.03.2012 09:44:27 via Website

I solved my problem, with building a bigger message buffer, i put 10 of my normal messages (nearly 100 byte) to a big message and send then the message.

at recieving side i parse the big message to the single messages, and now i have no read write errors...

i think bluetooth is optimized for biger data messages, so the transfer rate for lot of short messages is very low.

PS: to check the integrity of the recieved message, i genaret the md5 checksum at sending ang put it to the message, and at recieving i can check if the message is recived as i send it.

thanks for your help