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.

unknown 2015-03-29 18:38:57
thx for this. but how i can receive temperature from arduino ?

[Reply] [Reply with quote]
↑ 0 ↓
phamb587 2015-03-18 18:32:25
Hey admin!
I got the problem with my app that is done according to your guide
Fatal error-In resume() and an exception occurred during write:socket closed
Check that the SPP UUID
00001101-0000-1000-8000-00805f9b34fb exists on sever
What is this problem and how to solve it
Thanks!

[Reply] [Reply with quote]
↑ -1 ↓
rishdawg 2015-03-25 06:40:28
I'm getting this problem too, please help  :)

[Reply] [Reply with quote]
↑ 0 ↓
zehra 2015-03-13 19:29:23
Hi
I have questio if anyone can help me i need to do my Arduino UNO work wirelessly by using RN-171 WIFI shield and get the voltage of my circuit. anyone has idea how to code it?

[Reply] [Reply with quote]
↑ -1 ↓
nwell 2015-03-10 23:47:48
Works Great !
i have tested the receiving string part
w/ HC05 WBee Module + shield + Uno , compiled on Android Studio , Android Ver 5.0.1

Many Thanks !


[Reply] [Reply with quote]
↑ +2 ↓
Luqman 2015-01-18 01:22:50
Hi Admin... I am using Bluetooth HC05, i have problem for transfer data from android device:
im click button "LED ON" and i have message Toast "Turn on LED" but LED on arduino off

please help me

[Reply] [Reply with quote]
↑ +4 ↓
Luqman Khakim 2015-01-15 21:26:56
Hello Master... How Setting AT Command Bluetooth HC05 that data from arduino can received for android? please help me ...thanks

[Reply] [Reply with quote]
↑ +9 ↓
TIENMINHNGUYEN 2014-12-31 04:27:58
HI everyone !
- How to know this decree and where all numbers
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805 F9B34FB");
-----thank you

[Reply] [Reply with quote]
↑ +7 ↓
Mj 2014-12-23 18:38:27
How to set baud rate on android side ? On arduino side, you have chosen 9600 baud rate for UART but where we set the baud rate in android side, in case we want higher rate of data transmission.

Thanks for your tutorial  :) .

[Reply] [Reply with quote]
↑ +9 ↓
Ajay 2014-09-05 15:19:11
Hi....
I have used this code in one of my programs and i find that when i open the app without enabling bluetooth, there is a prompt to turn on bluetooth. However the app crashes without waiting for the bluetooth to turn on. However i dont face any issues when i run the app after turning on bluetooth. Any help regarding this is appreciated.

[Reply] [Reply with quote]
↑ +12 ↓
Alessandro 2014-08-29 17:32:21
Thank you very much!!
Only, I need to use SoftwareSerial library... so instead of using Serial.println("bla bla bla"), I us bluetooth.print("bla bla bla"), into my Arduino mega 2560 sketch. So android doesn't receive the Arduino message. Instead, the opposite works(commands to Arduino). Do you have any suggestion?
Thanks a lot!! :-D

[Reply] [Reply with quote]
↑ +8 ↓
Martin 2014-08-24 16:17:27
Hello,

now I found a solution to display values (e.g. from a sensor) at the droids screen in a proper way.

Just "take" the system-time in onCreate (or elsewhere) and update your screen at fixed rate. I called my variable "oneTick", see down below.

Hope this will help others  :)

code:
if ((oneTick + 300) < System.currentTimeMillis()) {
oneTick = System.currentTimeMillis();
textViewAlcValues.setText("Data: " + sbprint); // update TextView
}

[Reply] [Reply with quote]
↑ +7 ↓
aaron 2015-01-30 13:47:55
can you give me the full source code fo your program?
i need to display also values on android from arduino.
can you? please i really need it to my design project thanks a lot

[Reply] [Reply with quote]
↑ +1 ↓
Martin 2014-08-24 04:33:06
Hello brother,
for the most part I understand your code and the setup. But very strange things happen to my experiment... Only if I switch RX/TX at one device I will be able to use your code.
Do you know why this happens?

Thank you so much, your tutorials are quiet perfect.  :)

[Reply] [Reply with quote]
↑ +11 ↓
M 2014-08-19 06:47:34
Hello once again. I solved my problem by appending data in thread, not handler. I see now that the handler can be delayed and simply miss data, or even start to display existing data while thread is overwriting it. I still call the handler each time data is received simply to tell it to send text to gui.

[Reply] [Reply with quote]
↑ +12 ↓
M 2014-08-19 04:32:34
Further to my previous comment, it appears that the code receives the data perfectly according to output log in Eclipse. The issue is transferring the data to the handler.

[Reply] [Reply with quote]
↑ +8 ↓
M 2014-08-19 03:54:06
Firstly thank you very much for posting this example code. It has been very helpful.

Secondly, I have a problem appending data in the handler. Maybe a race condition, or buffer clear issue as it will occasionally skip information or display it wrong. My small modification to your code basically removes endOfLineIndex and continually appends data but I get the following example output:


trimpot = 166
trimpot = 167
trimpot = 166
trimpot =
6
trimpot = 163
trimpot = 6
rrimpot =
6
t
62 ot =
62
trimpot =
66


I notice the issue with your original code (BTW I am not using Arduino but my microcontroller works fine with BlueTerm). Is this a known issue? I cannot see anything wrong with your code, but I am very new to Android. Help appreciated!

M

[Reply] [Reply with quote]
↑ +7 ↓
John Michael Clarin 2014-08-14 09:08:45
sir, are you using Eclipse IDE or Processing IDE?

[Reply] [Reply with quote]
↑ +10 ↓
Phalguni 2014-07-11 18:38:09
Hi grum,
Thanking you u done good job.God bless you  :like:

[Reply] [Reply with quote]
↑ +13 ↓
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]
↑ +10 ↓
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]
↑ +10 ↓
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]
↑ +8 ↓

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

Leave a comment

Your name:
Your Email:

Comment:
Type the characters: *
captcha
Refresh