Android bluetooth communication with Arduino - java

I am currently looking at Google's Bluetooth Chat example. The goal is to get communication between android and and Arduino working based on this example.
While communication from the smartphone to the Arduino is working great, the other direction does not:
When sending bytes from the Arduino to the smartphone, the following code is used for receiving:
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
This has the following problems:
In my main activity, I get a handed a byte array that's always 1024 bytes long. No matter what the incoming byte length was. It would be really nice, if I had an idication how many bytes were received.
The bytes seem not to get read all at once. E.g. the code above is called multiple times, but the buffer NEVER contains all the bytes I sent from the Arduino. SOmetimes there is only the first bytes, then later only the last bytes.
Although this code is calles multiple times, my main activity gets only notified once. How can that be?
What is the right way to do this. Should one implement a mechanism that collects and concatenates the bytes? Or am I using this code the wrong way?

I always had trouble reading a byte buffer greater than one at a time. This is because there is no way to guarantee that you received all the bytes correctly. My work around was to call read repeatedly one byte at a time and fill out my buffer. That way if any of my bytes aren't read ill catch that in the I/O catch part of my connectedThread and can choose to deal with it however I want.
Sample connectedThread
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
// You can define this buffer to be 1024 or anything you like
buffer = new byte[3];
mmOutStream.write(253);
bytes = mmInStream.read(buffer,0,1);
mmOutStream.write(254);
bytes = mmInStream.read(buffer,1,1);
mmOutStream.write(255);
bytes = mmInStream.read(buffer,2,1);
mHandler.obtainMessage(MESSAGE_READ, buffer).sendToTarget();
}
catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
}
In this case I used a unsigned byte array to represent integers from 0-255. Furthermore I used values 255-253 as commands to tell my Arduino to send me certain types of information. You do not have to set any value to represent a command to arduino, instead you can just tell the arduino to loop through values it needs to send each time it receives a request for information. I found out this is one of the only ways to can confirm the amounts of bytes you received(i.e the size of your byte[] buffer).Although in this case I did not put anything in my catch statement for the connectedThread you could put a read command in there to confirm you receive a byte.
Message Handler
Here is how I dealt with the readBuffer...
/*
* Bluetooth Handler Method
*/
ConnectedThread connectedThread;
Handler mHandler = new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
switch(msg.what){
case SUCCESS_CONNECT:
// Do Something;
Toast.makeText(getActivity(),"CONNECTED",Toast.LENGTH_SHORT).show();
connectedThread = new ConnectedThread((BluetoothSocket)msg.obj);
listView.setVisibility(View.GONE);
connectedThread.start();
break;
case MESSAGE_READ:
byte[] readBuf = (byte[])msg.obj;
int tempInt = byteToInt(readBuf[0]);
int speedInt = byteToInt(readBuf[1]);
int cadenceInt = byteToInt(readBuf[2]);
EditText temperatureData = (EditText)getActivity().findViewById(R.id.temperatureData);
temperatureData.setText(Integer.toString(tempInt) + " C" );
EditText cadenceData = (EditText)getActivity().findViewById(R.id.cadence);
cadenceData.setText(Integer.toString(cadenceInt) + " rpm");
EditText speedData = (EditText)getActivity().findViewById(R.id.speed_data);
speedData.setText(Integer.toString(speedInt) + " kph");
}
}
};
In this case I was displaying live sensor data on my phone. But you can do anything really.
Hope that helped.

Related

Send int on socket as byte[] then recast to int not works

