Category: Main page » Arduino

Data transfer between Android and Arduino via Bluetooth

This article, shows two examples of working with Bluetooth: 1. Send data to Arduino 2. Data transfer between Android and Arduino.

Arduino

Wiring diagram is the same as in the previous article:

Connect Bluetooth module to Arduino

I use Arduino Nano V3 and Bluetooth module HC-06. Also, I connected the external LED to pin 12. Our program:

char incomingByte;  // incoming data
int  LED = 12;      // LED pin

void setup() {
  Serial.begin(9600); // initialization
  pinMode(LED, OUTPUT);
  Serial.println("Press 1 to LED ON or 0 to LED OFF...");
}

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!");
    }
  }
}

Android

We will use the Java code with an explicit MAC-address of the device. Find MAC-address can be in the program for Android: Bluetooth Terminal:

MAC-address

Our device is "BOLUTEK" with MAC-address 00:15:FF:F2:19:4C.

The first program is very simple, the main activity will contain two buttons: turn on LED and turn off LED. Data transfer in the program will be implemented only on Android devices to Arduino

Main activity

And our Java code of main activity:

package com.example.bluetooth1;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.UUID;
 
import com.example.bluetooth1.R;
 
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
 
public class MainActivity extends Activity {
  private static final String TAG = "bluetooth1";
   
  Button btnOn, btnOff;
   
  private BluetoothAdapter btAdapter = null;
  private BluetoothSocket btSocket = null;
  private OutputStream outStream = null;
   
  // SPP UUID service 
  private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
 
  // MAC-address of Bluetooth module (you must edit this line)
  private static String address = "00:15:FF:F2:19:5F";
   
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
 
    setContentView(R.layout.activity_main);
 
    btnOn = (Button) findViewById(R.id.btnOn);
    btnOff = (Button) findViewById(R.id.btnOff);
     
    btAdapter = BluetoothAdapter.getDefaultAdapter();
    checkBTState();
 
    btnOn.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        sendData("1");
        Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show();
      }
    });
 
    btnOff.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        sendData("0");
        Toast.makeText(getBaseContext(), "Turn off LED", Toast.LENGTH_SHORT).show();
      }
    });
  }
  
  private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
      if(Build.VERSION.SDK_INT >= 10){
          try {
              final Method  m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
              return (BluetoothSocket) m.invoke(device, MY_UUID);
          } catch (Exception e) {
              Log.e(TAG, "Could not create Insecure RFComm Connection",e);
          }
      }
      return  device.createRfcommSocketToServiceRecord(MY_UUID);
  }
   
  @Override
  public void onResume() {
    super.onResume();
 
    Log.d(TAG, "...onResume - try connect...");
   
    // Set up a pointer to the remote node using it's address.
    BluetoothDevice device = btAdapter.getRemoteDevice(address);
   
    // Two things are needed to make a connection:
    //   A MAC address, which we got above.
    //   A Service ID or UUID.  In this case we are using the
    //     UUID for SPP.
   
	try {
		btSocket = createBluetoothSocket(device);
	} catch (IOException e1) {
		errorExit("Fatal Error", "In onResume() and socket create failed: " + e1.getMessage() + ".");
	}
       
    // Discovery is resource intensive.  Make sure it isn't going on
    // when you attempt to connect and pass your message.
    btAdapter.cancelDiscovery();
   
    // Establish the connection.  This will block until it connects.
    Log.d(TAG, "...Connecting...");
    try {
      btSocket.connect();
      Log.d(TAG, "...Connection ok...");
    } catch (IOException e) {
      try {
        btSocket.close();
      } catch (IOException e2) {
        errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
      }
    }
     
    // Create a data stream so we can talk to server.
    Log.d(TAG, "...Create Socket...");
 
    try {
      outStream = btSocket.getOutputStream();
    } catch (IOException e) {
      errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
    }
  }
 
  @Override
  public void onPause() {
    super.onPause();
 
    Log.d(TAG, "...In onPause()...");
 
    if (outStream != null) {
      try {
        outStream.flush();
      } catch (IOException e) {
        errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
      }
    }
 
    try     {
      btSocket.close();
    } catch (IOException e2) {
      errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
    }
  }
   
  private void checkBTState() {
    // Check for Bluetooth support and then check to make sure it is turned on
    // Emulator doesn't support Bluetooth and will return null
    if(btAdapter==null) { 
      errorExit("Fatal Error", "Bluetooth not support");
    } else {
      if (btAdapter.isEnabled()) {
        Log.d(TAG, "...Bluetooth ON...");
      } else {
        //Prompt user to turn on Bluetooth
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, 1);
      }
    }
  }
 
  private void errorExit(String title, String message){
    Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
    finish();
  }
 
  private void sendData(String message) {
    byte[] msgBuffer = message.getBytes();
 
    Log.d(TAG, "...Send data: " + message + "...");
 
    try {
      outStream.write(msgBuffer);
    } catch (IOException e) {
      String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
      if (address.equals("00:00:00:00:00:00")) 
        msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 35 in the java code";
      	msg = msg +  ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
       
      	errorExit("Fatal Error", msg);       
    }
  }
}

