Welcome, Guest: Register On Nairaland / LOGIN! / Trending / Recent / New
Stats: 3,154,748 members, 7,824,154 topics. Date: Saturday, 11 May 2024 at 12:57 AM

Bluetooth Connectivity Between Android And Arduino - Programming - Nairaland

Nairaland Forum / Science/Technology / Programming / Bluetooth Connectivity Between Android And Arduino (798 Views)

Which One Should I Focus Between Android App Development And Web Application On / Udacity/google Africa Challenge Scholarship For Android And Web Development! / Free Arduino Tutorial (2) (3) (4)

(1) (Reply)

Bluetooth Connectivity Between Android And Arduino by KodeHauz: 3:19pm On Apr 15, 2019
Recently, I developed an android application that transfers data to and from an Arduino through Bluetooth. This post aims to highlight how this Bluetooth connection data transfer between the two devices is achieved.

Disclaimer: The scope of this article is limited to the Android application. All Arduino hardware configurations are excluded.

This workflow will be discussed in three stages:

- Device Discovery;

- Connection and

- Data transfer

Discovery
First things first, the necessary permissions must be declared in the manifest file:

<manifest ... >
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
...
</manifest>

On the Bluetooth devices discovery Activity, a BroadcastReceiver listens for discovered devices and updates a Recyclerview showing a list of available devices (paired and unpaired). The receiver is detailed thus:

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, because it's been listed already
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// only add device to the list if it is not already there
if (!mBtDevices.contains(device))
mBtDevices.add(device);
// update the reccyclerview here
}
// When discovery is finished,
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setProgressBarIndeterminateVisibility(false);
}
}
Registration for this broadcast is done in the activity’s onResume() method:

// Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);

// Register for broadcasts when discovery has finished
IntentFilter finishedFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, finishedFilter);
And unregistered in onPause() method

this.unregisterReceiver(mReceiver);
Connection
Bluetooth connectivity with any selected visible device is established through a service that is initialized at application launch and closed when the application is terminated as shown:

@Override
public void onCreate() {
super.onCreate();
// initialize
mBluetoothCommService = new BluetoothCommunicationService();
}
@Override
public void onTerminate() {
super.onTerminate();
if (mBluetoothCommService != null) {
mBluetoothCommService.stop();
}
}
This service queries the local Bluetooth adapter for paired Bluetooth devices and establishes a connection by spinning up a thread. RFCOMM channel/socket creation and connection are performed on this thread as shown:

private class ConnectThread extends Thread {
private final BluetoothSocket mSocket;
private final BluetoothDevice mDevice;
public ConnectThread(BluetoothDevice device) {
mDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.e(TAG, "Socket Type: create() failed", e);
}
mSocket = tmp;
mState = STATE_CONNECTING;
}
public void run() {
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// its a blocking call and will only return on a successful connection or an exception
mSocket.connect();
} catch (IOException e) {
try {
mSocket.close(); // Close the socket
} catch (IOException e2) {
Log.e(TAG, "unable to close() socket during connection failure", e2);
}
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, "Unable to connect device"wink;
msg.setData(bundle);
mHandler.sendMessage(msg);
mState = STATE_NONE;

return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothCommunicationService.this) {
mConnectThread = null;
}
// Cancel the thread that completed the connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(Constants.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
}
public void cancel() {
try {
mSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
Data Transfer
With connection established, data can be transmitted through a new thread that handles the InputStreams and OutputStreams:

private class ConnectedThread extends Thread {
private final BluetoothSocket mSocket;
private final InputStream mInStream;
private final OutputStream mOutStream;
private ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread: " + socket);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating input stream", e);
}
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "Error occurred when creating output stream", e);
}
mInStream = tmpIn;
mOutStream = tmpOut;
mState = STATE_CONNECTED;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (mState == STATE_CONNECTED) {
try {
// Read from the InputStream
bytes = mInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, "Device connection was lost"wink;
msg.setData(bundle);
mHandler.sendMessage(msg);
mState = STATE_NONE;

break;
}
}
}
// Write to the connected OutStream.
private void write(byte[] buffer) {
try {
mOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
private void cancel() {
try {
mSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
Because this service runs in the background, communication to / from the main UI thread is established by creating a handler which updates the UI (toasts, dialogs, view updated) based on the messsage received.

Each activity that requires communication with the service creates an instance of the handler and performs necessary action by overriding the handleMessage() method:

public class BluetoothCommunicationHandler extends Handler {
private WeakReference<Activity> mActivity;

public BluetoothCommunicationHandler() {
mActivity = null;
}

public void setCurrentActivity(Activity activity) {
mActivity = new WeakReference<>(activity);
}

@Override
public void handleMessage(Message msg) {
Activity activity = mActivity.get();
if (activity != null) {
switch (msg.what) {
case Constants.MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
break;
case Constants.MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
// do something with the received message
break;
case Constants.MESSAGE_DEVICE_NAME:
// save the connected device's name
String deviceName = msg.getData().getString(Constants.DEVICE_NAME);
break;
}
}
}
}


https://kodehauz.com/blog/data-transfer-between-android-and-arduino-over-bluetooth

1 Like

(1) (Reply)

New Job Alert!!! Develpers Jobs!!! / Python,java And C++ Good And Sound Programmer / How Can I Disable Sqlite Locking

(Go Up)

Sections: politics (1) business autos (1) jobs (1) career education (1) romance computers phones travel sports fashion health
religion celebs tv-movies music-radio literature webmasters programming techmarket

Links: (1) (2) (3) (4) (5) (6) (7) (8) (9) (10)

Nairaland - Copyright © 2005 - 2024 Oluwaseun Osewa. All rights reserved. See How To Advertise. 19
Disclaimer: Every Nairaland member is solely responsible for anything that he/she posts or uploads on Nairaland.