Android Bluetooth Connection Example
The Android platform includes support for the Bluetooth network stack, which allows a device to wirelessly exchange data with other Bluetooth devices.
The Android Bluetooth APIs provide us access to the Bluetooth functionality in order to wirelessly connect to other Bluetooth devices, enabling point-to-point and multipoint wireless features.
So, if we want to exchange data between different devices through our application, Bluetooth is a common way to connect two devices that support Bluetooth.
In this example we are going to create an application which activates Bluetooth, finds Bluetooth devices that may be near, scans for other undiscovered Bluetooth devices and finally uses Bluetooth connection to create a Chat Application between two devices.
Table Of Contents
- 1. Introduction
- 2. Create a New Android Studio Project
- 3. Create the layout of the BluetoothChat
- 4. Create the source code of the BluetoothChat
- 5. Create the source code of the BluetoothChatService
- 6. Create the layout of the DeviceListActivity
- 7. Create the source code of the DeviceListActivity
- 8. AndroidManifest.xml
- 9. build.gradle
- 10. Build, compile and run
- 11. Download the Android Studio Project
- 12. References
1. Introduction
For our example will use the following tools in a Windows 64-bit or an OS X platform:
- JDK 1.8
- Android Studio 2.1.2
- Android SDK 6.0
For this example we have used methods and implementation from the Android Bluetooth Example related to Android Bluetooth searching and pairing devices. We have also made use of the Android RecyclerView Example for the ui and layout of our Bluetooth Chat. Please visit them before starting the Android Bluetooth Connection Example
Let’s take a closer look:
2. Create a New Android Studio Project
You may skip project creation and jump directly to the beginning of the example below.
Open Android Studio and choose “Start a new Android Studio Project” in the welcome screen.
Specify the name of the application, the project and the package.
In the next window, select the form factors your app will run on.
In the next window you should choose to “Add an activity to Mobile”. In our example, we will choose to create a project with no activity, so choose: “Add no activity”.
Now press finish, and our project has just been created!
3. Create the layout of the BluetoothChat
Add a new xml file inside /res/layout
folder, with name main_activity.xml
. We should have /layout/main_activity.xml
file and paste the code below.
main_activity.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/my_recycler_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:paddingLeft="10dp" android:paddingRight="10dp" android:scrollbars="vertical" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/edit_text_out" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_weight="1" /> <Button android:id="@+id/button_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/send" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/scan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="connect" android:text="@string/connect" /> <Button android:id="@+id/discoverable" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="discoverable" android:text="@string/discoverable" /> </LinearLayout> </LinearLayout>
4. Create the source code of the BluetoothChat
Add a new Java class inside src/com.javacodegeeks.androidBluetoothExample/
so that we are going to have the src/com.javacodegeeks.androidBluetoothExample/BluetoothChat.java
file and paste the code below.
BluetoothChat.java
package com.javacodegeeks.androidBluetoothExample; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.inputmethod.EditorInfo; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import com.javacodegeeks.R; import androidRecyclerView.MessageAdapter; public class BluetoothChat extends Activity { // Message types sent from the BluetoothChatService Handler public static final int MESSAGE_STATE_CHANGE = 1; public static final int MESSAGE_READ = 2; public static final int MESSAGE_WRITE = 3; public static final int MESSAGE_DEVICE_NAME = 4; public static final int MESSAGE_TOAST = 5; // Key names received from the BluetoothChatService Handler public static final String DEVICE_NAME = "device_name"; public static final String TOAST = "toast"; // Intent request codes private static final int REQUEST_CONNECT_DEVICE = 1; private static final int REQUEST_ENABLE_BT = 2; private EditText mOutEditText; private Button mSendButton; // Name of the connected device private String mConnectedDeviceName = null; // String buffer for outgoing messages private StringBuffer mOutStringBuffer; // Local Bluetooth adapter private BluetoothAdapter mBluetoothAdapter = null; // Member object for the chat services private BluetoothChatService mChatService = null; private RecyclerView mRecyclerView; private LinearLayoutManager mLayoutManager; private MessageAdapter mAdapter; public int counter = 0; private List messageList = new ArrayList(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); mRecyclerView.setHasFixedSize(true); mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); mAdapter = new MessageAdapter(getBaseContext(), messageList); mRecyclerView.setAdapter(mAdapter); mRecyclerView.setItemAnimator(new DefaultItemAnimator()); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // If the adapter is null, then Bluetooth is not supported if (mBluetoothAdapter == null) { Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); finish(); return; } } @Override public void onStart() { super.onStart(); if (!mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); } else { if (mChatService == null) setupChat(); } } @Override public synchronized void onResume() { super.onResume(); if (mChatService != null) { if (mChatService.getState() == BluetoothChatService.STATE_NONE) { mChatService.start(); } } } private void setupChat() { mOutEditText = (EditText) findViewById(R.id.edit_text_out); mOutEditText.setOnEditorActionListener(mWriteListener); mSendButton = (Button) findViewById(R.id.button_send); mSendButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { TextView view = (TextView) findViewById(R.id.edit_text_out); String message = view.getText().toString(); sendMessage(message); } }); // Initialize the BluetoothChatService to perform bluetooth connections mChatService = new BluetoothChatService(this, mHandler); // Initialize the buffer for outgoing messages mOutStringBuffer = new StringBuffer(""); } @Override public synchronized void onPause() { super.onPause(); } @Override public void onStop() { super.onStop(); } @Override public void onDestroy() { super.onDestroy(); // Stop the Bluetooth chat services if (mChatService != null) mChatService.stop(); } private void ensureDiscoverable() { if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent); } } private void sendMessage(String message) { // Check that we're actually connected before trying anything if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) { Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show(); return; } // Check that there's actually something to send if (message.length() > 0) { // Get the message bytes and tell the BluetoothChatService to write byte[] send = message.getBytes(); mChatService.write(send); // Reset out string buffer to zero and clear the edit text field mOutStringBuffer.setLength(0); mOutEditText.setText(mOutStringBuffer); } } // The action listener for the EditText widget, to listen for the return key private TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView view, int actionId, KeyEvent event) { // If the action is a key-up event on the return key, send the message if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) { String message = view.getText().toString(); sendMessage(message); } return true; } }; // The Handler that gets information back from the BluetoothChatService private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_WRITE: byte[] writeBuf = (byte[]) msg.obj; // construct a string from the buffer String writeMessage = new String(writeBuf); mAdapter.notifyDataSetChanged(); messageList.add(new androidRecyclerView.Message(counter++, writeMessage, "Me")); break; case 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); mAdapter.notifyDataSetChanged(); messageList.add(new androidRecyclerView.Message(counter++, readMessage, mConnectedDeviceName)); break; case MESSAGE_DEVICE_NAME: // save the connected device's name mConnectedDeviceName = msg.getData().getString(DEVICE_NAME); Toast.makeText(getApplicationContext(), "Connected to " + mConnectedDeviceName, Toast.LENGTH_SHORT).show(); break; case MESSAGE_TOAST: Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show(); break; } } }; public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CONNECT_DEVICE: // When DeviceListActivity returns with a device to connect if (resultCode == Activity.RESULT_OK) { // Get the device MAC address String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); // Get the BLuetoothDevice object BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); // Attempt to connect to the device mChatService.connect(device); } break; case REQUEST_ENABLE_BT: // When the request to enable Bluetooth returns if (resultCode == Activity.RESULT_OK) { // Bluetooth is now enabled, so set up a chat session setupChat(); } else { // User did not enable Bluetooth or an error occured Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); finish(); } } } public void connect(View v) { Intent serverIntent = new Intent(this, DeviceListActivity.class); startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); } public void discoverable(View v) { ensureDiscoverable(); } }
5. Create the source code of the BluetoothChatService
The BluetoothChatService class does all the work for setting up and managing Bluetooth connections with other devices. It has a thread that listens for incoming connections, a thread for connecting with a device, and a thread for performing data transmissions when connected.
So, add a new Java class inside src/com.javacodegeeks.androidBluetoothExample/
so that we are going to have the src/com.javacodegeeks.androidBluetoothExample/BluetoothChatService.java
file and paste the code below.
BluetoothChatService.java
package com.javacodegeeks.androidBluetoothExample; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; /** * This class does all the work for setting up and managing Bluetooth * connections with other devices. It has a thread that listens for * incoming connections, a thread for connecting with a device, and a * thread for performing data transmissions when connected. */ public class BluetoothChatService { // Name for the SDP record when creating server socket private static final String NAME = "BluetoothChat"; // Unique UUID for this application private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"); // Member fields private final BluetoothAdapter mAdapter; private final Handler mHandler; private AcceptThread mAcceptThread; private ConnectThread mConnectThread; private ConnectedThread mConnectedThread; private int mState; // Constants that indicate the current connection state public static final int STATE_NONE = 0; // we're doing nothing public static final int STATE_LISTEN = 1; // now listening for incoming connections public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection public static final int STATE_CONNECTED = 3; // now connected to a remote device /** * Constructor. Prepares a new BluetoothChat session. * * @param context The UI Activity Context * @param handler A Handler to send messages back to the UI Activity */ public BluetoothChatService(Context context, Handler handler) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mState = STATE_NONE; mHandler = handler; } /** * Set the current state of the chat connection * * @param state An integer defining the current connection state */ private synchronized void setState(int state) { mState = state; // Give the new state to the Handler so the UI Activity can update mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); } /** * Return the current connection state. */ public synchronized int getState() { return mState; } /** * Start the chat service. Specifically start AcceptThread to begin a * session in listening (server) mode. Called by the Activity onResume() */ public synchronized void start() { // Cancel any thread attempting to make a 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 listen on a BluetoothServerSocket if (mAcceptThread == null) { mAcceptThread = new AcceptThread(); mAcceptThread.start(); } setState(STATE_LISTEN); } /** * Start the ConnectThread to initiate a connection to a remote device. * * @param device The BluetoothDevice to connect */ public synchronized void connect(BluetoothDevice device) { // Cancel any thread attempting to make a connection if (mState == STATE_CONNECTING) { 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 connect with the given device mConnectThread = new ConnectThread(device); mConnectThread.start(); setState(STATE_CONNECTING); } /** * Start the ConnectedThread to begin managing a Bluetooth connection * * @param socket The BluetoothSocket on which the connection was made * @param device The BluetoothDevice that has been connected */ public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { // 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; } // Cancel the accept thread because we only want to connect to one device if (mAcceptThread != null) { mAcceptThread.cancel(); mAcceptThread = 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(BluetoothChat.MESSAGE_DEVICE_NAME); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.DEVICE_NAME, device.getName()); msg.setData(bundle); mHandler.sendMessage(msg); setState(STATE_CONNECTED); } /** * Stop all threads */ public synchronized void stop() { if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } if (mAcceptThread != null) { mAcceptThread.cancel(); mAcceptThread = null; } setState(STATE_NONE); } /** * Write to the ConnectedThread in an unsynchronized manner * * @param out The bytes to write * @see ConnectedThread#write(byte[]) */ public void write(byte[] out) { // Create temporary object ConnectedThread r; // Synchronize a copy of the ConnectedThread synchronized (this) { if (mState != STATE_CONNECTED) return; r = mConnectedThread; } // Perform the write unsynchronized r.write(out); } /** * Indicate that the connection attempt failed and notify the UI Activity. */ private void connectionFailed() { setState(STATE_LISTEN); // Send a failure message back to the Activity Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.TOAST, "Unable to connect device"); msg.setData(bundle); mHandler.sendMessage(msg); } /** * Indicate that the connection was lost and notify the UI Activity. */ private void connectionLost() { setState(STATE_LISTEN); // Send a failure message back to the Activity Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.TOAST, "Device connection was lost"); msg.setData(bundle); mHandler.sendMessage(msg); } /** * This thread runs while listening for incoming connections. It behaves * like a server-side client. It runs until a connection is accepted * (or until cancelled). */ private class AcceptThread extends Thread { // The local server socket private final BluetoothServerSocket mmServerSocket; public AcceptThread() { BluetoothServerSocket tmp = null; // Create a new listening server socket try { tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { } mmServerSocket = tmp; } public void run() { setName("AcceptThread"); BluetoothSocket socket = null; // Listen to the server socket if we're not connected while (mState != STATE_CONNECTED) { try { // This is a blocking call and will only return on a // successful connection or an exception socket = mmServerSocket.accept(); } catch (IOException e) { break; } // If a connection was accepted if (socket != null) { synchronized (BluetoothChatService.this) { switch (mState) { case STATE_LISTEN: case STATE_CONNECTING: // Situation normal. Start the connected thread. connected(socket, socket.getRemoteDevice()); break; case STATE_NONE: case STATE_CONNECTED: // Either not ready or already connected. Terminate new socket. try { socket.close(); } catch (IOException e) { } break; } } } } } public void cancel() { try { mmServerSocket.close(); } catch (IOException e) { } } } /** * This thread runs while attempting to make an outgoing connection * with a device. It runs straight through; the connection either * succeeds or fails. */ private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { mmDevice = device; BluetoothSocket tmp = null; // Get a BluetoothSocket for a connection with the // given BluetoothDevice try { tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { } mmSocket = tmp; } public void run() { setName("ConnectThread"); // Always cancel discovery because it will slow down a connection mAdapter.cancelDiscovery(); // Make a connection to the BluetoothSocket try { // This is a blocking call and will only return on a // successful connection or an exception mmSocket.connect(); } catch (IOException e) { connectionFailed(); // Close the socket try { mmSocket.close(); } catch (IOException e2) { } // Start the service over to restart listening mode BluetoothChatService.this.start(); return; } // Reset the ConnectThread because we're done synchronized (BluetoothChatService.this) { mConnectThread = null; } // Start the connected thread connected(mmSocket, mmDevice); } public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } } /** * This thread runs during a connection with a remote device. * It handles all incoming and outgoing transmissions. */ private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the BluetoothSocket input and output streams try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { byte[] buffer = new byte[1024]; int bytes; // Keep listening to the InputStream while connected while (true) { try { // Read from the InputStream bytes = mmInStream.read(buffer); // Send the obtained bytes to the UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); } catch (IOException e) { connectionLost(); break; } } } /** * Write to the connected OutStream. * * @param buffer The bytes to write */ public void write(byte[] buffer) { try { mmOutStream.write(buffer); // Share the sent message back to the UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer) .sendToTarget(); } catch (IOException e) { } } public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } } }
6. Create the layout of the DeviceListActivity
Add a new xml file inside /res/layout
folder, with name device_list.xml
. We should have /layout/main_activity.xml
file and paste the code below.
device_list.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:id="@+id/title_paired_devices" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#666" android:paddingLeft="5dp" android:text="@string/title_paired_devices" android:textColor="#fff" android:visibility="gone" /> <ListView android:id="@+id/paired_devices" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:stackFromBottom="true" /> <TextView android:id="@+id/title_new_devices" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#666" android:paddingLeft="5dp" android:text="@string/title_other_devices" android:textColor="#fff" android:visibility="gone" /> <ListView android:id="@+id/new_devices" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="2" android:stackFromBottom="true" /> <Button android:id="@+id/button_scan" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/button_scan" /> </LinearLayout>
7. Create the source code of the DeviceListActivity
This Activity lists any paired devices and devices detected in the area after discovery. When a device is chosen by the user, the MAC address of the device is sent back to the parent Activity in the result Intent.
So, add a new Java class inside src/com.javacodegeeks.androidBluetoothExample/
so that we are going to have the src/com.javacodegeeks.androidBluetoothExample/DeviceListActivity.java
file and paste the code below.
DeviceListActivity.java
package com.javacodegeeks.androidBluetoothExample; package com.javacodegeeks.androidBluetoothExample; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import com.javacodegeeks.R; import java.util.Set; public class DeviceListActivity extends Activity { // Return Intent extra public static String EXTRA_DEVICE_ADDRESS = "device_address"; // Member fields private BluetoothAdapter mBtAdapter; private ArrayAdapter mPairedDevicesArrayAdapter; private ArrayAdapter mNewDevicesArrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Setup the window requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.device_list); // Set result CANCELED incase the user backs out setResult(Activity.RESULT_CANCELED); // Initialize the button to perform device discovery Button scanButton = (Button) findViewById(R.id.button_scan); scanButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { doDiscovery(); v.setVisibility(View.GONE); } }); // Initialize array adapters. One for already paired devices and // one for newly discovered devices mPairedDevicesArrayAdapter = new ArrayAdapter(this, R.layout.device_name); mNewDevicesArrayAdapter = new ArrayAdapter(this, R.layout.device_name); // Find and set up the ListView for paired devices ListView pairedListView = (ListView) findViewById(R.id.paired_devices); pairedListView.setAdapter(mPairedDevicesArrayAdapter); pairedListView.setOnItemClickListener(mDeviceClickListener); // Find and set up the ListView for newly discovered devices ListView newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(mDeviceClickListener); // 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 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter); // Get the local Bluetooth adapter mBtAdapter = BluetoothAdapter.getDefaultAdapter(); // Get a set of currently paired devices Set pairedDevices = mBtAdapter.getBondedDevices(); // If there are paired devices, add each one to the ArrayAdapter if (pairedDevices.size() > 0) { findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE); for (BluetoothDevice device : pairedDevices) { mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } } else { String noDevices = getResources().getText(R.string.none_paired).toString(); mPairedDevicesArrayAdapter.add(noDevices); } } @Override protected void onDestroy() { super.onDestroy(); // Make sure we're not doing discovery anymore if (mBtAdapter != null) { mBtAdapter.cancelDiscovery(); } // Unregister broadcast listeners this.unregisterReceiver(mReceiver); } /** * Start device discover with the BluetoothAdapter */ private void doDiscovery() { // Indicate scanning in the title setProgressBarIndeterminateVisibility(true); setTitle(R.string.scanning); // Turn on sub-title for new devices findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE); // If we're already discovering, stop it if (mBtAdapter.isDiscovering()) { mBtAdapter.cancelDiscovery(); } // Request discover from BluetoothAdapter mBtAdapter.startDiscovery(); } // The on-click listener for all devices in the ListViews private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { public void onItemClick(AdapterView av, View v, int arg2, long arg3) { // Cancel discovery because it's costly and we're about to connect mBtAdapter.cancelDiscovery(); // Get the device MAC address, which is the last 17 chars in the View String info = ((TextView) v).getText().toString(); String address = info.substring(info.length() - 17); // Create the result Intent and include the MAC address Intent intent = new Intent(); intent.putExtra(EXTRA_DEVICE_ADDRESS, address); // Set result and finish this Activity setResult(Activity.RESULT_OK, intent); finish(); } }; // The BroadcastReceiver that listens for discovered devices and // changes the title when discovery is finished private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @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) { mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } // When discovery is finished, change the Activity title } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setProgressBarIndeterminateVisibility(false); setTitle(R.string.select_device); if (mNewDevicesArrayAdapter.getCount() == 0) { String noDevices = getResources().getText(R.string.none_found).toString(); mNewDevicesArrayAdapter.add(noDevices); } } } }; }
8. AndroidManifest.xml
The AndroidManifest.xml of our project includes the BLUETOOTH
permissions:
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.javacodegeeks"> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name=".androidBluetoothExample.BluetoothChat" android:configChanges="orientation|keyboardHidden" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".androidBluetoothExample.DeviceListActivity" android:configChanges="orientation|keyboardHidden" android:label="@string/select_device" /> </application> </manifest >
9. build.gradle
We should add the AppCompat V7 support support library as well as RecyclerView V7 support support library the in our project. We can add them as dependencies to our application via build.gradle file.
build.gradle
apply plugin: 'com.android.application' android { compileSdkVersion 24 buildToolsVersion "24.0.0" defaultConfig { applicationId "com.javacodegeeks" minSdkVersion 14 targetSdkVersion 24 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.1.1' compile 'com.android.support:recyclerview-v7:24.1.1' }
10. Build, compile and run
This example should run simultaneously on two different Android devices, in order for the Bluetooth chat to connect and run.
When we build, compile and run our project, the main BluetoothChat should look like this:
11. Download the Android Studio Project
This was an example of Android Bluetooth Connection – BluetoothChat Example.
You can download the full source code of this example here: AndroidBluetoothExample.zip
Your example is fantastic. I am curious it is free to download and use. I want to use your source code in my program, is it free?
Thanks
Hi! Very nice code, but I have a question. Is it possible to connect for example 4+ phones or android devices like that? Would it be possible to have a chat with 5ppl who are in the same room?
in my case , it is not able to connect any nearby bluetooth device so how can i communicate
HI This is fantastic code But i just want to know that how to use BluetoothChatService as a background service so that i can use it in another activity also.
Excellent tutorial, I would like to learn how to integrate my android app to a bluetooth weighing scale
it show unable to connect
Hey!!! @Chryssa Aliferi i just downloaded your’s android bluetoothchat project it was really good but one more thing if you can provide me its documentation and overview that would be good
I want to submit in university