Android - transmit and receive data to the Arduino

To receive data from Arduino, in Android application we need to use threads. On the main window activity we add a new element TextView, which will be used to display the received data from the Arduino

package com.example.bluetooth2;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.UUID;
 
import com.example.bluetooth2.R;
 
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
 
public class MainActivity extends Activity {
  private static final String TAG = "bluetooth2";
   
  Button btnOn, btnOff;
  TextView txtArduino;
  Handler h;
   
  final int RECIEVE_MESSAGE = 1;		// Status  for Handler
  private BluetoothAdapter btAdapter = null;
  private BluetoothSocket btSocket = null;
  private StringBuilder sb = new StringBuilder();
  
  private ConnectedThread mConnectedThread;
   
  // SPP UUID service
  private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
 
  // MAC-address of Bluetooth module (you must edit this line)
  private static String address = "00:15:FF:F2:19:5F";
   
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
 
    setContentView(R.layout.activity_main);
 
    btnOn = (Button) findViewById(R.id.btnOn);					// button LED ON
    btnOff = (Button) findViewById(R.id.btnOff);				// button LED OFF
    txtArduino = (TextView) findViewById(R.id.txtArduino);		// for display the received data from the Arduino
    
    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;
    		}
        };
	};
     
    btAdapter = BluetoothAdapter.getDefaultAdapter();		// get Bluetooth adapter
    checkBTState();
 
    btnOn.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
    	btnOn.setEnabled(false);
    	mConnectedThread.write("1");	// Send "1" via Bluetooth
        //Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show();
      }
    });
 
    btnOff.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
    	btnOff.setEnabled(false);  
    	mConnectedThread.write("0");	// Send "0" via Bluetooth
        //Toast.makeText(getBaseContext(), "Turn off LED", Toast.LENGTH_SHORT).show();
      }
    });
  }
  
  private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
      if(Build.VERSION.SDK_INT >= 10){
          try {
              final Method  m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
              return (BluetoothSocket) m.invoke(device, MY_UUID);
          } catch (Exception e) {
              Log.e(TAG, "Could not create Insecure RFComm Connection",e);
          }
      }
      return  device.createRfcommSocketToServiceRecord(MY_UUID);
  }
   
  @Override
  public void onResume() {
    super.onResume();
 
    Log.d(TAG, "...onResume - try connect...");
   
    // Set up a pointer to the remote node using it's address.
    BluetoothDevice device = btAdapter.getRemoteDevice(address);
   
    // Two things are needed to make a connection:
    //   A MAC address, which we got above.
    //   A Service ID or UUID.  In this case we are using the
    //     UUID for SPP.
    
	try {
		btSocket = createBluetoothSocket(device);
	} catch (IOException e) {
		errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
	}
   
    // Discovery is resource intensive.  Make sure it isn't going on
    // when you attempt to connect and pass your message.
    btAdapter.cancelDiscovery();
   
    // Establish the connection.  This will block until it connects.
    Log.d(TAG, "...Connecting...");
    try {
      btSocket.connect();
      Log.d(TAG, "....Connection ok...");
    } catch (IOException e) {
      try {
        btSocket.close();
      } catch (IOException e2) {
        errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
      }
    }
     
    // Create a data stream so we can talk to server.
    Log.d(TAG, "...Create Socket...");
   
    mConnectedThread = new ConnectedThread(btSocket);
    mConnectedThread.start();
  }
 
  @Override
  public void onPause() {
    super.onPause();
 
    Log.d(TAG, "...In onPause()...");
  
    try     {
      btSocket.close();
    } catch (IOException e2) {
      errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
    }
  }
   
  private void checkBTState() {
    // Check for Bluetooth support and then check to make sure it is turned on
    // Emulator doesn't support Bluetooth and will return null
    if(btAdapter==null) { 
      errorExit("Fatal Error", "Bluetooth not support");
    } else {
      if (btAdapter.isEnabled()) {
        Log.d(TAG, "...Bluetooth ON...");
      } else {
        //Prompt user to turn on Bluetooth
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, 1);
      }
    }
  }
 
  private void errorExit(String title, String message){
    Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
    finish();
  }
 
  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() + "...");     
	          }
	    }
	}
}

