I am building an Android application to communicate with my NR-42 bluetooth device. I am able to connect to the bluetooth and send data to the device which is a PIC18F but I am not able to receive bluetooth data from my device to my android phone.
I am following this example http://solderer.tv/data-transfer-between-android-and-arduino-via-bluetooth/comment-page-1/
When I use tera-term it shows me that the bluetooth module is doing what it is suppose to do, but I can't get the data in my textViews. I am trying to send float data. I am new to android but the issue is happening here I assume.
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
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("\r\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
txtArduino.setText("Data from Arduino: " + sbprint); // update TextView
btnOff.setEnabled(true);
btnOn.setEnabled(true);
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
"
The input stream is being read here."
public void run() {
byte[] buffer = new byte[256]; // 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
Log.d(TAG, "sent handler");
} catch (IOException e) {
break;
}
}
}
Has anyone come across this issue or can help me out?
Thanks
Related
What I have :
HC-05 Bluetooth module
Arduino promini
BPM sensors
Android studio 3.0
What I have done :
Connect the Arduino, sensors, and HC-05 bluetooth using Serial
Send the data from Arduino script
Recieve and get the data using 3rd party apps from playstore
What I wanted to do :
Get the data from arduino's to be showed in the android text view, using native coded apps (not the one from the store) using android studio.
My current code :
Arduino script :
loop(){
Serial.println("*"+String(BPM)+"#"); //BPM from sensor
delay(200)
}
And some code for connecting and pairing using Android Bluetooth Adapter, which I can't showed here full because still hard coded, but the point is :
I made a handler, which recieves incoming inputs from the serial, and at least showing them on Toast component, but still haven't managed to make it work.
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE:
Toast.makeText(getApplicationContext(),"Data in",Toast.LENGTH_SHORT
).show();// if receive massage
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("\r\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
sensorView0.setText("Data from Arduino: " + sbprint); // update TextView
btnOff.setEnabled(true);
btnOn.setEnabled(true);
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
I also have a class :
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket 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 = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
Toast.makeText(getApplicationContext(),"Masuk ke handler private class",Toast.LENGTH_SHORT
).show();
// 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;
}
}
}
}
Which I think calls for the handler to read the message, but haven't managed to make it work.
I wanted to at least show the message to the Toast, or TextView, but haven't got a clear answer this last 3 weeks.
So anyone who can help will be appreciated.
I am sending data from an arduino through a Bluetooth module. I am simply streaming different integers;
int bluetoothData;
//give value to bluetoothData
Serial1.println(bluetoothData);
In my Android code, I have a Bluetooth socket that receives the data from the arduino. The data is taken care of by a Handler. And here lies the problem, sometimes the data is misread. For instance, I am sending '100', but instead the Handler saves in my database '000' or I send '194' and what is read is '994'. Sometimes such a reading mistake would occur once in every 15. Sometimes there will not be any mistake at all. Does someone know what may the reason be? Is it some hardware malfunction of the bluetooth module, is it the way I am reading the data, etc. Here is the Android code for the Thread receiving data:
final int RECIEVE_MESSAGE = 1;
...
mmInStream = socket.getOutputStream();
byte[] buffer = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
bytes = mmInStream.read(buffer);
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();
}
Here is the code for the handler itself:
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE:
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1);
sb.append(strIncom);
int endOfLineIndex = sb.indexOf("\r\n");
if (endOfLineIndex > 0) {
String sbprint = sb.substring(0, endOfLineIndex);
sb.delete(0, sb.length());
btData = Integer.parseInt(sbprint);
M = btData;
insert = mDataBaseHelper.insert(M,DataBaseHelper.TABLE_Temp);
}
I use some of the Bluetooth chat samplecode for sending a SMALL (177 byte to 3617 byte) "settings-file" "securly" between apps.
when it is under 1024 bit everything works fine: (so the 177 works PERFECT)
sendingdevice press "send button" and the reciver gets it (with a dialog if they want it..) (and I save the "string" to a "settings"file on that device)
but if the file is over 1024 it gets chunkt/cut off.. (example: 2000byte)
so the file gets corrupted (data-loss but some info remains..)
Probably I need to "split" my file in 1024 bits and send the bits and in the receiver-end, I need to "add them all up"..
but I don't know the "standard best practices" for this, do you have any suggestions?
I have tryed to "only higher" the 1024 byte to 65536byte, but that don't work..
(or maby I do this wrong..)
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();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}
sedan write:
/**
* Write to the connected OutStream.
* #param buffer The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
mmOutStream.flush();
// 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 when i "click on send settings":
String message = view.getText().toString();
String settingInAString = getSettingInALargeString();
sendMessage(settingInAString);
and in "sendMessage":
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send); //SO convert to byte and then send the byte..
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
and:
/**
* Write to the ConnectedThread in an unsynchronized manner
* #param out The bytes to write
* #see ConnectedThread#write(byte[])
*/
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
but I think you know what Im lookning for ...
(or can I some how change the "BluetoothChat" so it can sent and recive a large Sring, and not "byte:s"? :-) )
Best REGARDS to you all :-)
EDIT:
on the reader side I have this:
on the "reader end" I have:
....
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
//only a byte redebuffer, hmm can I change this? or do i use a whileloop?
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
recivedStringCheckFirst(readMessage);
//simple-check if the data is a "data-setting-file"
String [] allSettingsInALargeArray1 = doSplitOnLargeString(readMessage);
int titleArrayLength1 = getLengthOffTheUpCommingTitleArrayFromNew(allSettingsInALargeArray1); //this do a split and looks if it is 1,2,3..20 settings..)
mConversationArrayAdapter.add(titleArrayLength1 + " datasettings recived from " + mConnectedDeviceName + " SAVE THIS?");
//this type this text to the "chatwindow"
break;
Here is the splitting-chunk-problem now..
if i send under ~ 1024 I receive the correct amount of settings ant i can save this fine :-)
If i sent larger then 1024 I get first for exampel "6 settings from.." and then a new message that I recived "1 settings from.." message :-(
just for your info:
protected void recivedStringCheckFirst(String readMessage) {
String eventuellSettings = readMessage;
if (isThisASettingFile(eventuellSettings)){
//of ok..
System.out.println("incommingISAsetting :-) ");
inkommenSettings = eventuellSettings;
showDialog(); //dialog for save settings?
}
if (!isThisASettingFile(eventuellSettings)){
//not a settingsfile!
Toast.makeText(this, "try again..", Toast.LENGTH_LONG).show();
}
}
so i think it is:
case MESSAGE_READ:
is not only called if a complete file is received,
it is also called if a small chunks is received.
So I probably should place the "readFile-chunk" in a separate buffer
(i.e. mNewBufForFile += readFileChunk)
And then check the mNewBufForFile has a complete packet in it (how?). If it is done: I "save" the file message and then clear all buffer.
but how can i "split this from "Message_read", and do I "add a stopping bit" so i can check when i recive all the data? or can i do this better?
You can send as many bytes as you want. They come in in chunks smaller than the size of buffer (1024). Indeed the original code will mix all up caused by using one buffer. Change
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();
to
while (true) {
try {
byte[] buffer = new byte[1024];
// Read from the InputStream
int nbytes = mmInStream.read(buffer);
Log.i(TAG, "read nbytes: " + nbytes);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, nbytes, -1, buffer)
.sendToTarget();
The data still comes in in chuncks but now you get all displayed in the rigth sequence.
As the chunck sizes -during some tests- are smaller than 1024 it makes no sense to have a bigger buffer. If you want to transfer a real file you should concatenate all together. This is a normal action using sockets.
I am writing software for Android for communication between Arduino and Android.
The Arduino sends data using serial.println - I send the text "It works!".
The Android is receiving data in this way:
bytes = mmInStream.read(buffer);
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
And it displays some code instead of "it works!", more exactly it displays [B#40e3f9b8.
What is the reason and how can this problem be fixed?
You just tried to print a byte array. In Java, that just prints out the type of the object [B, followed by its address #40e3f9b8.
If you want to print the text out, use new String(bytes) to get a string from the bytearray (using the default charset), then print the string out.
You have to create a string from a byte array:
String strIncom = new String(buffer, 0, msg.arg1);
Full example with \r\n handler:
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
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("\r\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
txtArduino.setText("Data from Arduino: " + sbprint); // update TextView
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
See full example program with apk and sources here
I am using Bluetooth Chat sample app from Android website. I want to pass the complete incoming message, (message format included in the code below as this website is parsing the message for me which is my job in the code as well, to a function which removes the tags and extracts message name and value and uses it for further action. The readMessage string (in the switch case Message_Read) sends selected characters and omits few special characters. Following is the code from Bluetooth Chat app (from Android website).
I am not able to receive the complete message in the format which I have mentioned in the code. It gets displayed in multiple lines and many characters get deleted. Any suggestion why this is happening?
// The Handler that gets information back from the BluetoothChatService
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
mTitle.setText(R.string.title_connected_to);
mTitle.append(mConnectedDeviceName);
mConversationArrayAdapter.clear();
break;
case BluetoothChatService.STATE_CONNECTING:
mTitle.setText(R.string.title_connecting);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
mTitle.setText(R.string.title_not_connected);
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
mConversationArrayAdapter.add("Me: " + writeMessage);
break;
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);
mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
//Make sure there is a received message. Extract it's name and value
//int msgLen = readMessage.length();
//if( msgLen!= 0)
// Message format is <MSG><N>shiftDirection<!N><V>1<!V><!MSG>
if (readBuf.equals("<MSG><N>.*<!N><V>.*<!V><!MSG>"))
extractData(readMessage);
else mTitle.setText(R.string.floor_it);
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Toast.makeText(getApplicationContext(), "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
break;
case MESSAGE_TOAST:
Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
Toast.LENGTH_SHORT).show();
break;
}
}
};
The part of the code which reads the incoming stream of bytes into a buffer and passes the buffer object for display.
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);
//String Incoming = new String(buffer);
//Pass "Incoming" instead of "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;
}
}
}
I think the problem is, that case MESSAGE_READ: is not only called if a complete Packet is received, it is also called if a small fragment is received. So you should place the readMessage in a separate buffer (i.e. mNewBuf += readMessage) check the mNewBuf has a complete packet in it. If so, you parse your message and after that you clear your buffer. It worked for me.
if (readBuf.equals("<MSG><N>.*<!N><V>.*<!V><!MSG>"))
extractData(readMessage);
equals() doesn't apply regular expressions. If you want to match .*, use classes from java.util.regex to help you.
I was having the same issue, and I'm not 100% this will always work but I found this on the javadoc:
read(byte[] b, int off, int len)
Reads up to len bytes of data from the input stream into an array of bytes.
If you know how many bytes you are expecting then you could try using
bytes = mmInStream.read(buffer, 0, lengthYouWant);
However, this wouldn't work if your incoming data is variable in length.