I'm trying to serialize Object between NIO SocketChannel and blocking IO Socket. Since I can't use Serializable/writeObject on NIO, I thought to write code to serialize object into an ByteArrayOutputStream then send array length followed by array.
Sender function is
public void writeObject(Object obj) throws IOException{
ByteArrayOutputStream serializedObj = new ByteArrayOutputStream();
ObjectOutputStream writer = new ObjectOutputStream(serializedObj);
writer.writeUnshared(obj);
ByteBuffer size = ByteBuffer.allocate(4).putInt(serializedObj.toByteArray().length);
this.getSocket().write(size);
this.getSocket().write(ByteBuffer.wrap(serializedObj.toByteArray()));
}
and receiver is:
public Object readObject(){
try {
//Leggi dimensione totale pacchetto
byte[] dimension = new byte[4];
int byteRead = 0;
while(byteRead < 4) {
byteRead += this.getInputStream().read(dimension, byteRead, 4 - byteRead);
}
int size = ByteBuffer.wrap(dimension).getInt(); /* (*) */
System.out.println(size);
byte[] object = new byte[size];
while(size > 0){
size -= this.getInputStream().read(object);
}
InputStream in = new ByteArrayInputStream(object, 0, object.length);
ObjectInputStream ois = new ObjectInputStream(in);
Object res = ois.readUnshared();
ois.close();
return res;
} catch (IOException | ClassNotFoundException e) {
return null;
}
}
The problem is that size (*) is always equals to -1393754107 when serializedObj.toByteArray().length in my test is 316.
I don't understand why casting not works properly.
this.getSocket().write(size);
this.getSocket().write(ByteBuffer.wrap(serializedObj.toByteArray()));
If the result of getSocket() is a SocketChannel in non-blocking mode, the problem is here. You aren't checking the result of write(). In non-blocking mode it can write less than the number of bytes remaining in the ByteBuffer; indeed it can write zero bytes.
So youu aren't writing all the data you think you're writing, so the other end overruns and reads the next length word as part of the data being written, and reads part of the next data as the next length word, and gets a wrong answer. I'm surprised it didn't barf earlier. In fact it probably did, but your deplorable practice of ignoring IOExceptions masked it. Don't do that. Log them.
So you need to loop until all requested data has been written, and if any write() returns zero you need to select on OP_WRITE until it fires, which adds a considerable complication into your code as you have to return to the select loop while remembering that there is an outstanding ByteBuffer with data remaining to be written. And when you get the OP_WRITE and the writes complete you have to deregister interest in OP_WRITE, as it's only of interest after a write() has returned zero.
NB There is no casting in your code.
The problem was write() returned 0 always. This happens because the buffer wasn't flipped before write().

ServerSocket while not breaks on image data inputstream

I tried to send an image from One device to other Device using Bluetooth.For that I take Android Bluetooth chat application source code and it works fine when I send String.But If i send image as byte array the while loop not breaks or EOF not reached when read from Inputstream.
Model:1
It receives image properly.But here I need to pass resultByteArray length.But I dont know the length.How to know the length of byte array in inputstream? inputstream.available() returns 0.
while(true)
{
byte[] resultByteArray = new byte[150827];
DataInputStream dataInputStream = new DataInputStream(mmInStream);
dataInputStream.readFully(resultByteArray);
mHandler.obtainMessage(AppConstants.MESSAGE_READ, dataInputStream.available(),-1, resultByteArray).sendToTarget();
}
Model:2
In this code while loop not breaks,
ByteArrayOutputStream bao = new ByteArrayOutputStream();
byte[] resultByteArray = new byte[1024];
int bytesRead;
while ((bytesRead = mmInStream.read(resultByteArray)) != -1) {
Log.i("BTTest1", "bytesRead=>"+bytesRead);
bao.write(resultByteArray,0,bytesRead);
}
final byte[] data = bao.toByteArray();
Also tried byte[] resultByteArray = IOUtils.toByteArray(mmInStream);but it also not works.I followed Bluetooth chat sample.
How to solve this issue?
As noted in the comment, the server needs to put the length of image at front of the actual image data. And the length of the image length information should be fixed like 4 bytes.
Then in the while loop, you need to get 4 bytes first to figure out the length of the image. After that, read bytes of the exact length from the input stream. That is the actual image.
The while loop doesn't need to break during the connection is alive. Actually it needs to wait another image data in the same while loop. The InputStream.read() is a blocking function and the thread will be sleeping until it receives enough data from the input stream.
And then you can expect another 4 bytes right after the previous image data as a start of another image.
while(true) {
try {
// Get the length first
byte[] bytesLengthOfImage = new byte[4];
mmInStream.read(bytesLengthOfImage);
int lengthOfImage = 0;
{
ByteBuffer buffer = ByteBuffer.wrap(bytesLengthOfImage);
buffer.order(ByteOrder.BIG_ENDIAN); // Assume it is network byte order.
lengthOfImage = buffer.getInt();
}
byte[] actualImage = new byte[lengthOfImage]; // Mind the memory allocation.
mmInStream.read(actualImage);
mHandler.obtainMessage(AppConstants.MESSAGE_READ, lengthOfImage,-1, actualImage).sendToTarget();
} catch (Exception e) {
if(e instanceof IOException) {
// If the connection is closed, break the loop.
break;
}
else {
// Handle errors
break;
}
}
}
This is a kind of simplified communication protocol. There is an open source framework for easy protocol implementation, called NFCommunicator.
https://github.com/Neofect/NFCommunicator
It might be an over specificiation for a simple project, but is worth a look.

Bluetooth transfer App stops after using InputStream.read() with no error