Video:

Code updated: 28.01.2013

Download APK-files for Android: bluetooth1.apk and bluetooth2.apk

Download source code for Arduino and Android

Author: Koltykov A.V.

Dhakshina 2014-07-03 16:03:24
Same error
Fatal Error - In onResume() and an exception occured during write: socket closed.
Check that the SPP UUID: 0001101-0000-1000-8000-00805f9b34fb exists on server

[Reply] [Reply with quote]
↑ 0 ↓
altinay 2014-05-15 12:37:08
by the way, Digilent ChipKIT Max32 can be used instead of Arduino. BT HC-06 talks on Serial1 port of Max32. thats all.

[Reply] [Reply with quote]
↑ 0 ↓
Andrei Apopei 2014-04-17 14:07:13
What should be modified if I wanted to send characters to the Arduino - for more than 10 commands.
Thanks,
Andrei

[Reply] [Reply with quote]
↑ +1 ↓
Zahra Torabi 2014-02-25 15:55:27
Hi.
Thank you for your good example.
I have a question.
can i use this code for transfer data between two mobile with o.s Android?or it only work with Arduino?

[Reply] [Reply with quote]
↑ 0 ↓
baseball07 2014-02-20 21:01:57
Hi, when I run this on my device (4.2.2) the program immediately crashes saying "Unfortunately, Bluetooth2 has stopped". My device is Bluetooth enabled (have used the Bluetooth before on it) and both Bluetooth permissions are included in the build.

Does this have something to do with
"private BluetoothAdapter btAdapter = null;"

[Reply] [Reply with quote]
↑ +3 ↓
Greg 2014-02-19 03:49:09
Thanks for the great tutorial! I had the example running in no time and minutes later I created my own app to display data streaming from my arduino. Thank you!

[Reply] [Reply with quote]
↑ +2 ↓
Emika 2014-02-09 02:54:52
im use android gingerbread 2.3.6 and i have error message "In on Resume() and an exception occurred during write: socked closed.
check that SPP UUID:00001101-0000-1000-8000-00805F9B34FB exists on server
"

how should I solve the above is problem?... please help me

[Reply] [Reply with quote]
↑ +1 ↓
shannon 2014-02-04 16:42:11
Hi thanks for the example code! I managed to establish connection between the android phone and the Bluetooth remote device but could not send data from the phone to the device. What is lacking and what is the main purpose of the handler in the code?

[Reply] [Reply with quote]
↑ -3 ↓
Monte 2014-01-31 20:49:36
tried to compile the code, but the auto generated com.example.bluetooth1.R.java file is missing. The attachment provided by you doesn't contain this file. As such some error prevails. Please suggest a solution. Thanks in advance.

[Reply] [Reply with quote]
↑ 0 ↓
Helo 2014-06-18 08:13:03
Same as how you have change your first line of code:
package com.example.bluetooth1;
to your own package name,
package com.example.yourAppName;
you must do the same for line 8(first app) or 9(second app):
import com.example.bluetooth1.R;
to
import com.example.yourAppName.R;

[Reply] [Reply with quote]
↑ 0 ↓
Ralph 2014-02-09 11:58:59
i encounter this problem always in res library
sometimes i forgot to put correct id or the
draw-able file. png files only working for me with small letters

[Reply] [Reply with quote]
↑ -2 ↓
Ralph 2014-01-29 22:46:44
very much thanks to this website and to the author of the project.

bluetooth1 is working. you must set the bluetooth address correctly.
i get a hard time inputing the right address of my bt device. when i checked it in terminal it show's like this 0000:1:30403 i don't understand it at first i thought it was like this 00:00:01:30:40:03
but the correct address 00:00:01:03:40:03

bluetooth2 i this is also working but it has a little bug for me. when i click the on & off button it stay in press mode. you need to rotate the screen before it changes in unpress mode


