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`](https://developer.android.com/reference/android/bluetooth/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 [transferring Bluetooth
data](https://developer.android.com/develop/connectivity/bluetooth/transfer-data). This section
describes how to initiate the connection between two devices.

Make sure you have the appropriate
[Bluetooth permissions](https://developer.android.com/develop/connectivity/bluetooth/bt-permissions) and
[set up your app for Bluetooth](https://developer.android.com/develop/connectivity/bluetooth/setup) before
attempting to find Bluetooth 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.

![](https://developer.android.com/static/images/develop/connectivity/bluetooth/bluetooth-pairing.png)   

**Figure 1.** The Bluetooth pairing dialog.
| **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 1. Therefore, when your app 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`](https://developer.android.com/reference/android/bluetooth/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(String, UUID)`](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#listenUsingRfcommWithServiceRecord(java.lang.String,%20java.util.UUID)).

   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 app 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.

   A UUID is a standardized 128-bit format for a string ID used to uniquely
   identify information. A UUID is used to identify information that needs to be
   unique within a system or a network because the probability of a UUID being
   repeated is effectively zero. It is generated independently, without the use
   of a centralized authority. In this case, it's used to uniquely identify your
   app's Bluetooth service. To get a UUID to use with your app, you can use one
   of the many random
   [`UUID`](https://developer.android.com/reference/java/util/UUID) generators on the web, then initialize a
   UUID with
   [`fromString(String)`](https://developer.android.com/reference/java/util/UUID#fromString(java.lang.String)).
2. Start listening for connection requests by calling
   [`accept()`](https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket#accept()).

   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`.
3. Unless you want to accept additional connections, call
   [`close()`](https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket#close()).

   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, do not execute it in the main
activity UI thread. Executing it in another thread ensures that your app 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 app. 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.

#### Example

The following is a simplified thread for the server component that accepts
incoming connections:  

### Kotlin

```kotlin
private inner class AcceptThread : Thread() {

   private val mmServerSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.NONE) {
       bluetoothAdapter?.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID)
   }

   override fun run() {
       // Keep listening until exception occurs or a socket is returned.
       var shouldLoop = true
       while (shouldLoop) {
           val socket: BluetoothSocket? = try {
               mmServerSocket?.accept()
           } catch (e: IOException) {
               Log.e(TAG, "Socket's accept() method failed", e)
               shouldLoop = false
               null
           }
           socket?.also {
               manageMyConnectedSocket(it)
               mmServerSocket?.close()
               shouldLoop = false
           }
       }
   }

   // Closes the connect socket and causes the thread to finish.
   fun cancel() {
       try {
           mmServerSocket?.close()
       } catch (e: IOException) {
           Log.e(TAG, "Could not close the connect socket", e)
       }
   }
}
```

### Java

```java
private class AcceptThread extends Thread {
   private final BluetoothServerSocket mmServerSocket;

   public AcceptThread() {
       // Use a temporary object that is later assigned to mmServerSocket
       // because mmServerSocket is final.
       BluetoothServerSocket tmp = null;
       try {
           // MY_UUID is the app's UUID string, also used by the client code.
           tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
       } catch (IOException e) {
           Log.e(TAG, "Socket's listen() method failed", e);
       }
       mmServerSocket = tmp;
   }

   public void run() {
       BluetoothSocket socket = null;
       // Keep listening until exception occurs or a socket is returned.
       while (true) {
           try {
               socket = mmServerSocket.accept();
           } catch (IOException e) {
               Log.e(TAG, "Socket's accept() method failed", e);
               break;
           }

           if (socket != null) {
               // A connection was accepted. Perform work associated with
               // the connection in a separate thread.
               manageMyConnectedSocket(socket);
               mmServerSocket.close();
               break;
           }
       }
   }

   // Closes the connect socket and causes the thread to finish.
   public void cancel() {
       try {
           mmServerSocket.close();
       } catch (IOException e) {
           Log.e(TAG, "Could not close the connect socket", e);
       }
   }
}
```

In this example, only one incoming connection is desired, so as soon as a
connection is accepted and the `BluetoothSocket` is acquired, the app passes the
acquired `BluetoothSocket` to a separate thread, closes the
`BluetoothServerSocket`, and breaks out of the loop.

Note that when `accept()` returns the `BluetoothSocket`, the socket is already
connected. Therefore, you shouldn't call
[`connect()`](https://developer.android.com/reference/android/bluetooth/BluetoothSocket#connect()), as you do
from the client side.

The app-specific `manageMyConnectedSocket()` method is designed to initiate the
thread for transferring data, which is discussed in the topic about
[transferring Bluetooth
data](https://developer.android.com/develop/connectivity/bluetooth/transfer-data).

Usually, you should close your `BluetoothServerSocket` as soon as you are done
listening for incoming connections. In this example, `close()` is called as soon
as the `BluetoothSocket` is acquired. You may also want to provide a public
method in your thread that can close the private `BluetoothSocket` in the event
that you need to stop listening on that server socket.

### 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 [Find Bluetooth
devices](https://developer.android.com/develop/connectivity/bluetooth/find-bluetooth-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)`](https://developer.android.com/reference/android/bluetooth/BluetoothDevice#createRfcommSocketToServiceRecord(java.util.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)`](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#listenUsingRfcommWithServiceRecord(java.lang.String,%20java.util.UUID))
   to open its `BluetoothServerSocket`. To use a matching UUID, hard-code the
   UUID string into your app, 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`](https://developer.android.com/reference/java/io/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.

#### Example

The following is a basic example of a client thread that initiates a Bluetooth
connection:  

### Kotlin

```kotlin
private inner class ConnectThread(device: BluetoothDevice) : Thread() {

   private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) {
       device.createRfcommSocketToServiceRecord(MY_UUID)
   }

   public override fun run() {
       // Cancel discovery because it otherwise slows down the connection.
       bluetoothAdapter?.cancelDiscovery()

       mmSocket?.let { socket ->
           // Connect to the remote device through the socket. This call blocks
           // until it succeeds or throws an exception.
           socket.connect()

           // The connection attempt succeeded. Perform work associated with
           // the connection in a separate thread.
           manageMyConnectedSocket(socket)
       }
   }

   // Closes the client socket and causes the thread to finish.
   fun cancel() {
       try {
           mmSocket?.close()
       } catch (e: IOException) {
           Log.e(TAG, "Could not close the client socket", e)
       }
   }
}
```

### Java

```java
private class ConnectThread extends Thread {
   private final BluetoothSocket mmSocket;
   private final BluetoothDevice mmDevice;

   public ConnectThread(BluetoothDevice device) {
       // Use a temporary object that is later assigned to mmSocket
       // because mmSocket is final.
       BluetoothSocket tmp = null;
       mmDevice = device;

       try {
           // Get a BluetoothSocket to connect with the given BluetoothDevice.
           // MY_UUID is the app's UUID string, also used in the server code.
           tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
       } catch (IOException e) {
           Log.e(TAG, "Socket's create() method failed", e);
       }
       mmSocket = tmp;
   }

   public void run() {
       // Cancel discovery because it otherwise slows down the connection.
       bluetoothAdapter.cancelDiscovery();

       try {
           // Connect to the remote device through the socket. This call blocks
           // until it succeeds or throws an exception.
           mmSocket.connect();
       } catch (IOException connectException) {
           // Unable to connect; close the socket and return.
           try {
               mmSocket.close();
           } catch (IOException closeException) {
               Log.e(TAG, "Could not close the client socket", closeException);
           }
           return;
       }

       // The connection attempt succeeded. Perform work associated with
       // the connection in a separate thread.
       manageMyConnectedSocket(mmSocket);
   }

   // Closes the client socket and causes the thread to finish.
   public void cancel() {
       try {
           mmSocket.close();
       } catch (IOException e) {
           Log.e(TAG, "Could not close the client socket", e);
       }
   }
}
```

Notice that in this snippet, `cancelDiscovery()` is called before the connection
attempt occurs. You should always call `cancelDiscovery()` before `connect()`,
especially because `cancelDiscovery()` succeeds regardless of whether device
discovery is currently in progress. If your app needs to determine whether
device discovery is in progress, you can check using
[`isDiscovering()`](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#isDiscovering()).

The app-specific `manageMyConnectedSocket()` method is designed to initiate the
thread for transferring data, which is discussed in the section about
[transferring Bluetooth data](https://developer.android.com/develop/connectivity/bluetooth/transfer-data).

When you're done with your `BluetoothSocket`, always call `close()`. Doing so
immediately closes the connected socket and releases all related internal
resources.