Android cannot recieve all characters via bluetooth - java

I'm creating an app that sends and receive data with an arduino via bluetooth. Sending works fine, however when receiving data I don't get the first few characters of the string sent. I always don't get the first character, the second I sometimes get it, the third I almost always get it, etc.
So for example if the arduino sends "OK 1" I receive "K 1" or " 1" or "1", but never the complete string. An easy fix would be to add a few dummy characters, but that's a shit fix.
Here's the method which listens to incoming connections, directly copy/pasted from Android sample bluetooth code to send a simple string via bluetooth (though with a few fixes):
void beginListenForData()
{
final Handler handler = new Handler();
final byte delimiter = 10; //This is the ASCII code for a newline character
final boolean stopWorker = false;
final int readBufferPosition = 0;
final byte[]readBuffer = new byte[1024];
Thread workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
try
{
int bytesAvailable = inStream.available();
int readBufferPosition2 = readBufferPosition;
if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
inStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[readBufferPosition2];
System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
final String data = new String(encodedBytes);
readBufferPosition2 = 0;
handler.post(new Runnable()
{
public void run()
{
result.setText(data);
}
});
}
else
{
readBuffer[readBufferPosition2++] = b;
}
}
}
}
catch (IOException ex)
{
}
}
}
});
workerThread.start();
}
Here's all my code in case you want to test it (warning: lots of dummy and outdated code):
MainActivity.java http://pastebin.com/cdjW4Y1V
XML layout file http://pastebin.com/Ruf5euPP
Click on the first button to connect to the arduino and click on the second button to send a string and to begin receiving data.
So yep, I have absolutely no idea why it doesn't work. It works fine with TerminalBT so it's not a problem with the arduino, it's a problem with my app, but why do I receive characters randomly?

one thing i noticed is that you should not use 10 for the delimiter.
I have encountered this error before if you use 10 then some times it does not get recognized properly.
you should use standard Java Function to parse the delimiter.
System.getProperty("line.separator");
//OR
System.lineSeparator();

Related

Missing character off incoming string from Bluetooth