[Reply] [Reply with quote]
↑ +1 ↓
Diane 2014-04-29 23:29:52
Hello, I have the same problem. Did you figure out how to fix it and allow the button to release after being pushed?

[Reply] [Reply with quote]
↑ +1 ↓
Emilio 2014-01-24 19:59:51
Hi, i'm reciving an error en onPause() it seems that de outstream is empty and can't fulsh() data.
Anyone has the same issue?

[Reply] [Reply with quote]
↑ +2 ↓
ahmed kamal 2014-01-23 01:33:04
first this code was very helpful for me thanks a lot for your sharing 2 nd what is the difference between blue tooth 1 & 2
3 rd if i need to make a short cut in the program that make me able to decide which blue tooth i will work with thanks

[Reply] [Reply with quote]
↑ -5 ↓
Ewoks 2014-01-21 17:55:10
Hello ;)
Thanks for nice example. App is based on Chat example if I am not wrong. My question is did you try some kinda faster communication like 100-200 or even more commands and responses per second? Or let's say you send turn_on command and then you get reply from temperature sensor 200 times per second. I wonder how this code would perform in that situation. I noticed that some devices (Samsung for example) are sending data smoothly, but other (like Nexus :S) are sending not message after message but sometimes 2,5 or even 10 messages together. Let's say response is 10 bytes and I got at the same moment 120 bytes together so I need to cut it. Did u experience such a thing with bluetooth and Android devices? Thanks

[Reply] [Reply with quote]
↑ -1 ↓
grum 2014-01-12 01:15:39
First off, thanks for sharing this, it was a great help getting started! I am relatively new to Android development and was getting the same errors as many commenters, where the app would crash on pressing a button, despite having permissions set in the manifest file, and I would get the message:

Fatal Error - In onResume() and an exception occured during write: socket closed.
Check that the SPP UUID: 0001101-0000-1000-8000-00805f9b34fb exists on server


I am using Android 4.3 and it seems that some of the bluetooth libraries were changed around 4.2, so on line 125 where a bluetooth socket is created in onResume():

btSocket = createBluetoothSocket(device);

needs to be changed to:

btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);

That allowed my program to work. Good luck!

[Reply] [Reply with quote]
↑ +1 ↓
klaus 2013-12-13 18:29:26
On a physical device I always get "socket closed" and app crash. on emulator I always get "BlueTooth not supported" and app crash..

[Reply] [Reply with quote]
↑ +3 ↓
ht 2013-12-08 05:24:05
All that was need was putting the ADMIN permission before the BLUETOOTH permission in the manifest file and everything works great!!!!

[Reply] [Reply with quote]
↑ 0 ↓
ht 2013-12-08 04:48:13
So my only problem now seems to be that I get this error: Check that the SPP UUID: 00001101-0000-1000-8000-00805f9b34fb exists on server. actually this error has come up before on the comment list, I checked my MAC address and it was correct (checked it with Blue Term) I did notice that when I run the program my tablet does not connect to the RN-42. Any help with this would be great.

[Reply] [Reply with quote]
↑ +2 ↓
ht 2013-12-05 20:00:54
I have compiled your code everything seems to compile correctly as soon as I run it though the program crashes. Have you ever seen this behavior before?

[Reply] [Reply with quote]
↑ -1 ↓
Issy 2013-12-10 00:06:09
make sure you've added the manifest permissions. That's usually the reason.

[Reply] [Reply with quote]
↑ +6 ↓
eimcian 2013-11-22 00:40:04
I am getting the error below...

[2013-11-21 15:38:26 - Dex Loader] Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.
[2013-11-21 15:38:26 - Bluetooth1] Conversion to Dalvik format failed: Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.

[Reply] [Reply with quote]
↑ +3 ↓
rush 2014-01-20 04:34:48
it means that the target sdk is not installed or the wrong compile settings are applied

[Reply] [Reply with quote]
↑ +3 ↓
Jay 2013-10-15 22:27:11
What program do I use to change the Bluetooth device address? I can load it into my Nexus 7, but it crashes since the Bluetooth device address is wrong.

[Reply] [Reply with quote]
↑ +3 ↓

Pages: [1] | [2] | [3] | [4] [Next] | [Last]

Leave a comment

Your name:
Your Email:

Comment:
Type the characters: *
captcha
Refresh

robe de demoiselle d honneur