I am trying to make a file transfer Bluetooth app work using these sources:
http://developer.android.com/guide/topics/connectivity/bluetooth.html
https://android.googlesource.com/platform/development/+/25b6aed7b2e01ce7bdc0dfa1a79eaf009ad178fe/samples/BluetoothChat/
When I attempt to get the InputStream bytes using InputStream.read() method this way:
public class ConnectedThread extends Thread {
...(some code here)
public void run(){
byte[] buffer = new byte[1024];
int bytes = -1;
//Keep listening to the InputStream while connected
while (true){
try {
bytes = this.mmInStream.read(buffer);
//* this part is not reached
if (bytes==-1){
Log.d("NoData:","-1");
}
}
catch(Exception e){
Log.d("inStream exception:",e.getMessage());
break;
}
}
}
...(some code here)
}
The next part of the code ("if" part in this case) is never reached, nor a Log.D debug output or whatever else I put in following. I just get this message from LogCat:
BluetoothSocket read in: android.net.LocalStocketImpl$SocketInputStream#f7e
b08 len: 1024
To transfer the data from the Client to the Server I am doing this:
public class MainActivity extends Activity {
...(some code here)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
clientConnect();
//serverConnect();
}
...(some code here)
public void clientConnect(){
Set<BluetoothDevice> devices;
devices = bConfig.getPairedDevices();
if (devices == null){
return;
}
if (devices.size() > 0) {
BluetoothDevice device = devices.iterator().next();
ConnectThread connectTransmit = new ConnectThread(device,bConfig.getBluetoothAdapter(),BluetoothConfig.mUUID);
connectTransmit.start();
Toast.makeText(this, "connected", Toast.LENGTH_SHORT).show();
socket = connectTransmit.mmSocket;
ConnectedThread connectedThread = new ConnectedThread(socket);
//write file bytes to the connected thread, so the thread can receive its own input written bytes later
File file_to_transfer = new File(Environment.getExternalStorageDirectory() + "/txtTransfer.txt");
//get bytes from our File
int size = (int) file_to_transfer.length();
byte[] bytes = new byte[size];
try {
//14b are read succesfully, the whole text file
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file_to_transfer));
buf.read(bytes,0,bytes.length);
buf.close();
}catch (FileNotFoundException e){
Log.d("FileNotFoundException:",e.getMessage());
}catch (IOException e){
Log.d("IOException:",e.getMessage());
}
//send the data to the server
connectedThread.start();
connectedThread.write(bytes);
//connectedThread.cancel();
}
}
...(some code here)
}
The AcceptThread (Server part of the implementation) works, because when I run the client part to connect and then transfer the data, while debuging in the device the LogCat on the Server part activates and reaches the run method of the thread, where I call the ConnectedThread implementation but then after it "apparently" reads the bytes but it gets stuck on LogCat with no error.
Please let me know what can I do to finish reading the bytes to move to the next part of the flow.
Thank you
You're blocked waiting for more input.
The part labelled ... (some code here) should be inside the read loop, after the test for end of stream. NB If read() returns -1 it doesn't mean 'no data', it means end of stream, and you should close the socket and break out of the read loop. Otherwise you should then go on to process the data you've just read. At present you just read and ignore all input until end of stream, which is pointless. At best you can only process the last partial buffer, and you won't know how long it was.
In my opinion You should verify if something is in buffer before reading.
reading from stream is blocking operation so aplication will hang until somehing data appear.
How can I check if an InputStream is empty without reading from it?
In your client code you should probably keep the connectedThread object alive a while longer. Might be that once the if clause closes and it goes out of scope (not quite sure what happens with GC and all) the write just doesn't happen and your connection is not closed but not used either.
Calling flush() on the mmOutStream inside the connectedThread after the write might help also.
Like #EJP suggested, you should put something inside your read loop.
Edit: For the sake of debugging you could add this.wait(1000); immediately after your write in the client code.
Try changing your run method to this:
public void run(){
byte[] buffer = new byte[1024];
int bytesRead = 0;
final int shortSleepTime = 1000;
final int longSleepTime = 5000;
int emptyReadCounter = 0;
int sleepCounter = 0;
int currentSleepTime = shortSleepTime;
//Keep listening to the InputStream while connected
while (bytesRead >= 0){
try {
// if available() returns 0, there is nothing to read yet
if (this.mmInStream.available() != 0){
bytesRead = this.mmInStream.read(buffer);
// Check if we need to reset the sleep counters
if (emptyReadCounter != 0){
emptyReadCounter = 0;
sleepCounter = 0;
currentSleepTime = shortSleepTime;
// We can also do anything else dependent on just waking up
// from a sleep cycle in this block
}
// Do something with my now full buffer
// Remember not to process more than
// 'bytesRead' bytes from my buffer because the
// rest could be filled with crap left over from
// the last iteration
} else {
// Three consecutive empty reads means sleep
if (emptyReadCounter++ >= 3){
if (currentSleepTime != longSleepTime && sleepCounter++ >= 3){
currentSleepTime = longSleepTime;
}
Thread.sleep(currentSleepTime);
}
}
}
catch(Exception e){
Log.d("inStream exception:",e.getMessage());
break;
}
}
}