I am currently trying to create a water level readout as a progress bar in a simple Android app. Currently, I am using an Arduino Mega 2560 with a HC-05 to transmit the readout of the water level sensor. To simplify things, the arduino code is just counting up and down from 0 to 1000 and back, as follows.
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Test for Water Sensor");
Serial1.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
for (int i = 0; i <= 1000; i++)
{
Serial1.println(i);
Serial.println(i);
delay(100);
}
for (int i = 1000; i >= 0; i--)
{
Serial1.println(i);
Serial.println(i);
delay(100);
}
}
On the android end, I am using this to convert to int, then change the progress bar. It also currently displays the unconverted message in a TextView.
mHandler = new Handler(Looper.getMainLooper()){
#Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_READ){
String readMessage = null;
try {
readMessage = new String((byte[]) msg.obj, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
mReadBuffer.setText(readMessage);
try {
waterLevelValue = NumberFormat.getInstance().parse(readMessage).intValue();
waterLevel.setProgress(waterLevelValue);
} catch (ParseException e) {
e.printStackTrace();
}
}
if(msg.what == CONNECTING_STATUS){
if(msg.arg1 == 1)
mBluetoothStatus.setText("Connected to Device: " + msg.obj);
else
mBluetoothStatus.setText("Connection Failed");
}
}
};
The issue I am getting is that quite often (maybe 1-2 times a second) it is not reading the first digit. I can see on the Serial Monitor that all digits are going there, but on the android app, it will sometimes miss the first (eg: 443, 444, 45, 446, 447, etc)
What could be causing the issue here, I am very new to Bluetooth, so please help! More than happy to send more portions of code if needed.
EDIT: Adding code for reading input stream. Probably was important in the first place.
public void run() {
byte[] buffer = new byte[1024]; // 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.available();
if(bytes != 0) {
SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed.
bytes = mmInStream.available(); // how many bytes are ready to be read?
bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}

Bluetooth read incoming character one at a time

I have a small question about Bluetooth communication, I've been going through a tutorial on YouTube on how to create an app that communicates with my arduino. Everything is going fine; however my only problem is that when I test for incoming data from arduino in the phone the string data seems to be tested randomly using Stringbuilder thus the test sometimes may or may not work. The data received is as follows "B1234." Lettet B indicates which data is received, the following numbers are the data itself and the dot indicates the end of stream. I'm New to android so I'm sorry if my question is not as clear as it should be
Here's the onReceive java code for BluetoothConnectionService:
byte [] buffer = new byte [1024];
int bytes;
//Keep listening to the InputStream until an exception occurs
while(true) {
try {
bytes mainstream.read(buffer);
String incomingMessage = new String (buffer, 0, bytes);
Intent incomingMessageIntent = new Intent ("incomingMessage");
incomingMessageIntent.putExtra ("theMessage", incomingMessage);
LocalBroadcastManager.getInstance (mContext).sendBroadcast(incomingMessageIntent);
}
catch (Exception e) {
break;
}
}
And here's the received java code in MainActivity:
publix final BroadcastReceiver mBroadcastReceiver5 = new BroadcastReceiver () {
public void onReceive(Context context, Intent intent) {
final String text = intent.getStringExtra ("theMessage");
messages.append(text); //Append StringBuilder
FragmentData.RXData.setText (messages);
messages.setLength(0);
}
}

Setting raw data/byte array as a source of an ImageView

I have a Client-Server system where server is written in cpp and the client is written is Java (Android application).
The server reads an image from a local directory as an ifstream using read method.
The reading process is done inside a loop, where the program reads parts of the image every time. Every time a part of the image is read, it's sent over a socket to the client that collects all the piece inside a byteBuffer and when all the bytes of the image are transfered to the client, the client attempts to turn that array of bytes (after using byteBuffer.array() method) into a Bitmap.
This is where the problem begins - I've tried a few methods but it seems that I'm unable to turn this array of bytes into a Bitmap.
From what I understood, this byte array is probably a raw representation of the image, which can't be decodded using methods like BitmapFactory.decodeByteArray() since it wasn't encoded in the first place.
Ultimately, my question is - how can I proccess this array of bytes so that I'll be able to set the image as a source to an ImageView?
Note: I've already made sure that all the data is sent over the socket correctly and the pieces are collected in the right order.
Client code:
byte[] image_bytes
byte[] response_bytes;
private void receive_image ( final String protocol, final int image_size, final int buffer_size)
{
if (image_size <= 0 || buffer_size <= 0)
return;
Thread image_receiver = new Thread(new Runnable() {
#Override
public void run() {
ByteBuffer byteBuffer = ByteBuffer.allocate(image_size);
byte[] buffer = new byte[buffer_size];
int bytesReadSum = 0;
try {
while (bytesReadSum != image_size) {
activeReader.read(buffer);
String message = new String(buffer);
if (TextUtils.substring(message, 0, 5len_of_protocol_number).equals(protocol)) {
int bytesToRead = Integer.parseInt(TextUtils.substring(message,
len_of_protocol_number,
len_of_protocol_number + len_of_data_len));
byteBuffer.put(Arrays.copyOfRange(buffer,
len_of_protocol_number + len_of_data_len,
bytesToRead + len_of_protocol_number + len_of_data_len));
bytesReadSum += bytesToRead;
} else {
response_bytes = null;
break;
}
}
if (bytesReadSum == image_size) {
image_bytes = byteBuffer.array();
if (image_bytes.length > 0)
response_bytes = image_bytes;
else
response_bytes = null;
}
} catch (IOException e) {
response_bytes = null;
}
}
});
image_receiver.start();
try {
image_receiver.join();
} catch (InterruptedException e) {
response_bytes = null;
}
if (response_bytes != null)
{
final ImageView imageIV = (ImageView) findViewById(R.id.imageIV);
File image_file = new File(Environment.getExternalStorageDirectory(), "image_file_jpg");
try
{
FileOutputStream stream = new FileOutputStream(image_file);
stream.write(image_bytes);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
//Here the method returns null
final Bitmap image_bitmap = BitmapFactory.decodeFile(image_file.getAbsolutePath());
main.this.runOnUiThread(new Runnable() {
#Override
public void run() {
imageIV.setImageBitmap(image_bitmap);
imageIV.invalidate();
}
}
}
}
Whenever you exchange data between two machines of different architectures via sockets you need to know the Endianness (big-endian/little-endian) of each machine. If different, you will need to convert bytes to correct the data. Perhaps that's your issue. Here's a link with sample code: Converting Little Endian to Big Endian. You should be able to easily find more articles explaining the concept.
It turned out that something was wrong with my sending protocol.
After patching it up a bit it actually worked.
Thanks for the help.

How to get the Ping sensor data to Android Studio on a TextView via Blutooth HC-06

I have managed to set up the connection between my arduino and the App with the help of Instructables blog.
The connection is set but i need the sensor output value of the ardunio to be displayed on a TextView. This is the Arduino code.
How do i program my Android studio program to read the output value of the serial monitor in the Arduino?
Okay, in the tutorial shows how send data from the app to arduino, but not how receive data from the arduino to your app for do this, you will need:
Send data from arduino by HC-06.
Receive and decode your data in the app.
show decoded data in the TextView.
a litle example for do this.
In Arduino:
can be the example of the arduino page you must only make sure that HC-06 is properly connected in Serial port.
In the app code you can use this code to receive data, only change the name of SocketBT instance, for the instance that you need.
private class TareaLeer extends Thread
{
#Override
public void run()
{
while(SocketBT.isConnected())
{
InputStream inputStream;
try {
inputStream = SocketBT.getInputStream();
byte[] buffer = new byte[256];
if (inputStream.available() > 0) {
inputStream.read(buffer);
int i = 0;
for (i = 0; i < buffer.length && buffer[i] != 0; i++) {
}
String strInput = new String(buffer, 0, i);
String Recepcion = strInput;
Log.d("Recibi",Recepcion);
//Here you can pass the value of recepcion to any globlal variable and show in TextView
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Parar();
}
}
for show it on TextView you can do this.
MyTextView.setText(Recepcion);
this is a very general explanation, for do it , you need know how android code works basically, but is a good example for start Android and Arduino Programming.

Java proxy server - some requests aborted, weird bug

I'm kinda new to Java language, but have a good experience in other technologies.
Right now Im working on creating a proxy server and I have come up with the code that seems to work fine for single requests, but when I'm trying to open some html page that loads lots of styles, images etc, part of requests just got aborted ( this is what firebug tells me )
So, will try to simplify the code and be as much specific as possible in showing up the exact problem
Here's the main class :
public class ProxyThread {
public static void main(String[] args) {
ProxyThread Proxy = new ProxyThread();
Proxy.start();
}
public void start() {
ServerSocket server = new ServerSocket(this.portNumber, 1);
while(true) {
Socket serverClient = server.accept();
this._threads[threadCount] = new Thread( new RequestProcess( serverClient, threadCount++ ));
}
}
}
Here's the code of RequestProcess that does processing of each request
public class RequestProcess implements Runnable {
public void start() throws InterruptedException {
this.serverIn = new BufferedReader( new InputStreamReader( this.serverClient.getInputStream() ) );
this.serverOut = this.serverClient.getOutputStream() ;
String currentBuffer;
String request = "";
String host = "";
int port = 0;
while ((currentBuffer = this.serverIn.readLine()) != null) {
if (currentBuffer.length() == 0) {
break;
}
request += currentBuffer + "\r\n";
if (currentBuffer.startsWith("CONNECT ") || currentBuffer.startsWith("GET ")) {
host = this.parseHost( currentBuffer );
port = this.parsePort( currentBuffer );
}
}
request += "\r\n";
if (host.isEmpty() || request.isEmpty()) {
throw new InterruptedException("request or host empty, so exiting ");
}
clientRequestProcess clientProcess = new clientRequestProcess( host, port, request, this.threadNum );
byte[] response = clientProcess.processRequest();
this.serverOut.write(response);
this.serverOut.close();
}
}
And here's the class that process request and sending it to the actual server
public class clientRequestProcess {
public byte[] processRequest()
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte buf[] = new byte[256*1024];
Socket clientSocket = new Socket( host, port );
clientSocket.getOutputStream().write( request.getBytes() );
InputStream is = clientSocket.getInputStream();
int r = 1;
while (r > 0) {
r = is.read(buf);
if (r > 0) {
bos.write(buf, 0, r);
}
}
return bos.toByteArray();
}
}
All the code is draft one and is simplified to show the big picture of how it works. All try-catch blocks, debugging info etc are missed here.
steps
- Set up browser to use JAVA proxy
- Open some site
- Part of http requests are successfully processed and correct response is returned
-part of requests shows up as aborted in firebug. The thing is that part is absolutely random, so one time some file is loading, another it is not
Code troubleshooting shows me that first line of request (that comes from the browser) are empty, so my condition
if (currentBuffer.length() == 0) {
break;
}
breaks reading the socket and thus it ruturns nothing to the browser and connection gets aborted
I read rfc on http protocol and figured out that https requests considered to be over once \r\n meets, so that's why I'm using that condition
If I just open that file in separate tab - it loads successfully, don;t matter how many times im trying to reload it. But when a bunch of files are loaded at one time - some random of them gets aborted. So it is happening only when a lot of files loading, when one or even 3-5 - all files loads fine
Any ideas?
Thanks

Categories

Resources