In android, Bluetooth is a communication network protocol, which allows devices to connect wirelessly to exchange the data with other Bluetooth devices.
Generally, in android applications by using Bluetooth API’s we can implement Bluetooth functionalities, such as enable or disable Bluetooth, searching for available Bluetooth devices, connecting with the devices and managing the data transfer between devices within the range.
In android, we can perform Bluetooth related activities by using BluetoothAdapter class in our applications
Android Enable or Turn On Bluetooth
In android, By using the startActivityForResult() method with ACTION_REQUEST_ENABLE intent action parameter we can enable or turn on Bluetooth in our android applications.
Following is the code snippet to enable a Bluetooth by using BluetoothAdapter parameter ACTION_REQUEST_ENABLE.
Intent eintent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(eintent, intVal);
If you observe above code snippet, we used startActivityForResult() method with ACTION_REQUEST_ENABLE intent action parameter to enable a Bluetooth. The second parameter intVal is a locally defined integer that must be greater than 0.
Android Disable or Turn OFF Bluetooth
In android, we can disable or turn off Bluetooth just by invoking a BluetoothAdapter method disable().
Following is the code snippet to disable or turn off Bluetooth in android applications using disable() function.
BluetoothAdapter bAdapter = BluetoothAdapter.getDefaultAdapter();
bAdapter.disable();
we need to set Bluetooth permissions in our android manifest file as shown below to use Bluetooth features in our android applications
<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>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.mcuhq.simplebluetooth.MainActivity">
<CheckBox
android:id="@+id/checkbox_led_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:checked="false"
android:scaleX="1.7"
android:scaleY="1.7"
android:text="Toggle LED"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.1"
android:ellipsize="end"
android:maxLines="1"
android:text="RX:"
android:textStyle="bold" />
<TextView
android:id="@+id/read_buffer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:ellipsize="end"
android:maxLines="1"
android:text="<Read Buffer>" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.1"
android:ellipsize="end"
android:maxLines="1"
android:text="Status:"
android:textStyle="bold" />
<TextView
android:id="@+id/bluetooth_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:ellipsize="end"
android:maxLines="1"
android:text="<Bluetooth Status>" />
</LinearLayout>
<Button
android:id="@+id/scan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bluetooth ON" />
<Button
android:id="@+id/off"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bluetooth OFF" />
<Button
android:id="@+id/paired_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Show paired Devices" />
<Button
android:id="@+id/discover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Discover New Devices" />
<ListView
android:id="@+id/devices_list_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:choiceMode="singleChoice" />
</LinearLayout>
MainActivity.Java
package com.androindian.simplebluetooth;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private final String TAG = MainActivity.class.getSimpleName();
private static final UUID BT_MODULE_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // "random" unique identifier
// #defines for identifying shared types between calling functions
private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names
public final static int MESSAGE_READ = 2; // used in bluetooth handler to identify message update
private final static int CONNECTING_STATUS = 3; // used in bluetooth handler to identify message status
// GUI Components
private TextView mBluetoothStatus;
private TextView mReadBuffer;
private Button mScanBtn;
private Button mOffBtn;
private Button mListPairedDevicesBtn;
private Button mDiscoverBtn;
private ListView mDevicesListView;
private CheckBox mLED1;
private BluetoothAdapter mBTAdapter;
private Set<BluetoothDevice> mPairedDevices;
private ArrayAdapter<String> mBTArrayAdapter;
private Handler mHandler; // Our main handler that will receive callback notifications
private ConnectedThread mConnectedThread; // bluetooth background worker thread to send and receive data
private BluetoothSocket mBTSocket = null; // bi-directional client-to-client data path
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBluetoothStatus = (TextView)findViewById(R.id.bluetooth_status);
mReadBuffer = (TextView) findViewById(R.id.read_buffer);
mScanBtn = (Button)findViewById(R.id.scan);
mOffBtn = (Button)findViewById(R.id.off);
mDiscoverBtn = (Button)findViewById(R.id.discover);
mListPairedDevicesBtn = (Button)findViewById(R.id.paired_btn);
mLED1 = (CheckBox)findViewById(R.id.checkbox_led_1);
mBTArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
mBTAdapter = BluetoothAdapter.getDefaultAdapter(); // get a handle on the bluetooth radio
mDevicesListView = (ListView)findViewById(R.id.devices_list_view);
mDevicesListView.setAdapter(mBTArrayAdapter); // assign model to view
mDevicesListView.setOnItemClickListener(mDeviceClickListener);
// Ask for location permission if not already allowed
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
mHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg){
if(msg.what == MESSAGE_READ){
String readMessage = null;
readMessage = new String((byte[]) msg.obj, StandardCharsets.UTF_8);
mReadBuffer.setText(readMessage);
}
if(msg.what == CONNECTING_STATUS){
char[] sConnected;
if(msg.arg1 == 1)
mBluetoothStatus.setText(getString(R.string.BTConnected) + msg.obj);
else
mBluetoothStatus.setText(getString(R.string.BTconnFail));
}
}
};
if (mBTArrayAdapter == null) {
// Device does not support Bluetooth
mBluetoothStatus.setText(getString(R.string.sBTstaNF));
Toast.makeText(getApplicationContext(),getString(R.string.sBTdevNF),Toast.LENGTH_SHORT).show();
}
else {
mLED1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
if(mConnectedThread != null) //First check to make sure thread created
mConnectedThread.write("1");
}
});
mScanBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bluetoothOn();
}
});
mOffBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
bluetoothOff();
}
});
mListPairedDevicesBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v){
listPairedDevices();
}
});
mDiscoverBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
discover();
}
});
}
}
private void bluetoothOn(){
if (!mBTAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
mBluetoothStatus.setText(getString(R.string.BTEnable));
Toast.makeText(getApplicationContext(),getString(R.string.sBTturON),Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(),getString(R.string.BTisON), Toast.LENGTH_SHORT).show();
}
}
// Enter here after user selects "yes" or "no" to enabling radio
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent Data){
// Check which request we're responding to
if (requestCode == REQUEST_ENABLE_BT) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a contact.
// The Intent's data Uri identifies which contact was selected.
mBluetoothStatus.setText(getString(R.string.sEnabled));
}
else
mBluetoothStatus.setText(getString(R.string.sDisabled));
}
}
private void bluetoothOff(){
mBTAdapter.disable(); // turn off
mBluetoothStatus.setText(getString(R.string.sBTdisabl));
Toast.makeText(getApplicationContext(),"Bluetooth turned Off", Toast.LENGTH_SHORT).show();
}
private void discover(){
// Check if the device is already discovering
if(mBTAdapter.isDiscovering()){
mBTAdapter.cancelDiscovery();
Toast.makeText(getApplicationContext(),getString(R.string.DisStop),Toast.LENGTH_SHORT).show();
}
else{
if(mBTAdapter.isEnabled()) {
mBTArrayAdapter.clear(); // clear items
mBTAdapter.startDiscovery();
Toast.makeText(getApplicationContext(), getString(R.string.DisStart), Toast.LENGTH_SHORT).show();
registerReceiver(blReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
else{
Toast.makeText(getApplicationContext(), getString(R.string.BTnotOn), Toast.LENGTH_SHORT).show();
}
}
}
final BroadcastReceiver blReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// add the name to the list
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mBTArrayAdapter.notifyDataSetChanged();
}
}
};
private void listPairedDevices(){
mBTArrayAdapter.clear();
mPairedDevices = mBTAdapter.getBondedDevices();
if(mBTAdapter.isEnabled()) {
// put it's one to the adapter
for (BluetoothDevice device : mPairedDevices)
mBTArrayAdapter.add(device.getName() + "\n" + device.getAddress());
Toast.makeText(getApplicationContext(), getString(R.string.show_paired_devices), Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(getApplicationContext(), getString(R.string.BTnotOn), Toast.LENGTH_SHORT).show();
}
private AdapterView.OnItemClickListener mDeviceClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(!mBTAdapter.isEnabled()) {
Toast.makeText(getBaseContext(), getString(R.string.BTnotOn), Toast.LENGTH_SHORT).show();
return;
}
mBluetoothStatus.setText(getString(R.string.cConnet));
// Get the device MAC address, which is the last 17 chars in the View
String info = ((TextView) view).getText().toString();
final String address = info.substring(info.length() - 17);
final String name = info.substring(0,info.length() - 17);
// Spawn a new thread to avoid blocking the GUI one
new Thread()
{
@Override
public void run() {
boolean fail = false;
BluetoothDevice device = mBTAdapter.getRemoteDevice(address);
try {
mBTSocket = createBluetoothSocket(device);
} catch (IOException e) {
fail = true;
Toast.makeText(getBaseContext(), getString(R.string.ErrSockCrea), Toast.LENGTH_SHORT).show();
}
// Establish the Bluetooth socket connection.
try {
mBTSocket.connect();
} catch (IOException e) {
try {
fail = true;
mBTSocket.close();
mHandler.obtainMessage(CONNECTING_STATUS, -1, -1)
.sendToTarget();
} catch (IOException e2) {
//insert code to deal with this
Toast.makeText(getBaseContext(), getString(R.string.ErrSockCrea), Toast.LENGTH_SHORT).show();
}
}
if(!fail) {
mConnectedThread = new ConnectedThread(mBTSocket, mHandler);
mConnectedThread.start();
mHandler.obtainMessage(CONNECTING_STATUS, 1, -1, name)
.sendToTarget();
}
}
}.start();
}
};
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", UUID.class);
return (BluetoothSocket) m.invoke(device, BT_MODULE_UUID);
} catch (Exception e) {
Log.e(TAG, "Could not create Insecure RFComm Connection",e);
}
return device.createRfcommSocketToServiceRecord(BT_MODULE_UUID);
}
}
ConnectedThread.Java
package com.androindian.simplebluetooth;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.SystemClock;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private final Handler mHandler;
public ConnectedThread(BluetoothSocket socket, Handler handler) {
mmSocket = socket;
mHandler = handler;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
@Override
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.available();
if(bytes != 0) {
buffer = new byte[1024];
SystemClock.sleep(100); //pause and wait for rest of data. Adjust this depending on your sending speed.
bytes = mmInStream.available(); // how many bytes are ready to be read?
bytes = mmInStream.read(buffer, 0, bytes); // record how many bytes we actually read
mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget(); // Send the obtained bytes to the UI activity
}
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(String input) {
byte[] bytes = input.getBytes(); //converts entered String into bytes
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androindian.simplebluetooth">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<permission android:name="android.permission.BLUETOOTH" android:label="BLUETOOTH" />
<permission android:name="android.permission.BLUETOOTH_ADMIN" />
<permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>