MC Exp6
MC Exp6
To implement a Bluetooth network with application as transfer of a file from one device to
another.
Lab Outcome: -
Date of Performance: -
Date of Submission: -
Practical In charge
EXPERIMENT NO. 06
Aim: To implement a Bluetooth network with application as transfer of a file from one device
to another.
Theory:
The Android platform includes support for the Bluetooth network stack, which allows a device to
wirelessly exchange data with other Bluetooth devices. The application framework provides access
to the Bluetooth functionality through the Android Bluetooth APIs. These APIs let applications
wirelessly connect to other Bluetooth devices, enabling point-to-point and multipoint wireless
features.
Using the Bluetooth APIs, an Android application can perform the following:
● Scan for other Bluetooth devices
● Query the local Bluetooth adapter for paired Bluetooth devices
● Establish RFCOMM channels
● Connect to other devices through service discovery
● Transfer data to and from other devices
● Manage multiple connections
Classic Bluetooth is the right choice for more battery-intensive operations, which include
streaming and communicating between Android devices. For Bluetooth devices with low power
requirements, Android 4.3 (API level 18) introduces API support for Bluetooth Low Energy.
The basics: In order for Bluetooth-enabled devices to transmit data between each other, they must
first form a channel of communication using a pairing process. One device, a discoverable device,
makes itself available for incoming connection requests. Another device finds the discoverable
device using a service discovery process. After the discoverable device accepts the pairing request,
the two devices complete a bonding process where they exchange security keys. The devices cache
these keys for later use. After the pairing and bonding processes are complete, the two devices
exchange information. When the session is complete, the device that initiated the pairing request
releases the channel that had linked it to the discoverable device. The two devices remain bonded,
however, so they can reconnect automatically during a future session as long as they're in range of
each other and neither device has removed the bond.
Bluetooth permissions: In order to use Bluetooth features in your application, you must declare two
permissions. The first of these is BLUETOOTH. You need this permission to perform any
Bluetooth communication, such as requesting a connection, accepting a connection, and
transferring data.
The other permission that you must declare is ACCESS_FINE_LOCATION. Your app needs this
permission because a Bluetooth scan can be used to gather information about the location of the
user. This information may come from the user's own devices, as well as Bluetooth beacons in
use at locations such as shops and transit facilities.
If you want your app to initiate device discovery or manipulate Bluetooth settings, you must
declare the BLUETOOTH_ADMIN permission in addition to the BLUETOOTH permission. Most
applications need this permission solely for the ability to discover local Bluetooth devices. The
other abilities granted by this permission should not be used, unless the application is a "power
manager" that modifies Bluetooth settings upon user request.
Declare the Bluetooth permission(s) in your application manifest file. For example:
<manifest ... >
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
Work with profiles: Starting in Android 3.0, the Bluetooth API includes support for working
with Bluetooth profiles. A Bluetooth profile is a wireless interface specification for Bluetooth-
based communication between devices. An example is the Hands-Free profile. For a mobile
phone to connect to a wireless headset, both devices must support the Hands-Free profile.
The Android Bluetooth API provides implementations for the following Bluetooth profiles:
● Headset: The Headset profile provides support for Bluetooth headsets to be used
with mobile phones. Android provides the BluetoothHeadset class, which is a proxy
for controlling the Bluetooth Headset Service. This includes both Bluetooth Headset
and Hands-Free (v1.5) profiles. The BluetoothHeadset class includes support for AT
commands. For more discussion of this topic, see Vendor-specific AT commands
● A2DP: The Advanced Audio Distribution Profile (A2DP) profile defines how high
quality audio can be streamed from one device to another over a Bluetooth connection.
Android provides the BluetoothA2dp class, which is a proxy for controlling the Bluetooth
A2DP Service.
● Health Device: Android 4.0 (API level 14) introduces support for the Bluetooth Health
Device Profile (HDP). This lets you create applications that use Bluetooth to
communicate with health devices that support Bluetooth, such as heart-rate monitors,
blood meters, thermometers, scales, and so on.
Here are the basic steps for working with a profile:
1. Get the default adapter, as described in Setting Up Bluetooth.
2. Set up a BluetoothProfile.ServiceListener. This listener notifies BluetoothProfile
clients when they have been connected to or disconnected from the service.
3. Use getProfileProxy() to establish a connection to the profile proxy object associated
with the profile. In the example below, the profile proxy object is an instance of
BluetoothHeadset.
4. In onServiceConnected(), get a handle to the profile proxy object.
5. Once you have the profile proxy object, you can use it to monitor the state of the
connection and perform other operations that are relevant to that profile.
Vendor-specific AT commands:
Starting in Android 3.0 (API level 11), applications can register to receive system broadcasts of
predefined vendor-specific AT commands sent by headsets (such as a Plantronics +XEVENT
command). For example, an application could receive broadcasts that indicate a connected device's
battery level and could notify the user or take other action as needed. Create a broadcast receiver
for the ACTION_VENDOR_SPECIFIC_HEADSET_EVENT intent to handle vendor-specific AT
commands for the headset.
Health device profile:
Android 4.0 (API level 14) introduces support for the Bluetooth Health Device Profile (HDP). This
lets you create applications that use Bluetooth to communicate with health devices that support
Bluetooth, such as heart-rate monitors, blood meters, thermometers, and scales. The Bluetooth
Health API includes the classes BluetoothHealth, BluetoothHealthCallback, and
BluetoothHealthAppConfiguration, which are described in Key Classes and Interfaces.
In using the Bluetooth Health API, it's helpful to understand these key HDP
concepts: Source:
A health device-such as a weight scale, glucose meter, or thermometer-that transmits medical
data to a smart device, such as an Android phone or tablet.
Sink:
The smart device that receives the medical data. In an Android HDP application, the sink
is represented by a BluetoothHealthAppConfiguration object.
Registration:
The process used to register a sink for communicating with a particular health device.
Connection:
The process used to open a channel between a health device (source) and a smart device (sink).
Here are the basic steps involved in creating an Android HDP application:
1. Get a reference to the BluetoothHealth proxy object.
Similar to regular headset and A2DP profile devices, you must call getProfileProxy() with a
BluetoothProfile.ServiceListener and the HEALTH profile type to establish a connection
with the profile proxy object.
2. Create a BluetoothHealthCallback and registeran application configuration
(BluetoothHealthAppConfiguration) that acts as a health sink.
3. Establish a connection to a health device.
Note: Some devices initiate the connection automatically. It is unnecessary to carry out
this step for those devices.
4. When connected successfully to a health device, read/write to the health device using
the file descriptor. The received data need to be interpreted using a health manager
which implements the IEEE 11073 specifications.
5. When done, close the health channel and unregister the application. The channel also
closes when there is extended inactivity.
Set up Bluetooth
Before your application can communicate over Bluetooth, you need to verify that Bluetooth
is supported on the device, and if so, ensure that it is enabled.
If Bluetooth isn't supported, then you should gracefully disable any Bluetooth features. If
Bluetooth is supported, but disabled, then you can request that the user enable Bluetooth without
leaving your application. This setup is accomplished in two steps, using the BluetoothAdapter
1. Get the BluetoothAdapter.
The BluetoothAdapter is required for any and all Bluetooth activity. To get the
BluetoothAdapter, call the static getDefaultAdapter() method. This returns a
BluetoothAdapter that represents the device's own Bluetooth adapter (the Bluetooth radio).
There's one Bluetooth adapter for the entire system, and your application can interact with it
using this object. If getDefaultAdapter() returns null, then the device doesn't support
Bluetooth. For example:
BluetoothAdapter bluetoothAdapter =
BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) {
// Device doesn't support Bluetooth
}
2. Enable Bluetooth.
Next, you need to ensure that Bluetooth is enabled. Call isEnabled() to check whether
Bluetooth is currently enabled. If this method returns false, then Bluetooth is disabled. To
request that Bluetooth be enabled, call startActivityForResult(), passing in
an ACTION_REQUEST_ENABLE intent action. This call issues a request to
enable Bluetooth through the system settings (without stopping your application). For
example:
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent =
new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
A dialog appears requesting user permission to enable Bluetooth, as shown in Figure 1. If the user
responds "Yes", the system begins to enable Bluetooth, and focus returns to your application once
the process completes (or fails).
If enabling Bluetooth succeeds, your activity receives the RESULT_OK result code in the
onActivityResult() callback. If Bluetooth was not enabled due to an error (or the user responded
"No") then the result code is RESULT_CANCELED.
Optionally, your application can also listen for the ACTION_STATE_CHANGED broadcast
intent, which the system broadcasts whenever the Bluetooth state changes. This broadcast contains
the extra fields EXTRA_STATE and EXTRA_PREVIOUS_STATE, containing the new and old
Bluetooth states, respectively. Possible values for these extra fields are STATE_TURNING_ON,
STATE_ON, STATE_TURNING_OFF, and STATE_OFF. Listening for this broadcast can be
useful if your app needs to detect runtime changes made to the Bluetooth state.
Find devices
Using the BluetoothAdapter, you can find remote Bluetooth devices either through
device discovery or by querying the list of paired devices.
Device discovery is a scanning procedure that searches the local area for Bluetooth-enabled devices
and requests some information about each one. This process is sometimes referred to as
discovering, inquiring, or scanning. However, a nearby Bluetooth device responds to a discovery
request only if it is currently accepting information requests by being discoverable. If a device is
discoverable, it responds to the discovery request by sharing some information, such as the device's
name, its class, and its unique MAC address. Using this information, the device that is performing
the discovery process can then choose to initiate a connection to the discovered device.
Once a connection is made with a remote device for the first time, a pairing request is automatically
presented to the user. When a device is paired, the basic information about that device—such as the
device's name, class, and MAC address—is saved and can be read using the Bluetooth APIs. Using
the known MAC address for a remote device, a connection can be initiated with it at any time
without performing discovery, assuming the device is still within range.
Note that there is a difference between being paired and being connected:
● To be paired means that two devices are aware of each other's existence, have a shared
link- key that can be used for authentication, and are capable of establishing an encrypted
connection with each other.
● To be connected means that the devices currently share an RFCOMM channel and are able
to transmit data with each other. The current Android Bluetooth API's require devices to be
paired before an RFCOMM connection can be established. Pairing is automatically
performed when you initiate an encrypted connection with the Bluetooth APIs.
The following sections describe how to find devices that have been paired, or discover new
devices using device discovery.
Before performing device discovery, it's worth querying the set of paired devices to see if the
desired device is already known. To do so, call getBondedDevices(). This returns a set of
BluetoothDevice objects representing paired devices. For example, you can query all paired
devices and get the name and MAC address of each device, as the following code snippet
demonstrates:
Set<BluetoothDevice> pairedDevices =
To initiate a connection with a Bluetooth device, all that's needed from the associated BluetoothDevice object
is the MAC address, which you retrieve by calling getAddress().
Discover devices
To start discovering devices, simply call startDiscovery(). The process is asynchronous and returns
a boolean value indicating whether discovery has successfully started. The discovery process
usually involves an inquiry scan of about 12 seconds, followed by a page scan of each device found
to retrieve its Bluetooth name.
In order to receive information about each device discovered, your application must register a
BroadcastReceiver for the ACTION_FOUND intent. The system broadcasts this intent for each
device. The intent contains the extra fields EXTRA_DEVICE and EXTRA_CLASS, which in turn
contain a BluetoothDevice and a BluetoothClass, respectively.
Enable discoverability
If you would like to make the local device discoverable to other devices, call
startActivityForResult(Intent,int) with the ACTION_REQUEST_DISCOVERABLE intent. This
issues a request to enable the system's discoverable mode without having to navigate to the Settings
app, which would stop your own app. By default, the device becomes discoverable for 120
seconds, or 2 minutes. You can define a different duration, up to 3600 seconds (1 hour), by adding
the EXTRA_DISCOVERABLE_DURATION extra.
The following code snippet sets the device to be discoverable for 5 minutes (300 seconds):
Intent discoverableIntent =
new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
300); startActivity(discoverableIntent);
A dialog is displayed, requesting the user's permission to make the device discoverable, as shown
in Figure 2. If the user responds "Yes," then the device becomes discoverable for the specified
amount of time. Your activity then receives a call to the onActivityResult() callback, with the result
code equal to the duration that the device is discoverable. If the user responded "No", or if an error
occurred, the result code is RESULT_CANCELED.
Note: If Bluetooth has not been enabled on the device, then making the device
discoverable automatically enables Bluetooth.
The device silently remains in discoverable mode for the allotted time. If you would like to
be notified when the discoverable mode has changed, you can register a BroadcastReceiver
for the ACTION_SCAN_MODE_CHANGED intent. This intent contains the extra fields
EXTRA_SCAN_MODE and EXTRA_PREVIOUS_SCAN_MODE, which provide the new and
old scan mode, respectively. Possible values for each extra are as follows:
SCAN_MODE_CONNECTABLE_DISCOVERABLE
The device is in discoverable mode.
SCAN_MODE_CONNECTABLE
The device isn't in discoverable mode but can still receive connections.
SCAN_MODE_NONE
The device isn't in discoverable mode and cannot receive connections.
If you are initiating the connection to a remote device, you don't need to enable device
discoverability. Enabling discoverability is only necessary when you want your application to host
a server socket that accepts incoming connections, as remote devices must be able to discover other
devices before initiating connections to those other devices.
Connect devices
In order to create a connection between two devices, you must implement both the server-side and
client-side mechanisms because one device must open a server socket, and the other one must
initiate the connection using the server device's MAC address. The server device and the client
device each obtain the required BluetoothSocket in different ways. The server receives socket
information when an incoming connection is accepted. The client provides socket information
when it opens an RFCOMM channel to the server.
The server and client are considered connected to each other when they each have a connected
BluetoothSocket on the same RFCOMM channel. At this point, each device can obtain input and
output streams, and data transfer can begin, which is discussed in the section about Manage a
connection. This section describes how to initiate the connection between two devices.
Connection techniques
One implementation technique is to automatically prepare each device as a server so that each
device has a server socket open and listening for connections. In this case, either device can initiate
a connection with the other and become the client. Alternatively, one device can explicitly host the
connection and open a server socket on demand, and the other device initiates the connection.
Note: If the two devices have not been previously paired, then the Android framework
automatically shows a pairing request notification or dialog to the user during the connection
procedure, as shown in Figure 3. Therefore, when your application attempts to connect devices, it
doesn't need to be concerned about whether or not the devices are paired. Your RFCOMM
connection attempt gets blocked until the user has successfully paired the two devices, and the
attempt fails if the user rejects pairing, or if the pairing process fails or times out.
Connect as a server
When you want to connect two devices, one must act as a server by holding an open
BluetoothServerSocket. The purpose of the server socket is to listen for incoming connection
requests and provide a connected BluetoothSocket after a request is accepted. When the
BluetoothSocket is acquired from the BluetoothServerSocket,
the BluetoothServerSocket can—and should—be discarded, unless you want the device to
accept more connections.
To set up a server socket and accept a connection, complete the following sequence of steps:
1. Get a BluetoothServerSocket by calling listenUsingRfcommWithServiceRecord().
The string is an identifiable name of your service, which the system automatically writes to a
new Service Discovery Protocol (SDP) database entry on the device. The name is arbitrary and
can simply be your application name. The Universally Unique Identifier (UUID) is also
included in the SDP entry and forms the basis for the connection agreement with the client
device. That is, when the client attempts to connect with this device, it carries a UUID that
uniquely identifies the service with which it wants to connect. These UUIDs must match in
order for the connection to be accepted.
This is a blocking call. It returns when either a connection has been accepted or an
exception has occurred. A connection is accepted only when a remote device has sent a
connection request containing a UUID that matches the one registered with this listening
server socket. When successful, accept() returns a connected BluetoothSocket.
This method call releases the server socket and all its resources, but doesn't close the
connected BluetoothSocket that's been returned by accept(). Unlike TCP/IP, RFCOMM
allows only one connected client per channel at a time, so in most cases, it makes sense to
call close() on the BluetoothServerSocket immediately after accepting a connected socket.
Because the accept() call is a blocking call, it should not be executed in the main activity UI
thread so that your application can still respond to other user interactions. It usually makes sense
to do all work that involves a BluetoothServerSocket or BluetoothSocket in a new thread managed
by your application. To abort a blocked call such as accept(), call close() on the
BluetoothServerSocket or BluetoothSocket from another thread. Note that all methods on a
BluetoothServerSocket or BluetoothSocket are thread-safe
Connect as a client
In order to initiate a connection with a remote device that is accepting connections on an open
server socket, you must first obtain a BluetoothDevice object that represents the remote device. To
learn how to create a BluetoothDevice, see Finding Devices. You must then use the
BluetoothDevice to acquire a BluetoothSocket and initiate the connection.
The basic procedure is as follows:
1. Using the BluetoothDevice, get a BluetoothSocket by calling
createRfcommSocketToServiceRecord(UUID). This method initializes a
BluetoothSocket object that allows the client to connect to a BluetoothDevice. The
UUID passed here must match the UUID used by the server device when it
called listenUsingRfcommWithServiceRecord(String, UUID) to open its
BluetoothServerSocket. To use a matching UUID, hard-code the UUID string into
your application, and then reference it from both the server and client code.
2. Initiate the connection by calling connect(). Note that this method is a blocking call. After
a client calls this method, the system performs an SDP lookup to find the remote device
with the matching UUID. If the lookup is successful and the remote device accepts the
connection, it shares the RFCOMM channel to use during the connection, and the
connect() method returns. If the connection fails, or if the connect() method times out (after
about 12 seconds), then the method throws an IOException.
Because connect() is a blocking call, you should always perform this connection procedure in
a thread that is separate from the main activity (UI) thread.
Manage a connection
After you have successfully connected multiple devices, each one has a connected
BluetoothSocket. This is where the fun begins because you can share information between devices.
Using the BluetoothSocket, the general procedure to transfer data is as follows:
1. Get the InputStream and OutputStream that handle transmissions through the socket
using getInputStream() and getOutputStream(), respectively.
2. Read and write data to the streams using read(byte[]) and write(byte[]).
There are, of course, implementation details to consider. In particular, you should use a
dedicated thread for reading from the stream and writing to it. This is important because both
the read(byte[]) and write(byte[]) methods are blocking calls. The read(byte[]) method blocks until
there is something to read from the stream. The write(byte[]) method doesn't usually block, but it
can block for flow control if the remote device isn't calling read(byte[]) quickly enough and the
intermediate buffers become full as a result. So, your main loop in the thread should be dedicated
to reading from the InputStream. A separate public method in the thread can be used to initiate
writes to the OutputStream
All of the Bluetooth APIs are available in the android.bluetooth package. Here's a summary of
the classes and interfaces you need to create Bluetooth connections:
BluetoothAdapter
Represents the local Bluetooth adapter (Bluetooth radio). The BluetoothAdapter is the entry-point
for all Bluetooth interaction. Using this, you can discover other Bluetooth devices, query a list of
bonded (paired) devices, instantiate a BluetoothDevice using a known MAC address, and create a
BluetoothServerSocket to listen for communications from other devices.
BluetoothDevice
Represents a remote Bluetooth device. Use this to request a connection with a remote device
through a BluetoothSocket or query information about the device such as its name, address, class,
and bonding state.
BluetoothSocket
Represents the interface for a Bluetooth socket (similar to a TCP Socket). This is the connection
point that allows an application to exchange data with another Bluetooth device using InputStream
and OutputStream.
BluetoothServerSocket
Represents an open server socket that listens for incoming requests (similar to a TCP
ServerSocket). In order to connect two Android devices, one device must open a server socket with
this class. When a remote Bluetooth device makes a connection request to this device, the device
accepts the connection, then returns a connected BluetoothSocket.
BluetoothClass
Describes the general characteristics and capabilities of a Bluetooth device. This is a read-only set
of properties that defines the device's classes and services. Although this information provides a
useful hint regarding a device's type, the attributes of this class don't necessarily describe all
Bluetooth profiles and services that the device supports.
BluetoothProfile
An interface that represents a Bluetooth profile. A Bluetooth profile is a wireless interface
specification for Bluetooth-based communication between devices. An example is the Hands-Free
profile. For more discussion of profiles, see Working with Profiles.
BluetoothHeadset
Provides support for Bluetooth headsets to be used with mobile phones. This includes both
the Bluetooth Headset profile and the Hands-Free (v1.5) profile.
BluetoothA2dp
Defines how high-quality audio can be streamed from one device to another over a
Bluetooth connection using the Advanced Audio Distribution Profile (A2DP).
BluetoothHealth
Represents a Health Device Profile proxy that controls the Bluetooth service.
BluetoothHealthCallback
An abstract class that you use to implement BluetoothHealth callbacks. You must extend this class
and implement the callback methods to receive updates about changes in the application’s
registration state and Bluetooth channel state.
BluetoothHealthAppConfiguration
Represents an application configuration that the Bluetooth Health third-party application
registers to communicate with a remote Bluetooth health device.
BluetoothProfile.ServiceListener
An interface that notifies BluetoothProfile interprocess communication (IPC) clients when
they have been connected to or disconnected from the internal service that runs a particular
profile.
PROGRAM-
XML File
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Your Bluetooth Connection"
android:textAlignment="center"
android:textColor="#673AB7"
android:textSize="20sp" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Turn on" />
<Space
android:layout_width="match_parent"
android:layout_height="20dp"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Turn off" />
<Space
android:layout_width="match_parent"
android:layout_height="20dp"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Visible" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
JAVA File
package com.example.bluetooth;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
b1 = findViewById(R.id.button);
b2 = findViewById(R.id.button2);
b3 = findViewById(R.id.button3);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
activityResultLauncher.launch(intent);
}
});
b2.setOnClickListener(new View.OnClickListener() {
@SuppressLint("MissingPermission")
@Override
public void onClick(View view) {
bluetoothAdapter.disable();
}
});
b3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
activityResultLauncher.launch(intent);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}
OUTPUT-
CONCLUSION:
Thus, we have studied how to implement a Bluetooth network with application as transfer of a file
from one device to another