You are on page 1of 53

Anrdroid Send/Receive Data With Arduino Via

Bluetooth – Part 1
APRIL 7, 2014/WINGOODHARRY

In the last three posts I went through the basic steps to send data from an Android device to an Arduino using a
bluetooth serial module. That was fun and all but it would be better if the Arduino could send data back to the
Android device. With functionality like that there a lot more plausible uses for the technology. For this example
I am going to go through the steps to make a 4 channel voltage logger but with a few minor changes this could
be used to send/receive practically anything.

All files used are available on GitHub here.


Like last time, lets get the Arduino stuff out of the way first. For this project I have made a simple sketch and
circuit that takes four analog inputs A0-A3 and then converts the values to 2dp float voltage values. The values
are then displayed on the LCD screen and transmitted on the serial port (in our case, it is going to a Bluetooth
module but for testing the serial port utility on the Arduino IDE will do for now). This process happens every
2000ms so that it is easy to follow what is happening. And just so we know that comms are being established
both ways I have put in the ability to change the state of the built in LED on pin 13 on/off. Pretty standard
wiring but here is a diagram incase you are unsure. I actually used a 4×20 LCD screen but the pin outs are
usually the same or very similar and code is very easy to change for 2×16 etc. Also decided to use an Arduino
Nano for this – love it!
Below is the sketch for the Arduino. It serves three simple functions:
1. Reads in sensor values from A0-A3 and converts them to float values in the range 0-5. So if 5V is put on A0,
the sensor will be at 1023 which is converted with a mathematical function to 5.00.

2. Prints the converted values of the sensors on to an LCD screen. I used a 4×20 but if you use a smaller screen
you should only need to change a few lines of code.

3. Sends converted sensor values over serial to another device, in this instance the bluetooth module. Using a set
of print statements and a for loop the data string will look something like this #1.23+2.34+3.23+2.43+~ The ‘#’
and ‘~’ are used by the Android app to determine the validity and length of the incoming string, as it knows ~ is
the end. From here it can find the values of the four sensors using string methods. I used ‘+’ to separate the
values for my own benefit, as it makes things clearer to see on hyperterminal etc, they aren’t needed for any
other reason.

1 #include <LiquidCrystal.h>
2
int led = 13;
3 LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
4 // Pins used for inputs and outputs**************************************************
5 const int analogInPin0 = A0;// Analog input pins
6 const int analogInPin1 = A1;
7 const int analogInPin2 = A2;
const int analogInPin3 = A3;
8
9 //Arrays for the 4 inputs**********************************************
10 float sensorValue[4] = {0,0,0,0};
11 float voltageValue[4] = {0,0,0,0};
12
13 //Char used for reading in Serial characters
char inbyte = 0;
14 //***********************************************************************************
15
16 void setup() {
17 // initialise serial communications at 9600 bps:
18 Serial.begin(9600);
lcd.begin(20, 4); //change to 16, 2 for smaller 16x2 screens
19 pinMode(led, OUTPUT);
20 digitalWrite(led, HIGH);
21 }
22
23 void loop() {
24 readSensors();
getVoltageValue();
25 printLCD();
26 sendAndroidValues();
27 //when serial values have been received this will be true
28 if (Serial.available() > 0)
{
29 inbyte = Serial.read();
30 if (inbyte == '0')
31 {
32 //LED off
33 digitalWrite(led, LOW);
}
34 if (inbyte == '1')
35 {
36 //LED on
37 digitalWrite(led, HIGH);
38 }
}
39 //delay by 2s. Meaning we will be sent values every 2s approx
40 //also means that it can take up to 2 seconds to change LED state
41 delay(2000);
42 }
43
void readSensors()
44 {
45 // read the analog in value to the sensor array
46 sensorValue[0] = analogRead(analogInPin0);
47 sensorValue[1] = analogRead(analogInPin1);
48 sensorValue[2] = analogRead(analogInPin2);
sensorValue[3] = analogRead(analogInPin3);
49 }
50 //sends the values from the sensor over serial to BT module
51 void sendAndroidValues()
52 {
//puts # before the values so our app knows what to do with the data
53 Serial.print('#');
54 //for loop cycles through 4 sensors and sends values via serial
55 for(int k=0; k<4; k++)
56 {
57 Serial.print(voltageValue[k]);
Serial.print('+');
58 //technically not needed but I prefer to break up data values
59 //so they are easier to see when debugging
60 }
61 Serial.print('~'); //used as an end of transmission character - used in app for stri
62 length
Serial.println();
63 delay(10); //added a delay to eliminate missed transmissions
64 }
65
66 void printLCD()
67 {
68 for{
(int i = 0; i<4; i++) //change 4 to 2 if using small screen
69 lcd.setCursor(0, i);
70 lcd.write("Sensor");
71 lcd.setCursor(7, i);
72 lcd.print(i);
lcd.setCursor(8, i);
73 lcd.print(" = ");
74 lcd.setCursor(11, i);
75 lcd.print(voltageValue[i]);
76 lcd.setCursor(15, i);
77 } lcd.print("V");
78
79 }
80 void getVoltageValue()
81 {
82 for (int x = 0; x < 4; x++)
{
83 voltageValue[x] = ((sensorValue[x]/1023)*5);
84 }
85 }
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
Load that sketch on to your Arduino and power it all up. The voltage values should display on the screen if all
ok. Put a lead from any of the pins A0-3 to 5V to check the sensors work correctly and the screen updates the
results. Momentarily disconnect the bluetooth module Tx and Rx from the Arduino and open the serial monitor
in the Arduino IDE. You should see the voltage values being transmitted every 2 seconds in the form
#1.23+1.54………~. Just send a 1 and a 0 back to the Arduino from the monitor to check the LED on pin 13
turns on/off and that is the Arduino side done and proved working. Mine looked like this:

Not the neatest of things but it worked for me! On to the Android part in part 2.
Android Send/Receive data with Arduino using
Bluetooth – Part 2
APRIL 15, 2014/WINGOODHARRY