How to separate data being received over bluetooth in android

I have modified the BluetoothChat example code to connect to a generic bluetooth transceiver which I have connected to the UART on a TI MSP430 development board. I have established communication and can send and receive a single string and display the value in a TextView. Below is the C code that I'm using to send the 1-3 digit value for pressure, temp1 and temp 2. It is fairly straightforward, and I is working as designed.
for(int i = 0; i <= 2; i++) // send pressure value
{
UCA0TXBUF = pressureString[i];
while(!(IFG2 & UCA0TXIFG));
}
for(int i = 0; i <= 2; i++) // send temp1 value
{
UCA0TXBUF = tempOneString[i];
while(!(IFG2 & UCA0TXIFG));
}
for(int i = 0; i <= 2; i++) // send temp2 value
{
UCA0TXBUF = tempTwoString[i];
while(!(IFG2 & UCA0TXIFG));
}
Now I want to send multiple pieces of data to the android device and have them displayed according to their data type in a separate TextView for each value. For right now I am measuring two temperature sensors and a pressure sensor. I have sent all of the data to the android device with no problems, but all the values just overwrite each other in the TextView so that only the last string sent is displayed.
This is the portion of code that runs while connected to a remote device:
/**
* 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;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
This is the code that reads the message and displays it in the TextView:
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);
mTextView.setText(readMessage); //added by AMJ in attempt to display variable in textview
break;
I can't seem to figure out how to program the android application to be able to tell the difference between strings, so that when I receive the Temp1 string it goes to the Temp1TextView, and Temp2 string goes to Temp2TextView, etc. Should I add a special character as the first bit sent from the MSP430, and reference that bit in Android to identify where it should go? Just a thought.
Any help is much appreciated.
EDIT: I figured I could try and convert the int to a string, then use the tokenizer to separate it, and then convert it back to an int. However, the application is now crashing when it receives data over bluetooth. Here is the code that I'm using to convert it. Any idea why it may be crashing?
bytes = mmInStream.read(buffer);
byteString = String.valueOf(bytes);
StringTokenizer tokens = new StringTokenizer(byteString, ":");
String first = tokens.nextToken(); // this will contain exhaust temp
String second = tokens.nextToken(); // this will contain damper position
separatebytes1 = Integer.valueOf(first);
separatebytes2 = Integer.valueOf(second);
// Read from the InputStream
// bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
// mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
// .sendToTarget();
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, separatebytes1, -1, buffer)
.sendToTarget();
This is the logcat from the crash:
W/dalvikvm(24850): threadid=11: thread exiting with uncaught exception (group=0x
411ae300)
E/AndroidRuntime(24850): FATAL EXCEPTION: Thread-1286
E/AndroidRuntime(24850): java.util.NoSuchElementException
E/AndroidRuntime(24850): at java.util.StringTokenizer.nextToken(StringTok
enizer.java:208)
E/AndroidRuntime(24850): at com.example.android.BluetoothChat.BluetoothCh
atService$ConnectedThread.run(BluetoothChatService.java:411)
W/ActivityManager( 270): Force finishing activity com.example.android.Bluetoo
thChat/.BluetoothChat
You either have a single message with several values in pre-defined order, or you'll have to tell the receiver (app) which value is being sent next, more or less as you suggested.
The crash (regarding your edited question) occurs likely because byteString does not contain a ":". If this is the case, your
String second = tokens.nextToken()
will throw exactly the Fatal Exception you posted.
So, before you separate the string with tokens.nextToken(), check how many Tokens are in the bytestring with:
tokens.countTokens

Android - Pass object via bluetooth

The Bluetooth chat example for Android is very useful to learn how to pass strings between phones - is it possible to use the same code to pass objects between phones? I have the same classes defined in both phones, I just want to pass the instance of one class from one phone to another. Is there any sample code available? I tried using serialization and replacing outputstream and inputstream in the chat example with objectoutputstream and objectinputstream but it didn't seem to work
The best way I found to handle this was the following:
I set up my objects as implementing Serializable that I wanted to send.
I set up the following code to manage the messages:
public byte[] serialize() throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b);
o.writeObject(this);
return b.toByteArray();
}
//AbstractMessage was actually the message type I used, but feel free to choose your own type
public static AbstractMessage deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b);
return (AbstractMessage) o.readObject();
I changed the write statements to accept a Serializable, and then make the final write:
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(AbstractMessage buffer) {
try {
Log.v(TAG,"Writing \""+(buffer.serialize())+"\"");
mmOutStream.write(buffer.serialize());
// Share the sent message back to the UI Activity
mHandler.obtainMessage(AbstractMessageManager.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
The Bluetooth Chat example is a demonstration of using the Serial Port Profile (SPP) which is based upon RFCOMM. You can serially send across any data you like once the connection is established; you simply need to be able to represent your objects into a serial stream of bytes, i.e. serialize them.
Therefore the use of serialization would certainly be a way of getting your objects sent over the link. The Bluetooth API's send and receive functions deal with arrays of bytes, but you could easily adapt the Bluetooth Chat example to use streams, e.g. the send function would read bytes out of a stream and put them into an array buffer, then you send that buffer, etc. Then the application code would simply talk via input and output stream pipes - that's one way I've done it in the past.
So there's nothing wrong with your actual idea. The bigger problem is that the way you've implemented it is not right, and more problematic still is that the way you've asked your question is quite poor, too. You need to be more descriptive about exactly what didn't work, explain what debugging you've already tried, and post code samples and Logcat outputs so we can help you properly.
Finally, I did find what I think is a bug in the Bluetooth Chat code example: The data receive function passes a reference of the receive byte array to the ArrayList that's used to show each line of text received. This is alright when small amounts of slow text are being transmitted across, but when you try to send large amounts of data, you start to see the data being corrupted, presumably because the ArrayList adapter is still reading bytes out of that same array when the array is being filled with even newer data.
The answer is yes. A String is an Object. Remember? But how exactly to do it, I am still searching for a solution and that's what brought me here...
Trev16v,
First of all, thanks for your initial feedback.
In order to serialise my object, I used the classes serializeObject and deserializeObject from
http://www.jondev.net/articles/Android_Serialization_Example_(Java)
They seem to work well: if I serialise an object (created out of a class that implements Serializable) from a phone/activity and deserialize it from the same phone i manage to get an object out of the generated byte[].
I then tried to use the same code in the class BluetoothChatServices in the bluetooth chat example in oder to send the serialised object to the other phone (in that example there is
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;
}
and the bytes are passed using
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
and read using
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[10240];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothManageActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
The problem with using BluetoothChatServices as it is is that the array of bytes received on the other phone is different from the one sent when it comes to serialised objects. For example, to give an idea element [0] of the seriealized object is =-84 when i send it, the one i receive from the other phone has element [0] to [4] =0, then [5]=4 and all the other elements are also not aligned. I tried in the methods write and run above to change Inputstream and Outputstream with ObjectInputStream and ObjectOutputstream but without success (if this was supposed to be the way to implement it, I can post the code I tried to use)
Again, thanks a lot for your help, I am new to all these concepts so if I am talking nonsense I will be also happy to be addressed to a tutorial
thanks
Facing same problem ... When i am sending a series of objects from one Android device, data sends properly ... But in receiving end all objects does not construct from received byte[].
Error occurs randomly for any received object but the same code works properly in Java ... I think the some bytes misses when transferring data from one device to another ...
Serializable object to byte[] and byte[] to object conversion can be done with the following code
public static byte[] toByteArray(Object obj)
{
byte[] bytes = null;
ObjectOutputStream oos = null;
try
{
oos = new ObjectOutputStream(new ByteArrayOutputStream());
oos.writeObject(obj);
oos.flush();
return bos.toByteArray();
}
catch(Exception e)
{
Log.e("Bluetooth", "Cast exception at sending end ...");
}
return bytes;
}
public static Object toObject(byte[] bytes)
{
Object obj = null;
ObjectInputStream ois = null;
try
{
ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return ois.readObject();
}
catch(Exception ex)
{
Log.e("Bluetooth", "Cast exception at receiving end ...");
}
return obj;
}
I actually found the problem - when the bytes are loaded using
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
they are actually loaded in 2 steps.. While debugging and stepping into the code I found that if first loads 990 bytes and then the remaining bytes.. so when i am back to the UI handler i see only the bytes loaded in the second step..
i wonder if there is a way to force to load all bytes at once

Categories