I am trying to read bytes received via a bluetooth connection and convert it to String
Monitor input stream
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(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}
MainActivity when I receive, the log statement does not seem to get called if there is multiple lines. If it is just a single line, it's fine
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
String readMessage = new String(readBuf, 0, msg.arg1);
Log.d(TAG, "Incoming message: " + readMessage); // does not get called when there's a linebreak.
When I try to check if the string contains certain info as such, it doesn't get called even though the String I received does contain it.
For example, given if I receivedreadMessage = "Obstacle String\nStart of 2nd line"
The following statement doesn't get called
if (readMessage.contains("Obstacle String"))
But when I try to set the readMessage to some TextView, it is able to display the string correctly.
For some reason Android logcat does not seems to handle \r
So, I trimmed the string as such
readMessage = readMessage.replaceAll("\r", "");
Related
I'm trying to decode a []byte from an Arduino BT, I got the connection perfectly, the problem is when I try to decode the array. all that I get is this character � (the same number of bytes sent) I think that the problem is on the decoding. I try with ASCII charset but still the same problem. I'm using Android Studio and set to UTF-8 format.
Could someone tell me what is happening please?
OutputStream:
public void write(byte[] bytes) {
String text = new String(bytes, StandardCharsets.US_ASCII);
Log.d(TAG, "write: Writing to outputstream: " + text);
try {
mmOutStream.write(bytes);
Log.d(TAG, "write: Writing to outputstream: " + bytes);
} catch (IOException e) {
Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
}
}
InputStream:
public void run (){
byte [] buffer = new byte[1024];
int bytes;
while(true){
try {
bytes = mmInStream.read(buffer);
String incomingMessage = new String (buffer,0,bytes, StandardCharsets.US_ASCII);
Log.d(TAG,"InputStream: " + incomingMessage);
Intent incomingMessageIntent = new Intent("incomingMessage");
incomingMessageIntent.putExtra("El mensaje", incomingMessage);
Log.d(TAG,"Mensaje enviado a la main actv " + incomingMessage);
LocalBroadcastManager.getInstance(mContext).sendBroadcast (incomingMessageIntent);
} catch (IOException e) {
Log.e(TAG,"Error leyendo Imputstream" +e.getMessage());
break;
}
}
}
Logcat to see the character that I receive:
From the Arduino side you should use char as sending format.
Serial.write Writes binary data to the serial port. This data is sent as a byte or series of bytes
So simply try to decode
Serial.print("1234ABCD\r\n");
Not knowing the commands on Android I guess bytes in Arduino speak is char and not binary data. And always post all code used!
is there a quicker way to copy bytes from one array to another without iteration ?
I'm reading bytes via Bluetooth from the input stream
public void run() {
byte[] buffer = new byte[100]; // 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
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
break;
}
}
}
This sends a random number of bytes to the handler.
I then read these and put them into an array to then process the data when the download is complete. The data being sent from a PIC micro is 6055 bytes long.
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SUCCESS_CONNECT:
// Connected so start connected thread
btSocket = (BluetoothSocket) msg.obj;
byteCount = 0;
arrayCount = 0;
mConnectedThread = new FullDataActivity.ConnectedThread(btSocket);
mConnectedThread.start();
mConnectedThread.write(getFullDataConByte); // Send 255 to start
break;
case RECIEVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
// iterate through obj and copy bytes to fullDataChunk array
for (int a = 0; a < msg.arg1; a++) {
fullDataChunk[byteCount] = readBuf[a];
Log.d("readBuf[a] = ",Integer.toString(readBuf[a] & 0xFF));
byteCount++;
}
// if all bytes done process
if (byteCount == 6055) {// process data when complete.
My handler is missing bytes somewhere and corrupting the data when its copying them in the for loop. I don't know if the run method is sending new bytes to the handler before the rest are processed in the for loop.
I've done a Log of the bytes sent in the Run and they are right. It's when the handler is processing that they go wrong.
I either need to ensure the data sent is processed before new data is sent, or copy the data to the array quicker ?
Anyone any ideas.
The fastest way to copy an array should be by using System.arraycopy()
.
Did this in the run, then the handler receives full array without errors.
public void run() {
byte[] fullBuffer = new byte[6055];
byte[] buffer = new byte[100]; // buffer store for the stream
int bytes; // bytes returned from read()
int bytesCount = 0;
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
System.arraycopy(buffer,0,fullBuffer,bytesCount,bytes);
bytesCount = bytesCount + bytes;
Log.d("FD Read - ", Integer.toString(bytesCount));
if(bytesCount >= 6055){
h.obtainMessage(RECIEVE_MESSAGE, bytesCount, -1, fullBuffer).sendToTarget(); // Send to message queue Handler
Log.d("FD Read - ", "Message sent");
bytesCount = 0;
Log.d("FD Read - ", "bytesCount re-set");
}
//h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
break;
}
}
}
I have this block of code to read an array sent from the server to the client of recent updates, the issue is that sometimes it works and sometimes it doesn't. It will print out the version properly, but everything else will either not print out, all print out on the same line, or have 2 on the same line.
The purpose of this is to receive a String[] of recent updates from the server, which is looped through and sent as an individual String. Those updates are then displayed on a GUI.
private Response update() {
try {
Socket socket = new Socket(RS2Client.IP, 55555);
byte[] bytes = new byte[1024];
socket.getInputStream().read(bytes);
String version = new String(bytes);
System.err.println("VERSION READ " + version);
for (int i = 0; i < 6; i++) {
byte[] b = new byte[1024];
socket.getInputStream().read(b);
String text = new String(b);
getRecentUpdates().add(text.trim());
System.out.println("New update: " + text);
}
for (String update : getRecentUpdates()) {
System.err.println(update);
}
System.out.println("Client connected! Version: " + version);
socket.close();
if (Double.parseDouble(version) != RS2Client.CLIENT_VERSION) {
return Response.BAD;
}
} catch (Exception e) {
e.printStackTrace();
return Response.ERROR;
}
return Response.GOOD;
}
A socket sends a stream of bytes. It does not keep track of the end of each byte array you send.
If you want to send a byte array, you should send the length first, so you know how many bytes to expect.
I'm trying to send images from my computer to my phone by using a Java program connect to an Android app.
The code I use to send the image:
byte[] data = imageToByteArray(img);
sendMessage(Main.imageCheck + data.length);
out.write(data);
out.flush();
This code is run from the Java program on my computer. The sendMessage() method is:
public void sendMessage(String s) {
if (out != null && server.isConnected()) {
try {
out.writeUTF(s);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The code I use to receive the image and other data:
while ((input = in.readUTF()) != null) {
if (!input.equalsIgnoreCase(pulseCheckMessage)) {
if (input.contains(imageCheck)) {
//byte[] data = Base64.decode(input.replace(imageCheck, ""), Base64.DEFAULT);
byte[] data = new byte[Integer.parseInt(input.replace(imageCheck, ""))];
int length = in.read(data);
updateScreenImage = BitmapFactory.decodeByteArray(data, 0, length);
MainActivity.this.runOnUiThread(updateUiRunnable);
} else {
inLine = "Received: " + input;
MainActivity.this.runOnUiThread(updateUiRunnable);
}
}
pulseTakenTime = System.currentTimeMillis();
pulseCheckReceived = true;
isAlive = true;
}
The commented out code (including the base64 class) was when I was sending the image data as a string by using Base64.encode to convert the byte[] array to a string to send over, which worked without a problem except that it was too slow. So I decided to send the bytes over which I thought would be faster.
imageCheck and Main.imageCheck are strings that are the same. The app receives that string and recognizes it and expects a byte[] array so it tries to do in.read(data) however I get an error:
ERROR: java.nio.charset.ModifiedUtf8.decode(ModifiedUtf8.java:57)
ERROR: java.io.DataInputStream.decodeUTF(DataInputStream.java:444)
ERROR: java.io.DataInputStream.decodeUTF(DataInputStream.java:438)
ERROR: java.io.DataInputStream.readUTF(DataInputStream.java:433)
ERROR: com.mangopearapples.pccontroller.MainActivity.run(MainActivity.java:238)
Thanks.
My guess is that int length = in.read(data); doesn't read all the bytes that have been sent, as documented:
Reads some number of bytes from the contained input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer
(emphasis mine)
So, the next iteration tries to read the unread bytes of the image as UTF, and it fails. Always use a loop to read bytes from a stream, which stops once all the expected number of bytes have been read.
To confirm that this is the real problem, debug and see if the length returned matches with the actual length.
I am using bluetooth chat in order to connect and recieve data from a bluetooth device.
I use the following code for reading data:
public void run() {
byte[] buffer = new byte[1024];
int bytes;
Log.v("MR", "start listening....");
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
Log.d("MR", "buffer in try");
bytes = mmInStream.read(buffer);
Log.d("MR", "input stream :"+(new String(buffer)));
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Conn.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
Log.d("MR", "buffer after");
} catch (Exception e) {
Log.e("MR", "Error :"+e.getMessage());
//
connectionLost();
// break;
}
Log.d("MR", "buffer after while");
}
}
The device is sending data all the time without stopping.
With the above code I get the message of:
Log.d("MR", "buffer in try");
then it goes to the next line:
bytes=mmInStream.read(buffer);
and never returns from that call. I guess this is because it starts reading data from the device and doesn't stop until it disconnects. How can I read a certain amount of bytes at a time?
EDIT
Unless it stay to the bytes = mmInStream.read(buffer); code due to that it don;t get any data back on from the device?
I use DataInputStreams instead as you can do a readFully() method which waits to read a certain number of bytes before returning. I setup the BT connection like this:
BluetoothDevice btDevice = bta.getRemoteDevice(macAddress);
BluetoothSocket btSocket = InsecureBluetooth.createRfcommSocketToServiceRecord(
btDevice, UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"), false);
btSocket.connect();
InputStream input = btSocket.getInputStream();
DataInputStream dinput = new DataInputStream(input);
then later on when I want to read I use readFully:
dinput.readFully(byteArray, 0, byteArray.length);