To get things moving along quickly I am going to use the same activity that I used in the last blog to find my
paired devices. This can be found here. Only one thing will change and that is the activity name. Call it
DeviceListActivity, as it is no longer the main activity.
import java.util.Set;
1 import android.app.Activity;
2 import android.bluetooth.BluetoothAdapter;
3 import android.bluetooth.BluetoothDevice;
4 import android.content.Intent;
import android.os.Bundle;
5 import android.util.Log;
6 import android.view.View;
7 import android.widget.AdapterView;
8 import android.widget.ArrayAdapter;
import android.widget.Button;
9 import android.widget.ListView;
10 import android.widget.TextView;
11 import android.widget.Toast;
12 import android.widget.AdapterView.OnItemClickListener;
13
14
15 public class DeviceListActivity extends Activity {
// Debugging for LOGCAT
16 private static final String TAG = "DeviceListActivity";
17 private static final boolean D = true;
18
19
20 // declare button for launching website and textview for connection status
21 Button tlbutton;
22 TextView textView1;
23
// EXTRA string to send on to mainactivity
24 public static String EXTRA_DEVICE_ADDRESS = "device_address";
25
26 // Member fields
27 private BluetoothAdapter mBtAdapter;
28 private ArrayAdapter<String> mPairedDevicesArrayAdapter;
29
@Override
30 protected void onCreate(Bundle savedInstanceState) {
31 super.onCreate(savedInstanceState);
32 setContentView(R.layout.device_list);
33 }
34
35 @Override
public void onResume()
36 {
37 super.onResume();
38 //***************
39 checkBTState();
40
41 textView1 = (TextView) findViewById(R.id.connecting);
textView1.setTextSize(40);
42 textView1.setText(" ");
43
44 // Initialize array adapter for paired devices
mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device
45
46 // Find and set up the ListView for paired devices
47 ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
48 pairedListView.setAdapter(mPairedDevicesArrayAdapter);
49 pairedListView.setOnItemClickListener(mDeviceClickListener);
50
// Get the local Bluetooth adapter
51 mBtAdapter = BluetoothAdapter.getDefaultAdapter();
52
53 // Get a set of currently paired devices and append to 'pairedDevices'
54 Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
55
56 // Add previosuly paired devices to the array
57 if (pairedDevices.size() > 0) {
findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);//
58 for (BluetoothDevice device : pairedDevices) {
59 mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.get
60 }
61 } else {
String noDevices = getResources().getText(R.string.none_paired).toStri
62 mPairedDevicesArrayAdapter.add(noDevices);
63 }
64 }
65
66 // Set up on-click listener for the list (nicked this - unsure)
67 private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {
68
69 textView1.setText("Connecting...");
70 // Get the device MAC address, which is the last 17 chars in the View
71 String info = ((TextView) v).getText().toString();
72 String address = info.substring(info.length() - 17);
73
74 // Make an intent to start next activity while taking an extra which i
Intent i = new Intent(DeviceListActivity.this, MainActivity.class);
75 i.putExtra(EXTRA_DEVICE_ADDRESS, address);
76 startActivity(i);
77 }
78 };
79
private void checkBTState() {
80 // Check device has Bluetooth and that it is turned on
81 mBtAdapter=BluetoothAdapter.getDefaultAdapter(); // CHECK THIS OUT THAT I
82 if(mBtAdapter==null) {
83 Toast.makeText(getBaseContext(), "Device does not support Bluetooth",
84 Toast.LENGTH_SHORT).show();
} else {
85 if (mBtAdapter.isEnabled()) {
86 Log.d(TAG, "...Bluetooth ON...");
87 } else {
88 //Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENAB
89 startActivityForResult(enableBtIntent, 1);
90
91 }
92 }
93 }
}
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
Also make sure that you update your permissions in the manifest to allow bluetooth (and the DeviceListActivity
name if you didn’t start a new project from part 1).

1 <?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
package="com.example.arduinosensors"
3 android:versionCode="1"
4 android:versionName="1.0" >
5
6 <uses-sdk
7 android:minSdkVersion="8"
android:targetSdkVersion="17" />
8 <uses-permission android:name="android.permission.BLUETOOTH"/>
9 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
10
11 <application
12 android:allowBackup="true"
13 android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
14 android:theme="@style/AppTheme" >
15 <activity
16 android:name="com.example.arduinosensors.MainActivity"
17 android:label="@string/app_name"
18 android:screenOrientation="portrait" >
19
20 </activity>
<activity
21 android:name="com.example.arduinosensors.DeviceListActivity"
22 android:label="@string/app_name"
23 android:screenOrientation="portrait" >
24 <intent-filter>
<action android:name="android.intent.action.MAIN" />
25
26 <category
27 android:name="android.intent.category.LAUNCHER" />
28 </intent-filter>
29 </activity>
30 </application>
31
</manifest>
32
33
34
35
36
Now on to the new stuff! We are making an activity that will allow us to turn on/off an LED on the Arduino as
well as receive data via bluetooth. When finished it will look like the image below.
As we are sending and receiving data this time through Bluetooth rather than just sending there are a few more
things to take care of.
First of all is the fact that we cannot simply wait for a bluetooth message to come along on the main thread of
our activity. If we did we would most likely get an ‘Application Not Responding’ message. So we need to run a
new thread for the bluetooth data receiving to take place on, as well as a handler to update the UI when relevant
data has been received. To get a better idea of how threads and handlers work read this.
Another thing to concern ourselves with may be that we are now getting data in from our Arduino. What do we
do with it!!!! If you remember from part 1, the data will be arriving in the form: #1.23+2.34+3.23+2.43+~ So
from this we can use the fact that ~ is the last character, therefore the end of that transmission. # is the beginning
of the transmission so we can say if the first character of the string is # we are good to go on reading the data.
Finally we can work out where our data is in the string from #. The data for sensor 0 will be at elements 1-5 in
the string so we can extract what we need with the use of substring. This procedure is repeated for the remaining
three sensors. With that information now acquired we can use setText to display the sensor values in the
corresponding textViews.

You will also notice I have added two textViews at the bottom of the app that display the actual data string
received from the Arduino sensors. The other view shows the length of the string received, ideally this should be
21 every time. I put this in while debugging but thought it was useful. I have tried to comment a fair bit in the
code below so it is clear what part is doing what. However, if you have any questions feel free to send me a
message. So create a new blank activity and layout file and add the following code. Your manifest should
update automatically referencing the new activity. First off is the xml layout file:

1 <RelativeLayout
2 xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:paddingBottom="@dimen/activity_vertical_margin"
6 android:paddingLeft="@dimen/activity_horizontal_margin"
7 android:paddingRight="@dimen/activity_horizontal_margin"
8 android:paddingTop="@dimen/activity_vertical_margin" >
9
<TextView
10 android:id="@+id/testView1"
11 android:layout_width="wrap_content"
12 android:layout_height="wrap_content"
13 android:layout_above="@+id/txtString"
android:text=""
14 android:textSize="15sp" />
15
16 <TextView
17 android:id="@+id/txtString"
18 android:layout_width="wrap_content"
19 android:layout_height="50dp"
android:layout_alignLeft="@+id/testView1"
20 android:layout_alignParentBottom="true"
21 android:text=""
22 android:textSize="15sp" />
23
24 <Button
25 android:id="@+id/buttonOn"
26 android:layout_width="wrap_content"
android:layout_height="wrap_content"
27 android:layout_alignParentLeft="true"
28 android:layout_alignParentTop="true"
29 android:text="LED ON" />
30
31 <Button
android:id="@+id/buttonOff"
32 android:layout_width="wrap_content"
33 android:layout_height="wrap_content"
34 android:layout_alignBottom="@+id/buttonOn"
35 android:layout_alignParentRight="true"
36 android:text="LED OFF" />
37
<TextView
38 android:id="@+id/sensorView1"
39 android:layout_width="wrap_content"
40 android:layout_height="wrap_content"
41 android:layout_below="@+id/sensorView0"
android:layout_centerHorizontal="true"
42 android:text="Sensor 1 Voltage = ????"
43 android:textAppearance="?android:attr/textAppearanceMedium" />
44
45 <TextView
46 android:id="@+id/sensorView2"
47 android:layout_width="wrap_content"
android:layout_height="wrap_content"
48 android:layout_below="@+id/sensorView1"
49 android:layout_centerHorizontal="true"
50 android:text="Sensor 2 Voltage = ????"
51 android:textAppearance="?android:attr/textAppearanceMedium" />
52
53 <TextView
android:id="@+id/sensorView3"
54 android:layout_width="wrap_content"
55 android:layout_height="wrap_content"
56 android:layout_below="@+id/sensorView2"
57 android:layout_centerHorizontal="true"
android:text="Sensor 3 Voltage = ????"
58 android:textAppearance="?android:attr/textAppearanceMedium" />
59
60 <TextView
61 android:id="@+id/sensorView0"
62 android:layout_width="wrap_content"
63 android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
64 android:layout_marginTop="196dp"
65 android:text="Sensor 0 Voltage = ????"
66 android:textAppearance="?android:attr/textAppearanceMedium" />
67
68 </RelativeLayout>
69
70
71
72
73
74
75
76
77
78
79
And now the java…

