I am doing an app for my arduino sensor I wanted to know how to actually obtain the data from arduino to android studio via bluetooth because in my arduino I put Serial.println("occupied") but when receive in android it somehow mixed with some numbers/bytes like "o2cuppied" or else it will receive seperately in logcat. I don't know what is wrong with it.
Arduino Code:
void setup() {
serial1.begin(9600); //for the bluetooth module
}
void loop() {
//send data to Bluetooth module//
if (dist[0] < dist_threshold) {
serial1.print("Occupied\n");
}
if (dist[1] < dist_threshold) {
serial1.print("Occupied2\n");
}
Android
#Override
protected void onCreate(Bundle savedInstanceState) {
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECEIVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
// and clear
txtArduino.setText("Data from Arduino: " + strIncom);
break;
}
}
};
}
private class ConnectedThread extends Thread {
private final BluetoothSocket bluetoothSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
bluetoothSocket = socket;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
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.read(buffer); // Get number of bytes and message in "buffer"
String incomingMessage = new String(buffer, 0, bytes);
Log.d(TAG, "InputStream: " + incomingMessage);
h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
break;
}
}
}
}
Logcat
2019-11-27 12:28:13.505 12733-12893/com.example.fyp D/MainActivity: InputStream: O
2019-11-27 12:28:13.508 12733-12893/com.example.fyp D/MainActivity: InputStream: ccupied
private StringBuilder sb = new StringBuilder();
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,
sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length());
final String finalSbprint = sbprint;
TCP: You have to concatenate the incoming bytes.
But if the Arduino is only going to send text you can make your life easier by letting it send "Occupied\n" instead of "Occupied".
On the receiving side you add a BufferedStreamReader and use its readLine() member to read that line.
Related
So, I am using my arduino to collect some data and send it to my android app , so that I can store this data in a file, making my android a sort of datalogger.
I am using an hC-06 for this, working at 115200 bauds/sec. Seems to be allright when the arduino sends the data chunks ( 60bytes every chunk) every 100ms aprox.
The problem begins when I "query" the arduino for some special data, by sending a single byte with the OutputStream method. From the moment the app uses the "mmOutStream.write(buffer);" the data received by InputStream becomes unstable, varying the chunk size with random values ( 60 bytes, 45 butes, 100 bytes, etc...)
It seems like using OutputStream kind of corrupts the InputStream buffer...
Anyone has been through this? Thaks in advance
below the code:
// It handles all incoming and outgoing transmissions.
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private boolean send_request=false;
private byte[] send_buffer;
public ConnectedThread(BluetoothSocket socket, String socketType) {
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) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer;
ArrayList<Integer> arr_byte = new ArrayList<Integer>();
// Keep listening to the InputStream while connected
while (true) {
try {
int data = mmInStream.read();
if(data == 0x0A) {
}
else if(data == 0x0D) {
buffer = new byte[arr_byte.size()];
for(int i = 0 ; i < arr_byte.size() ; i++) {
buffer[i] = arr_byte.get(i).byteValue();
}
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothState.MESSAGE_READ
, buffer.length, -1, buffer).sendToTarget();
arr_byte = new ArrayList<Integer>();
}
else {
arr_byte.add(data);
}
} catch (IOException e) {
connectionLost();
// Start the service over to restart listening mode
BluetoothService.this.start(BluetoothService.this.isAndroid);
break;
}
}
}
// Write to the connected OutStream.
// #param buffer The bytes to write
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// mmOutStream.close(); //vdv , close after writing to see if liberates memeory . uncommenting this causes the phone not to connect
//TODO: investigate and solve why a single writing in the outstream causes the inputstream to get corrupted after a while.
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BluetoothState.MESSAGE_WRITE
, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.d(TAG,"write exception"); //vdv
}
}
I used this code to read the reply of a Bluetooth not LE device.
The solution is a Xamarin Forms project and the code is in the DependencyService.
using Android.Bluetooth;
....
public byte[] GetCommand()
{
byte[] rbuffer = new byte[200];
try
{
// Read data from the device
while (!_socket.InputStream.CanRead || !_socket.InputStream.IsDataAvailable())
{
}
int readByte = _socket.InputStream.Read(rbuffer, 0, rbuffer.Length);
}
catch (Java.IO.IOException e)
{
}
return rbuffer;
}
How is it possible to solve it?
I would use the following code instead:
//create new class for connect thread
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
//creation of the connect thread
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
//Create I/O streams for connection
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256];
int bytes;
// Keep looping to listen for received messages
while (true) {
try {
bytes = mmInStream.read(buffer); //read bytes from input buffer
String readMessage = new String(buffer, 0, bytes);
// Send the obtained bytes to the UI Activity via handler
bluetoothIn.obtainMessage(handlerState, bytes, -1, readMessage).sendToTarget();
} catch (IOException e) {
break;
}
}
}
//write method
public void write(String input) {
byte[] msgBuffer = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(msgBuffer); //write bytes over BT connection via outstream
} catch (IOException e) {
//if you cannot write, close the application
Toast.makeText(getBaseContext(), "Connection Failure", Toast.LENGTH_LONG).show();
finish();
}
}
}
This is working for me to get bluetooth information from an Arduino! :)
I went to a struggle. There are so many tutorials regarding this topic, but I cannot adapt any of those to my project.
What I want to do is simple:
User press the button in Android (Dialog opens, user enters numbeers, presses ok)
Arduino compares data and if it matches send one message to Android, if no - another.
Concept is this.
What I have so far is simple Arduino code
void loop() {
if (Serial.available() > 0) { // if the data came
incomingByte = Serial.read(); // read byte
if(incomingByte == '0') {
digitalWrite(LED, LOW); // if 1, switch LED Off
Serial.println("LED OFF. Press 1 to LED ON!"); // print message
}
if(incomingByte == '1') {
digitalWrite(LED, HIGH); // if 0, switch LED on
Serial.println("LED ON. Press 0 to LED OFF!");
bluetoothSerial.write
}
}
I found great tutorial for sending data from Arduino to Android, but it's made in Thread mode and I cannot adopt it to my AsyncThread solution. This is the main problem :\
My Android AsyncThread code looks like that:
private class ConnectBT extends AsyncTask<Void, Void, Void> // UI thread
{
private boolean ConnectSuccess = true; //if it's here, it's almost connected
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(ConnectedActivity.this, "Connecting...", "Please wait!!!"); //show a progress dialog
}
#Override
protected Void doInBackground(Void... devices) //while the progress dialog is shown, the connection is done in background
{
try
{
if (btSocket == null || !isBtConnected)
{
myBluetooth = BluetoothAdapter.getDefaultAdapter();//get the mobile bluetooth device
BluetoothDevice dispositivo = myBluetooth.getRemoteDevice(address);//connects to the device's address and checks if it's available
btSocket = dispositivo.createInsecureRfcommSocketToServiceRecord(myUUID);//create a RFCOMM (SPP) connection
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
btSocket.connect();//start connection
}
}
catch (IOException e)
{
ConnectSuccess = false;//if the try failed, you can check the exception here
}
return null;
}
#Override
protected void onPostExecute(Void result) //after the doInBackground, it checks if everything went fine
{
super.onPostExecute(result);
if (!ConnectSuccess)
{
Toast.makeText(ConnectedActivity.this, "Connection Failed. Is it a SPP Bluetooth? Try again.", Toast.LENGTH_SHORT).show();
finish();
}
else
{
Toast.makeText(ConnectedActivity.this, "Succeed.", Toast.LENGTH_SHORT).show();
isBtConnected = true;
}
progress.dismiss();
}
}
Solution from the tutorial:
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;
}
};
};
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 {
// 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;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(String message) {
Log.d(TAG, "...Data to send: " + message + "...");
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
Log.d(TAG, "...Error data send: " + e.getMessage() + "...");
}
}
}
Full tutorial can be found here:
http://solderer.tv/data-transfer-between-android-and-arduino-via-bluetooth/
I can send data from Android to Arduino with no problem. But receiving it.. nope. Any suggestions?
EDITv2
Silly me. I've put handler and thread's code in my activity. And ran
mConnectedThread = new ConnectedThread();
mConnectedThread.start();
in AsyncTask background task. I can see valid toast message now.
Tnx!
I'm making a Battleships game and I want to send an Array of a class named Ships(which contains stuff like ship name, size, rotated or not and an arraylist for coordinates). I've googled this and looked on Stack overflow and I basically need to serialize the array, but this is where I'm stuck. I need to use ObjectOutputStream, but how do I encorporate that into the code below (taken from android dev site). Note I have already made the ship class implement serializable. Thanks in advance
public class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "connectedthread started");
// mHandler.obtainMessage(TEST).sendToTarget();
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) {
Log.e(TAG, "temp sockets not created");
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "Begin mConnectedThread");
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.read(buffer);
// Send the obtained bytes to the UI activity
Log.i(TAG, "reaaaad msg");
mHandler.obtainMessage(SetUpGame.MESSAGE_READ2, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnectd");
break;
}
}
}
/*
* Call this from the main activity to send data to the remote
* device
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
Log.i(TAG, "writeeee msg");
mHandler.obtainMessage(SetUpGame.MESSAGE_WRITE, -1,-1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write");
}
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close of connect socket failed");
}
}
}
and my handler:
final Handler mHandler = new Handler() {
#Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MESSAGE_READ2:
byte[] readBuf = (byte[]) msg.obj;
String readMessage = new String(readBuf, 0, msg.arg1);
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
String writeMessage = new String(writeBuf);
//Toast.makeText(getApplicationContext(),"Me:" + writeMessage, Toast.LENGTH_SHORT).show();
break;
In the code above you get input/output streams from the connected socket.
Now you can stream data to/from the socket using those streams.
How exactly you do this depends on the type of data you want to stream. In this case you have a serializable Object to send, so you will wrap your stream in a filter that adapts the stream for use with Objects: ObjectOutputStream/ObjectInputStream...
ObjectOutputStream oos = new ObjectOutputStream( mmOutStream );
for (Ship ship: ships)
oos.writeObject( ship );
This code iterates through the array of Ships, writing each ship to the stream (and hence, to the Bluetooth socket).
The receiving side is the same, with one additional complication: you don't necessarily know when to stop or what to read. There are various schemes for handling this, and there are SO questions dealing specifically with this. The Bluetooth page of the Android developer's guide has sample code for this:
http://developer.android.com/guide/topics/connectivity/bluetooth.html
I need to show data to a TextView from a serial Bluetooth.
But when i connect my application with the serial device, it did connected but suddenly went forced closed. The logcat shows nothing so I don't know what's wrong.
This is the code when application listens the inputstream while connected:
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
//mEmulatorView.write(buffer, bytes);
mTextView.append(new String(buffer));
// Send the obtained bytes to the UI Activity
//mHandler.obtainMessage(BlueTerm.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
String a = buffer.toString();
mTextView.setText(a);
a = "";
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
and TextView mTextView = (TextView) findViewById(R.id.dataTerm);
and on the layout:
<TextView
android:id="#+id/dataTerm"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
So does anyone know what went wrong?
Any answers are so helpful, thanks..
The code that finally work
On the main file, in my case named FinalSetting:
On the Activity method, declare:
//Layout View
private static TextView mTextView;
On the onCreate(Bundle savedInstanceState) method declare the textview:
mTextView = (TextView) findViewById(R.id.dataTerm);
On the Handler method:
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
//mEmulatorView.write(readBuf, msg.arg1);
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
//mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
mTextView.setText(readMessage);
break;
On the BluetoothService.java file:
Let's just straight to the method
//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];
//final 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(FinalSetting.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
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(FinalSetting.MESSAGE_WRITE, buffer.length, -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);
}
}
}
After you connect to the serial Bluetooth device, the data will show up on the TextView.
Hope this help :D
Seems like you are trying to modify mTextView in a non-UI thread which is illegal and might be the reason for FC (if not any other issue). However you can achieve this as below:
Change this:
mTextView.append(new String(buffer));
To this:
mTextView.post(new Runnable() {
#Override
public void run() {
mTextView.append(new String(buffer));
}
});