1 package com.example.arduinosensors;
2
3 import java.io.IOException;
import java.io.InputStream;
4 import java.io.OutputStream;
5 import java.util.UUID;
6 import android.app.Activity;
7 import android.bluetooth.BluetoothAdapter;
8 import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
9 import android.content.Intent;
10 import android.os.Bundle;
11 import android.os.Handler;
12 import android.view.View;
import android.view.View.OnClickListener;
13 import android.widget.Button;
14 import android.widget.TextView;
15 import android.widget.Toast;
16
17 public class MainActivity extends Activity {
18
19 Button btnOn, btnOff;
TextView txtArduino, txtString, txtStringLength, sensorView0, sensorView1, senso
20 Handler bluetoothIn;
21
22 final int handlerState = 0; //used to identify handler mes
23 private BluetoothAdapter btAdapter = null;
24 private BluetoothSocket btSocket = null;
private StringBuilder recDataString = new StringBuilder();
25
26
private ConnectedThread mConnectedThread;
27
28 // SPP UUID service - this should work for most devices
29 private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-
30
31 // String for MAC address
32 private static String address;
33
@Override
34 public void onCreate(Bundle savedInstanceState) {
35 super.onCreate(savedInstanceState);
36
37 setContentView(R.layout.activity_main);
38
39 //Link the buttons and textViews to respective views
40 btnOn = (Button) findViewById(R.id.buttonOn);
btnOff = (Button) findViewById(R.id.buttonOff);
41 txtString = (TextView) findViewById(R.id.txtString);
42 txtStringLength = (TextView) findViewById(R.id.testView1);
43 sensorView0 = (TextView) findViewById(R.id.sensorView0);
44 sensorView1 = (TextView) findViewById(R.id.sensorView1);
45 sensorView2 = (TextView) findViewById(R.id.sensorView2);
sensorView3 = (TextView) findViewById(R.id.sensorView3);
46
47 bluetoothIn = new Handler() {
48 public void handleMessage(android.os.Message msg) {
49 if (msg.what == handlerState) { //i
50 String readMessage = (String) msg.obj;
connect thread
51 recDataString.append(readMessage);
52 int endOfLineIndex = recDataString.indexOf("~");
53 if (endOfLineIndex > 0) {
54 String dataInPrint = recDataString.substring(0, endOfLineIndex
55 txtString.setText("Data Received = " + dataInPrint);
int dataLength = dataInPrint.length();
56 txtStringLength.setText("String Length = " + String.valueOf(dat
57
58 if (recDataString.charAt(0) == '#')
59 {
60 String sensor0 = recDataString.substring(1, 5);
String sensor1 = recDataString.substring(6, 10);
61 String sensor2 = recDataString.substring(11, 15);
62 String sensor3 = recDataString.substring(16, 20);
63
64 sensorView0.setText(" Sensor 0 Voltage = " + sensor0 + "V")
65 sensorView1.setText(" Sensor 1 Voltage = " + sensor1 + "V")
66 sensorView2.setText(" Sensor 2 Voltage = " + sensor2 + "V")
sensorView3.setText(" Sensor 3 Voltage = " + sensor3 + "V")
67 }
68 recDataString.delete(0, recDataString.length());
69 // strIncom =" ";
70 dataInPrint = " ";
71 }
}
72 }
73 };
74
75 btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapt
76 checkBTState();
77
// Set up onClick listeners for buttons to send 1 or 0 to turn on/off LED
78 btnOff.setOnClickListener(new OnClickListener() {
79 public void onClick(View v) {
80 mConnectedThread.write("0"); // Send "0" via Bluetooth
81 Toast.makeText(getBaseContext(), "Turn off LED", Toast.LENGTH_SHORT).show(
82 }
});
83
84 btnOn.setOnClickListener(new OnClickListener() {
85 public void onClick(View v) {
86 mConnectedThread.write("1"); // Send "1" via Bluetooth
87 Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show()
}
88 });
89 }
90
91 private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOEx
92
93 return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
94 //creates secure outgoing connecetion with BT device using UUID
95 }
96
@Override
97 public void onResume() {
98 super.onResume();
99
100 //Get MAC address from DeviceListActivity via intent
101 Intent intent = getIntent();
102
//Get the MAC address from the DeviceListActivty via EXTRA
103 address = intent.getStringExtra(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
104
105 //create device and set the MAC address
106 BluetoothDevice device = btAdapter.getRemoteDevice(address);
107
108 try {
109 btSocket = createBluetoothSocket(device);
} catch (IOException e) {
110 Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_LO
111 }
112 // Establish the Bluetooth socket connection.
113 try
{
114 btSocket.connect();
115 } catch (IOException e) {
116 try
117 {
118 btSocket.close();
} catch (IOException e2)
119 {
120 //insert code to deal with this
121 }
122 }
123 mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
124
125 //I send a character when resuming.beginning transmission to check device is c
126 //If it is not an exception will be thrown in the write method and finish() wi
127 mConnectedThread.write("x");
128 }
129
@Override
130 public void onPause()
131 {
132 super.onPause();
133 try
134 {
//Don't leave Bluetooth sockets open when leaving activity
135 btSocket.close();
136 } catch (IOException e2) {
137 //insert code to deal with this
138 }
}
139
140 //Checks that the Android device Bluetooth is available and prompts to be turned
141 private void checkBTState() {
142
143 if(btAdapter==null) {
144 Toast.makeText(getBaseContext(), "Device does not support bluetooth", Toas
145 } else {
if (btAdapter.isEnabled()) {
146 } else {
147 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
148 startActivityForResult(enableBtIntent, 1);
149 }
}
150 }
151
152 //create new class for connect thread
153 private class ConnectedThread extends Thread {
154 private final InputStream mmInStream;
155 private final OutputStream mmOutStream;
156
//creation of the connect thread
157 public ConnectedThread(BluetoothSocket socket) {
158 InputStream tmpIn = null;
159 OutputStream tmpOut = null;
160
161 try {
//Create I/O streams for connection
162 tmpIn = socket.getInputStream();
163 tmpOut = socket.getOutputStream();
164 } catch (IOException e) { }
165
166 mmInStream = tmpIn;
167 mmOutStream = tmpOut;
}
168
169 public void run() {
170 byte[] buffer = new byte[256];
171 int bytes;
172
173 // Keep looping to listen for received messages
174 while (true) {
try {
175 bytes = mmInStream.read(buffer); //read bytes from
176 String readMessage = new String(buffer, 0, bytes);
177 // Send the obtained bytes to the UI Activity via handler
178 bluetoothIn.obtainMessage(handlerState, bytes, -1, readMessage
} catch (IOException e) {
179 break;
180 }
181 }
182 }
183 //write method
public void write(String input) {
184 byte[] msgBuffer = input.getBytes(); //converts entered Stri
185 try {
186 mmOutStream.write(msgBuffer); //write bytes over BT
187 } catch (IOException e) {
//if you cannot write, close the application
188 Toast.makeText(getBaseContext(), "Connection Failure", Toast.LENGT
189 finish();
190
191 }
192 }
193 }
}
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
One small thing to add. I used to send the buffer from my run method in the connectThread but found that I
would sometimes get garbled data with anything but slow data rates. It turns out this was because the buffer was
getting full and struggling to keep up. A much better method is to create a string in the run method from the
buffer and then send that to the UI thread via the handler.

Turn on your Arduino and bluetooth module and run your Android app. If all goes well your sensor values will
go from ? to voltage values. If I have missed anything give me a shout.

Just a reminder that all files used are available on GitHub here.
I used these blogs to make this project:

http://english.cxem.net/arduino/arduino5.php
http://bellcode.wordpress.com/2012/01/02/android-and-arduino-bluetooth-communication/
Android to Arduino Data Send via Bluetooth Serial –
Part 3
MARCH 16, 2014/WINGOODHARRY

Now to make our app actually do something useful with out BT enabled Arduino. Before we make the new
activity a few changes must be made to the Device List activity to support the new activity we are about to
make.

First, an intent EXTRA is needed to take the chosen device’s MAC address to the next activity. Just put this
with all the the other declarations at the top of the class

1 //An EXTRA to take the device MAC to the next activity


2 public static String EXTRA_DEVICE_ADDRESS;
An onClick listener will then be added for the list view so that a device can be selected from the list. Inside the
method triggered by the list selection the BT device MAC address will be parsed from the data in the listview
and a new Intent will be instantiated to call the ArduinoMain activity. I put this at the bottom of my
DeviceListActivity class.

1
2 private OnItemClickListener mDeviceClickListener = new OnItemClickListener()
{
3 public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3)
4 {
5 textConnectionStatus.setText("Connecting...");
6 // Get the device MAC address, which is the last 17 chars in the View
String info = ((TextView) v).getText().toString();
7 String address = info.substring(info.length() - 17);
8
9 // Make an intent to start next activity while taking an extra which is
10 address.
11 Intent i = new Intent(DeviceListActivity.this, ArduinoMain.class);
12 i.putExtra(EXTRA_DEVICE_ADDRESS, address);
startActivity(i);
13 }
14 };
15
Lastly we need to attach the new onClick listener to the list view so the Listview set up in onCreate should look
like the below. (add the bottom line to your code, nothing else has changed)

1 // Find and set up the ListView for paired devices


ListView pairedListView = (ListView)
2 findViewById(R.id.paired_devices);
3 pairedListView.setAdapter(mPairedDevicesArrayAdapter);
4 pairedListView.setOnItemClickListener(mDeviceClickListener);
That is Device List activity done so on to the new activity. But just in case you are unsure here is the finished
code.

package com.example.simplebluetooth;
1
2 import java.util.Set;
3 import android.app.Activity;
4 import android.bluetooth.BluetoothAdapter;
5 import android.bluetooth.BluetoothDevice;
import android.content.Intent;
6 import android.os.Bundle;
7 import android.view.View;
8 import android.widget.AdapterView;
9 import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
10 import android.widget.ListView;
11 import android.widget.TextView;
12 import android.widget.Toast;
13
14 public class DeviceListActivity extends Activity {
15
16 // textview for connection status
TextView textConnectionStatus;
17 ListView pairedListView;
18
19 //An EXTRA to take the device MAC to the next activity
20 public static String EXTRA_DEVICE_ADDRESS;
21
22 // Member fields
23 private BluetoothAdapter mBtAdapter;
private ArrayAdapter<String> mPairedDevicesArrayAdapter;
24
25 @Override
26 protected void onCreate(Bundle savedInstanceState)
27 {
28 super.onCreate(savedInstanceState);
29 setContentView(R.layout.activity_device_list);
30
textConnectionStatus = (TextView) findViewById(R.id.connecting);
31 textConnectionStatus.setTextSize(40);
32
33 // Initialize array adapter for paired devices
34 mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device
35
36 // Find and set up the ListView for paired devices
37 pairedListView = (ListView) findViewById(R.id.paired_devices);
pairedListView.setOnItemClickListener(mDeviceClickListener);
38 pairedListView.setAdapter(mPairedDevicesArrayAdapter);
39
40 }
41
42 @Override
43 public void onResume()
44 {
super.onResume();
45 //It is best to check BT status at onResume in case something has changed wh
46 checkBTState();
47
48 mPairedDevicesArrayAdapter.clear();// clears the array so items aren't dupli
49 onPause
50
textConnectionStatus.setText(" "); //makes the textview blank
51
52
// Get the local Bluetooth adapter
53 mBtAdapter = BluetoothAdapter.getDefaultAdapter();
54
55 // Get a set of currently paired devices and append to pairedDevices list
56 Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
57
// Add previously paired devices to the array
58 if (pairedDevices.size() > 0) {
59 findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);//ma
60 for (BluetoothDevice device : pairedDevices) {
61 mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAd
62 }
} else {
63 mPairedDevicesArrayAdapter.add("no devices paired");
64 }
65 }
66
67 //method to check if the device has Bluetooth and if it is on.
//Prompts the user to turn it on if it is off
68 private void checkBTState()
69 {
70 // Check device has Bluetooth and that it is turned on
71 mBtAdapter=BluetoothAdapter.getDefaultAdapter(); // CHECK THIS OUT
72 if(mBtAdapter==null) {
Toast.makeText(getBaseContext(), "Device does not support Bluetooth
73 Toast.LENGTH_SHORT).show();
74 finish();
75 } else {
76 if (!mBtAdapter.isEnabled()) {
//Prompt user to turn on Bluetooth
77
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENAB
78 startActivityForResult(enableBtIntent, 1);
79 }
80 }
81 }
82
// Set up on-click listener for the listview
83 private OnItemClickListener mDeviceClickListener = new OnItemClickListener()
84 {
85 public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3)
86 {
87 textConnectionStatus.setText("Connecting...");
// Get the device MAC address, which is the last 17 chars in the View
88 String info = ((TextView) v).getText().toString();
89 String address = info.substring(info.length() - 17);
90
91 // Make an intent to start next activity while taking an extra which i
92 Intent i = new Intent(DeviceListActivity.this, ArduinoMain.class);
i.putExtra(EXTRA_DEVICE_ADDRESS, address);
93
startActivity(i);
94 }
95 };
96
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
Create a new, blank Android activity in eclipse and name it ArduinoMain. All other things remain default. Open
the layout file for the activity (this should be acticity_arduino_main). All we really need at first is two buttons
for functions 1 & 2, and an editText field to enter text we want to send to the LCD screen. Add these features to
the xml file so it looks like the one below.

1 <RelativeLayout
2 xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:paddingBottom="@dimen/activity_vertical_margin"
6 android:paddingLeft="@dimen/activity_horizontal_margin"
7 android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
8
tools:context=".ArduinoMain" >
9
10 <EditText
11 android:id="@+id/editText1"
12 android:layout_width="fill_parent"
13 android:layout_height="wrap_content"
android:layout_marginTop="0dp"
14 android:layout_weight="2"
15 android:ems="10"
16 android:hint="Enter some text"
17 android:imeOptions="actionSend"
18 android:singleLine="true" />
19
<Button
20 android:id="@+id/functionOne"
21 android:layout_width="wrap_content"
22 android:layout_height="wrap_content"
23 android:layout_centerHorizontal="true"
android:layout_marginTop="104dp"
24 android:text="Function 1" />
25
26 <Button
27 android:id="@+id/functionTwo"
28 android:layout_width="wrap_content"
29 android:layout_height="wrap_content"
android:layout_alignLeft="@+id/functionOne"
30 android:layout_below="@+id/functionOne"
31 android:layout_marginTop="67dp"
32 android:text="Function 2" />
33
34 </RelativeLayout>
35
36
37
38
39
If you have a look at the editText attributes you will see I have opted to include a send key on the soft keyboard.
This way we don’t need to waste a button on sending our text! It will all look like the below when finished. Note
that I have optimised this for a Nexus 7.
Now on to the Arduino Main activity java file. Open it up (src/com.example…) and get ready to get coding. To
set up a Bluetooth connection we need to do a few things:

1. Initialise the buttons and add onClick listeners

2. Set a pointer to the BT device using its MAC address

3. Open a BT socket for communication with the BT device.

4. Create a data outstream so we can send data to the BT device.

5. Create a method to send data down the outstream.

6. Tidy up the process with proper use of onResume, onPause so that the BT connection is not wasting
resources.

Before looking at the code below I would strongly recommend looking at the Android Developer Bluetooth
documentation. It gives clear instruction on how communication is made. Its very helpful, they are Google after
all. But without further delay lets write this activity!
Below is the code for the ArduinoMain activity. As usual I have commented in the code to show what is going
on but send me any questions if it isn’t clear.

1 package com.example.simplebluetooth;
2
import java.io.IOException;
3
4
import java.io.OutputStream;
5 import java.util.UUID;
6
7 import android.app.Activity;
8 import android.bluetooth.BluetoothAdapter;
9 import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
10 import android.content.Intent;
11 import android.os.Bundle;
12 import android.view.KeyEvent;
13 import android.view.View;
14 import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
15 import android.widget.Button;
16 import android.widget.EditText;
17 import android.widget.Toast;
18
19 public class ArduinoMain extends Activity {
20
//Declare buttons & editText
21 Button functionOne, functionTwo;
22
23 private EditText editText;
24
25 //Memeber Fields
26 private BluetoothAdapter btAdapter = null;
27 private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
28
29 // UUID service - This is the type of Bluetooth device that the BT module is
30 // It is very likely yours will be the same, if not google UUID for your manufactur
31 private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9
32
33 // MAC-address of Bluetooth module
public String newAddress = null;
34
35 /** Called when the activity is first created. */
36 @Override
37 public void onCreate(Bundle savedInstanceState) {
38 super.onCreate(savedInstanceState);
39 setContentView(R.layout.activity_arduino_main);
40
addKeyListener();
41
42 //Initialising buttons in the view
43 //mDetect = (Button) findViewById(R.id.mDetect);
44 functionOne = (Button) findViewById(R.id.functionOne);
45 functionTwo = (Button) findViewById(R.id.functionTwo);
46
//getting the bluetooth adapter value and calling checkBTstate function
47 btAdapter = BluetoothAdapter.getDefaultAdapter();
48 checkBTState();
49
50 /********************************************************************************
51 * Buttons are set up with onclick listeners so when pressed a method is called
52 * In this case send data is called with a value and a toast is made
* to give visual feedback of the selection made
53 */
54
55 functionOne.setOnClickListener(new OnClickListener() {
56 public void onClick(View v) {
57 sendData("1");
58 Toast.makeText(getBaseContext(), "Function 1", Toast.LENGTH_SHORT).show();
}
59 });
60
61 functionTwo.setOnClickListener(new OnClickListener() {
62 public void onClick(View v) {
63 sendData("2");
Toast.makeText(getBaseContext(), "Function 2", Toast.LENGTH_SHORT).show();
64 }
65 });
66 }
67
68 @Override
69 public void onResume() {
super.onResume();
70 // connection methods are best here in case program goes into the background etc
71
72 //Get MAC address from DeviceListActivity
73 Intent intent = getIntent();
74 newAddress = intent.getStringExtra(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
75
76 // Set up a pointer to the remote device using its address.
77 BluetoothDevice device = btAdapter.getRemoteDevice(newAddress);
78
//Attempt to create a bluetooth socket for comms
79 try {
80 btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
81 } catch (IOException e1) {
82 Toast.makeText(getBaseContext(), "ERROR - Could not create Bluetooth socket",
}
83
84 // Establish the connection.
85 try {
86 btSocket.connect();
87 } catch (IOException e) {
88 try {
btSocket.close(); //If IO exception occurs attempt to close socket
89 } catch (IOException e2) {
90 Toast.makeText(getBaseContext(), "ERROR - Could not close Bluetooth socket"
91 }
92 }
93
// Create a data stream so we can talk to the device
94 try {
95 outStream = btSocket.getOutputStream();
96 } catch (IOException e) {
97 Toast.makeText(getBaseContext(), "ERROR - Could not create bluetooth outstrea
98 }
//When activity is resumed, attempt to send a piece of junk data ('x') so that it
99 // i.e don't wait for a user to press button to recognise connection failure
100 sendData("x");
101 }
102
103 @Override
104 public void onPause() {
super.onPause();
105 //Pausing can be the end of an app if the device kills it or the user doesn't ope
106 //close all connections so resources are not wasted
107
108 //Close BT socket to device
109 try {
110 btSocket.close();
} catch (IOException e2) {
111 Toast.makeText(getBaseContext(), "ERROR - Failed to close Bluetooth socket",
112 }
113 }
114 //takes the UUID and creates a comms socket
115 private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOExcep
116
117 return device.createRfcommSocketToServiceRecord(MY_UUID);
}
118
119 //same as in device list activity
120 private void checkBTState() {
121 // Check device has Bluetooth and that it is turned on
122 if(btAdapter==null) {
123 Toast.makeText(getBaseContext(), "ERROR - Device does not support bluetooth",
finish();
124 } else {
125 if (btAdapter.isEnabled()) {
126 } else {
127 //Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
128 startActivityForResult(enableBtIntent, 1);
129 }
130 }
131 }
132
// Method to send data
133 private void sendData(String message) {
134 byte[] msgBuffer = message.getBytes();
135
136 try {
137 //attempt to place data on the outstream to the BT device
138 outStream.write(msgBuffer);
} catch (IOException e) {
139 //if the sending fails this is most likely because device is no longer there
140 Toast.makeText(getBaseContext(), "ERROR - Device not found", Toast.LENGTH_SHOR
141 finish();
142 }
}
143 public void addKeyListener() {
144
145 // get edittext component
146 editText = (EditText) findViewById(R.id.editText1);
147
148 // add a keylistener to keep track user input
149 editText.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
150
151 // if keydown and send is pressed implement the sendData method
152 if ((keyCode == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent
153 //I have put the * in automatically so it is no longer needed when en
154 sendData('*' + editText.getText().toString());
155 Toast.makeText(getBaseContext(), "Sending text", Toast.LENGTH_SHORT).
156
return true;
157 }
158
159 return false;
160 }
161 });
}
162
163}
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
Now you have all that completed lets give it a go! Turn on your Arduino with the the BT module connected and
code loaded up. Plug in your Android device to your PC/mac and run the project. Select your BT serial device
from the paired list in the app and a new activity should open with two buttons and an editTextbox. Give it a go
and send some text and it should pop up on the LCD screen. If so, give the buttons a press and make sure they
trigger functions one and two.

There are obviously plenty of things that can be done with this type of functionality (remotes etc) so get adding
buttons and extra functions to the Arduino. In The next article we will switch things up a bit though and add
receiving comms to the app, which is a bit more fun (tricky).

Comment if there are any errors or if some bits need expanding upon, as when this was written I was the only
audience.
ANDROID, ARDUINO

DATA TRANSFER BETWEEN ANDROID AND


ARDUINO VIA BLUETOOTH
NOVEMBER 1, 2012 ANATOLIY 181 COMMENTS

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:

I use Arduino Nano V3 and Bluetooth module HC-06. I also connected the external LED to pin 12. It’s program:

1 char incomingByte; // incoming data


2 int LED = 12; // LED pin

4 void setup() {

5 Serial.begin(9600); // initialization

pinMode(LED, OUTPUT);
6
Serial.println("Press 1 to LED ON or 0 to LED OFF...");
7
}
8

9
void loop() {
10
if (Serial.available() > 0) { // if the data came
11
incomingByte = Serial.read(); // read byte
12 if(incomingByte == '0') {

13 digitalWrite(LED, LOW); // if 1, switch LED Off

14 Serial.println("LED OFF. Press 1 to LED ON!"); // print


message
15
}
16
if(incomingByte == '1') {
17 digitalWrite(LED, HIGH); // if 0, switch LED on

18 Serial.println("LED ON. Press 0 to LED OFF!");

19 }

20 }

21 }

22

Android
We use the Java code with an explicit MAC-address of the device. Find MAC-address can be in the program for Android:
Bluetooth Terminal:
Our device that is “BOLUTEK” with MAC-address 00:15:FF:F2:19:4C.

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

It’s Java code of main activity:

1 package com.example.bluetooth1;

3 import java.io.IOException;

4 import java.io.OutputStream;

5 import java.lang.reflect.Method;

6 import java.util.UUID;

7
import com.example.bluetooth1.R;
8

9
10 import android.app.Activity;

11 import android.bluetooth.BluetoothAdapter;

import android.bluetooth.BluetoothDevice;
12
import android.bluetooth.BluetoothSocket;
13
import android.content.Intent;
14
import android.os.Build;
15
import android.os.Bundle;
16
import android.util.Log;
17 import android.view.View;

18 import android.view.View.OnClickListener;

19 import android.widget.Button;

20 import android.widget.Toast;

21
public class MainActivity extends Activity {
22
private static final String TAG = "bluetooth1";
23

24
Button btnOn, btnOff;
25

26
private BluetoothAdapter btAdapter = null;
27
private BluetoothSocket btSocket = null;
28
private OutputStream outStream = null;
29

30 // SPP UUID service

31 private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805

32

33 // MAC-address of Bluetooth module (you must edit this line)

34 private static String address = "00:15:FF:F2:19:5F";

35

36 /** Called when the activity is first created. */


37 @Override

38 public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
39

40
setContentView(R.layout.activity_main);
41

42
btnOn = (Button) findViewById(R.id.btnOn);
43
btnOff = (Button) findViewById(R.id.btnOff);
44

45
btAdapter = BluetoothAdapter.getDefaultAdapter();
46
checkBTState();
47

48 btnOn.setOnClickListener(new OnClickListener() {

49 public void onClick(View v) {

50 sendData("1");

51 Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show();

}
52
});
53

54
btnOff.setOnClickListener(new OnClickListener() {
55
public void onClick(View v) {
56
sendData("0");
57
Toast.makeText(getBaseContext(), "Turn off LED", Toast.LENGTH_SHORT).show()
58
}

59 });

60 }

61

62 private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOExc

63 if(Build.VERSION.SDK_INT >= 10){


64 try {

65 final Method m = device.getClass().getMethod("createInsecureRfcommSo


{ UUID.class });
66
return (BluetoothSocket) m.invoke(device, MY_UUID);
67 } catch (Exception e) {

68 Log.e(TAG, "Could not create Insecure RFComm Connection",e);

69 }

70 }

71 return device.createRfcommSocketToServiceRecord(MY_UUID);

}
72

73
@Override
74
public void onResume() {
75
super.onResume();
76

77
Log.d(TAG, "...onResume - try connect...");
78

79
// Set up a pointer to the remote node using it's address.
80 BluetoothDevice device = btAdapter.getRemoteDevice(address);

81

82 // Two things are needed to make a connection:

83 // A MAC address, which we got above.

84 // A Service ID or UUID. In this case we are using the

85 // UUID for SPP.

86
try {
87
btSocket = createBluetoothSocket(device);
88
} catch (IOException e1) {
89
errorExit("Fatal Error", "In onResume() and socket create failed: " + e1.ge
90
}
91

92 // Discovery is resource intensive. Make sure it isn't going on

93 // when you attempt to connect and pass your message.

btAdapter.cancelDiscovery();
94

95
// Establish the connection. This will block until it connects.
96
Log.d(TAG, "...Connecting...");
97
try {
98
btSocket.connect();
99
Log.d(TAG, "...Connection ok...");
100 } catch (IOException e) {

101 try {

102 btSocket.close();

103 } catch (IOException e2) {

errorExit("Fatal Error", "In onResume() and unable to close socket during c


104
e2.getMessage() + ".");
105 }

106 }

107

108 // Create a data stream so we can talk to server.

109 Log.d(TAG, "...Create Socket...");

110

111 try {

outStream = btSocket.getOutputStream();
112
} catch (IOException e) {
113
errorExit("Fatal Error", "In onResume() and output stream creation failed:" +
114
}
115
}
116

117
@Override
118 public void onPause() {

119 super.onPause();

120
Log.d(TAG, "...In onPause()...");
121

122
if (outStream != null) {
123
try {
124
outStream.flush();
125
} catch (IOException e) {
126
errorExit("Fatal Error", "In onPause() and failed to flush output stream: "
127 }

128 }

129

130 try {

131 btSocket.close();

132 } catch (IOException e2) {

errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getM


133
}
134
}
135

136
private void checkBTState() {
137
// Check for Bluetooth support and then check to make sure it is turned on
138
// Emulator doesn't support Bluetooth and will return null
139
if(btAdapter==null) {
140 errorExit("Fatal Error", "Bluetooth not support");

141 } else {

142 if (btAdapter.isEnabled()) {

143 Log.d(TAG, "...Bluetooth ON...");

} else {
144
145 //Prompt user to turn on Bluetooth

146 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(enableBtIntent, 1);
147
}
148
}
149
}
150

151
private void errorExit(String title, String message){
152
Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).sh
153 finish();

154 }

155

156 private void sendData(String message) {

157 byte[] msgBuffer = message.getBytes();

158
Log.d(TAG, "...Send data: " + message + "...");
159

160
try {
161
outStream.write(msgBuffer);
162
} catch (IOException e) {
163
String msg = "In onResume() and an exception occurred during write: " + e.get
164
if (address.equals("00:00:00:00:00:00"))
165 msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the
the java code";
166
msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exis
167

168
errorExit("Fatal Error", msg);
169
}
170
}
171
}
172

173

174

175

176

177

178

179

180

181

182

183

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

1 package com.example.bluetooth2;

3 import java.io.IOException;

import java.io.InputStream;
4
import java.io.OutputStream;
5
import java.lang.reflect.Method;
6
import java.util.UUID;
7

8
import com.example.bluetooth2.R;
9

10
import android.app.Activity;
11 import android.bluetooth.BluetoothAdapter;

12 import android.bluetooth.BluetoothDevice;
13 import android.bluetooth.BluetoothSocket;

14 import android.content.Intent;

import android.os.Build;
15
import android.os.Bundle;
16
import android.os.Handler;
17
import android.util.Log;
18
import android.view.View;
19
import android.view.View.OnClickListener;
20 import android.widget.Button;

21 import android.widget.TextView;

22 import android.widget.Toast;

23

24 public class MainActivity extends Activity {

private static final String TAG = "bluetooth2";


25

26
Button btnOn, btnOff;
27
TextView txtArduino;
28
Handler h;
29

30
final int RECIEVE_MESSAGE = 1; // Status for Handler
31
private BluetoothAdapter btAdapter = null;
32
private BluetoothSocket btSocket = null;
33 private StringBuilder sb = new StringBuilder();

34

35 private ConnectedThread mConnectedThread;

36

37 // SPP UUID service

38 private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805

39
40 // MAC-address of Bluetooth module (you must edit this line)

41 private static String address = "00:15:FF:F2:19:5F";

42
/** Called when the activity is first created. */
43
@Override
44
public void onCreate(Bundle savedInstanceState) {
45
super.onCreate(savedInstanceState);
46

47
setContentView(R.layout.activity_main);
48

49
btnOn = (Button) findViewById(R.id.btnOn); // button LED ON
50 btnOff = (Button) findViewById(R.id.btnOff); // button LED OFF

51 txtArduino = (TextView) findViewById(R.id.txtArduino); // for display the

52

53 h = new Handler() {

54 public void handleMessage(android.os.Message msg) {

switch (msg.what) {
55
case RECIEVE_MESSAGE:
56
byte[] readBuf = (byte[]) msg.obj;
57
String strIncom = new String(readBuf, 0, msg.arg1);
58 array

59 sb.append(strIncom);

60 int endOfLineIndex = sb.indexOf("\r\n");

if (endOfLineIndex > 0) {
61
String sbprint = sb.substring(0, endOfLineIndex);
62
sb.delete(0, sb.length());
63
txtArduino.setText("Data from Arduino: " + sbprint);
64
btnOff.setEnabled(true);
65
btnOn.setEnabled(true);
66 }
67 //Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + ".

68 break;

}
69
};
70
};
71

72
btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapte
73
checkBTState();
74

75
btnOn.setOnClickListener(new OnClickListener() {
76 public void onClick(View v) {

77 btnOn.setEnabled(false);

78 mConnectedThread.write("1"); // Send "1" via Bluetooth

79 //Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show(

}
80
});
81

82
btnOff.setOnClickListener(new OnClickListener() {
83
public void onClick(View v) {
84
btnOff.setEnabled(false);
85
mConnectedThread.write("0"); // Send "0" via Bluetooth
86
//Toast.makeText(getBaseContext(), "Turn off LED", Toast.LENGTH_SHORT).show
87 }

88 });

89 }

90

91 private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOExc

if(Build.VERSION.SDK_INT >= 10){


92
try {
93
final Method m = device.getClass().getMethod("createInsecureRfcommSo
94 { UUID.class });

95 return (BluetoothSocket) m.invoke(device, MY_UUID);

} catch (Exception e) {
96
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
97
}
98
}
99
return device.createRfcommSocketToServiceRecord(MY_UUID);
100
}
101

102
@Override
103 public void onResume() {

104 super.onResume();

105

106 Log.d(TAG, "...onResume - try connect...");

107

108 // Set up a pointer to the remote node using it's address.

BluetoothDevice device = btAdapter.getRemoteDevice(address);


109

110
// Two things are needed to make a connection:
111
// A MAC address, which we got above.
112
// A Service ID or UUID. In this case we are using the
113
// UUID for SPP.
114

115
try {
116
btSocket = createBluetoothSocket(device);
117 } catch (IOException e) {

118 errorExit("Fatal Error", "In onResume() and socket create failed: " + e.get

119 }

120
121 // Discovery is resource intensive. Make sure it isn't going on

122 // when you attempt to connect and pass your message.

btAdapter.cancelDiscovery();
123

124
// Establish the connection. This will block until it connects.
125
Log.d(TAG, "...Connecting...");
126
try {
127
btSocket.connect();
128
Log.d(TAG, "....Connection ok...");
129 } catch (IOException e) {

130 try {

131 btSocket.close();

132 } catch (IOException e2) {

errorExit("Fatal Error", "In onResume() and unable to close socket during c


133
e2.getMessage() + ".");
134 }

135 }

136

137 // Create a data stream so we can talk to server.

138 Log.d(TAG, "...Create Socket...");

139

140 mConnectedThread = new ConnectedThread(btSocket);

mConnectedThread.start();
141
}
142

143
@Override
144
public void onPause() {
145
super.onPause();
146

147
Log.d(TAG, "...In onPause()...");
148

149 try {

150 btSocket.close();

151 } catch (IOException e2) {

errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getM


152
}
153
}
154

155
private void checkBTState() {
156
// Check for Bluetooth support and then check to make sure it is turned on
157
// Emulator doesn't support Bluetooth and will return null
158 if(btAdapter==null) {

159 errorExit("Fatal Error", "Bluetooth not support");

160 } else {

161 if (btAdapter.isEnabled()) {

Log.d(TAG, "...Bluetooth ON...");


162
} else {
163
//Prompt user to turn on Bluetooth
164
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
165
startActivityForResult(enableBtIntent, 1);
166
}
167
}
168 }

169

170 private void errorExit(String title, String message){

171 Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).sh

172 finish();

}
173

174
175 private class ConnectedThread extends Thread {

176 private final InputStream mmInStream;

private final OutputStream mmOutStream;


177

178
public ConnectedThread(BluetoothSocket socket) {
179
InputStream tmpIn = null;
180
OutputStream tmpOut = null;
181

182
// Get the input and output streams, using temp objects because
183
// member streams are final
184 try {

185 tmpIn = socket.getInputStream();

186 tmpOut = socket.getOutputStream();

187 } catch (IOException e) { }

188
mmInStream = tmpIn;
189
mmOutStream = tmpOut;
190
}
191

192
public void run() {
193
byte[] buffer = new byte[256]; // buffer store for the stream
194
int bytes; // bytes returned from read()
195

196
// Keep listening to the InputStream until an exception occurs

197 while (true) {

198 try {

199 // Read from the InputStream

200 bytes = mmInStream.read(buffer); // Get number of bytes

h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarge


201
queue Handler
202 } catch (IOException e) {

203 break;

}
204
}
205
}
206

207
/* Call this from the main activity to send data to the remote device */
208
public void write(String message) {
209
Log.d(TAG, "...Data to send: " + message + "...");
210 byte[] msgBuffer = message.getBytes();

211 try {

212 mmOutStream.write(msgBuffer);

213 } catch (IOException e) {

Log.d(TAG, "...Error data send: " + e.getMessage() + "...");


214
}
215
}
216
}
217
}
218

219

220

221

222

223

224

225

226

227

228
229

230

231

232

233

234
ANDROID AND ARDUINO BLUETOOTH COMMUNICATION
In this post I will be talking about how to get an Arduino and an Android tablet talking to each other using Bluetooth

We will be using an Arduino Uno ($29.95) with a Silver Bluetooth Mate ($40.95) from SparkFun.com, and my Samsung Galaxy
7.0 running Android 2.3.4.

Wiring the bluetooth mate to the Arduino is really simple and spark fun has a great link on the product page explaining it. Here are the
connections that need to be made:

Bluetooth
Arduino
Mate

No
connection
CTS-I
(leave
floating)

VCC 5V

GND GND

TX-O D2

RX-I D3

No
connection
RTS-O
(leave
floating)

To illustrate the connection between the Arduino the tablet we will be sending simple text messages back and forth between them.
However, since the Arduino doesn’t really have a keyboard, we are going to plug the arduino into our pc and talk to it via a serial
connection using usb.
The arduino code is fairly simple. In a nutshell is opens a serial connection to the computer, and a serial connection to the bluetooth
mate. Any data received on one is written to the other and vice versa. Since we are going to be using the Arduino’s regular RX and TX
lines for talking to the PC, we are going to have to use a software based serial connection on two other digital pins using
the NewSoftSerial Arduino library which can be downloaded here. Just copy the folder in the zip to the libraries folder under
your Arduno folder (for me it is at C:\Program Files\arduino-1.0\libraries)

Here is the Arduino code:

#include <SoftwareSerial.h>

int bluetoothTx = 2;
int bluetoothRx = 3;

SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);

void setup()
{
//Setup usb serial connection to computer
Serial.begin(9600);

//Setup Bluetooth serial connection to android


bluetooth.begin(115200);
bluetooth.print("$$$");
delay(100);
bluetooth.println("U,9600,N");
bluetooth.begin(9600);
}

void loop()
{
//Read from bluetooth and write to usb serial
if(bluetooth.available())
{
char toSend = (char)bluetooth.read();
Serial.print(toSend);
}

//Read from usb serial to bluetooth


if(Serial.available())
{
char toSend = (char)Serial.read();
bluetooth.print(toSend);
}
}

That takes care of the Arduino side of things. The Android bits are little bit tougher.

The Android project we are going to write is going to have to do a few things:

1. Open a bluetooth connection


2. Send data
3. Listen for incoming data
4. Close the connection

But before we can do any of that we need to take care of a few pesky little details. First, we need to pair the Arduino and Android
devices. You can do this from the Android device in the standard way by opening your application drawer and going to Settings. From
there open Wireless and network. Then Bluetooth settings. From here just scan for devices and pair it like normal. If it asks for a pin
it’s probably 1234. You shouldn’t need to do anything special from the Arduino side other than to have it turned on. Next we need to tell
Android that we will be working with bluetooth by adding this element to the <manifest> tag inside the AndroidManifest.xml file:
<uses-permission android:name=”android.permission.BLUETOOTH” />
Alright, now that we have that stuff out of the way we can get on with opening the bluetooth connection. To get started we need
a BluetoothAdapter reference from Android. We can get that by calling
BluetoothAdapter.getDefaultAdapter();
The return value of this will be null if the device does not have bluetooth capabilities. With the adapter you can check to see if bluetooth
is enabled on the device and request that it be turned on if its not with this code:

if(!mBluetoothAdapter.isEnabled())
{
Intent enableBluetooth = new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBluetooth, 0);
}

Now that we have the bluetooth adapter and know that its turned on we can get a reference to our Arduino’s bluetooth device with this
code:

Set pairedDevices = mBluetoothAdapter.getBondedDevices();


if(pairedDevices.size() > 0)
{
for(BluetoothDevice device : pairedDevices)
{
if(device.getName().equals("MattsBlueTooth")) //Note, you will need to change
this to match the name of your device
{
mmDevice = device;
break;
}
}
}

Armed with the bluetooth device reference we can now connect to it using this code:

UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard


SerialPortService ID
mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
mmSocket.connect();
mmOutputStream = mmSocket.getOutputStream();
mmInputStream = mmSocket.getInputStream();

This opens the connection and gets input and output streams for us to work with. You may have noticed that huge ugly UUID.
Apparently there are standard UUID’s for various devices and Serial Port’s use that one. There are lists available out there, but I got this
one from the Android documentation.

If everything has gone as expected, at this point you should be able to connect to your Arduino from your Android device. The
connection takes a few seconds to establish so be patient. Once the connection is established the red blinking light on the bluetooth
chip should stop and remain off.

Closing the connection is simply a matter of calling close() on the input and output streams as well as the socket

Now we are going to have a little fun and actually send the Arduino some data from the Android device. Make yourself a text box (also
known as an EditText in weird Android speak) as well as a send button. Wire up the send button’s click event and add this code:

String msg = myTextbox.getText().toString();


msg += "\n";
mmOutputStream.write(msg.getBytes());

With this we have one way communication established! Make sure the Arduino is plugged in to the computer via the USB cable and
open the Serial Monitor from within the Arduino IDE. Open the application on your Android device and open the connection. Now
whatever your type in the textbox will be sent to the Arduino over air and magically show up in the serial monitor window.

Sending data is trivial. Sadly, listening for data is not. Since data could be written to the input stream at any time we need a separate
thread to watch it so that we don’t block the main ui thread and cause Android to think that we have crashed. Also the data written on
the input stream is relatively arbitrary so there isn’t a simple way to just be notified of when a line of text shows up. Instead lots of short
little packets of data will show up individually one at a time until the entire message is received. Because of this we are going to need to
buffer the data in an array until enough of the data shows up that we can tell what to do. The code for doing this and the threading is a
little be long winded but it is nothing too complicated.

First we will tackle the problem of getting a worker thread going. Here is the basic code for that:

final Handler handler = new Handler();


workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
//Do work
}
}
});
workerThread.start();

The first line there declares a Handler which we can use to update the UI, but more on that later. This code will start a new thread. As
long as the run() method is running the thread will stay alive. Once the run() method completes and returns the thread will die. In our
case, it is stuck in a while loop that will keep it alive until our boolean stopWorker flag is set to true, or the thread is interrupted. Next
lets talk about actually reading data.

The input stream provides an .available() method which returns us how many (if any) bytes of data are waiting to be read. Given that
number we can make a temporary byte array and read the bytes into it like so:

int bytesAvailable = mmInputStream.available();


if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
mmInputStream.read(packetBytes);
}

This gives us some bytes to work with, but unfortunately this is rather unlikely to be all of the bytes we need (or who know its might be
all of them plus some more from the next command). So now we have do that pesky buffering thing I was telling you about earlier. The
read buffer is just byte array that we can store incoming bytes in until we have them all. Since the size of message is going to vary we
need to allocate enough space in the buffer to account for the longest message we might receive. For our purposes we are allocating
1024 spaces, but the number will need to be tailored to your specific needs. Alright, back to the code. Once we have packet bytes we
need to add them to the read buffer one at a time until we run in to the end of line delimiter character, in our case we are using a
newline character (Ascii code 10)

for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0, encodedBytes, 0,
encodedBytes.length);
final String data = new String(encodedBytes, "US-ASCII");
readBufferPosition = 0;

//The variable data now contains our full command


}
else
{
readBuffer[readBufferPosition++] = b;
}
}

At this point we now have the full command stored in the string variable data and we can act on it however we want. For this simple
example we just want to take the string display it in on a on screen label. Sticking the string into the label would be pretty simple except
that this code is operating under a worker thread and only the main UI thread can access the UI elements. This is where that Handler
variable is going to come in. The handler will allow us to schedule a bit of code to be executed by main UI thread. Think of the handler
as delivery boy who will take the code you wanted executed and deliver it to main UI thread so that it can execute the code for you.
Here is how you can do that:

handler.post(new Runnable()
{
public void run()
{
myLabel.setText(data);
}
});

And that is it! We now have two way communication between the Arduino and an Android device! Plugin the Arduino and open the
serial monitor. Run your Android application and open the bluetooth connection. Now what type in the textbox on the Android device will
show up in the serial monitor window for the Arduino, and what you type in the serial monitor window will show up on the Android
device.
The source code for both the Arduino and Android is available at: http://project-greengiant.googlecode.com/svn/trunk/Blog/Android
Arduino Bluetooth

You might also like