This guide provides an overview of how to support key use cases for
communicating with peripheral devices when your app is running in the
background:

- [Find a device](https://developer.android.com/develop/connectivity/bluetooth/ble/background#find-device)
- [Connect to a device](https://developer.android.com/develop/connectivity/bluetooth/ble/background#connect-device)
- [Stay connected to a device](https://developer.android.com/develop/connectivity/bluetooth/ble/background#stay-connected)

There are multiple options to support each of these use cases. Each one has
benefits and drawbacks that might make it more or less suitable for your
specific needs.

The following diagram shows a simplified view of the guidance on this page:

![](https://developer.android.com/static/images/develop/connectivity/bluetooth/ble-background.png)
| **Note:** The [general guidance for background
| work](https://developer.android.com/develop/background-work/background-tasks) on Android applies for Bluetooth-related work too.

## Find a device

First, your app needs to find a device to connect to. To find a BLE device you
can use either of the following APIs:

- [`BluetoothLeScanner`](https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner) as described in [Find BLE
  devices](https://developer.android.com/develop/connectivity/bluetooth/ble/find-ble-devices). ([Sample](https://github.com/android/platform-samples/blob/main/samples/connectivity/bluetooth/ble/src/main/java/com/example/platform/connectivity/bluetooth/ble/FindBLEDevicesSample.kt))
- [`CompanionDeviceManager`](https://developer.android.com/reference/android/companion/CompanionDeviceManager) as described in [Companion device
  pairing](https://developer.android.com/develop/connectivity/bluetooth/companion-device-pairing#implement). ([Sample](https://github.com/android/platform-samples/blob/main/samples/connectivity/bluetooth/companion/src/main/java/com/example/platform/connectivity/bluetooth/cdm/CompanionDeviceManagerSample.kt))

| **Note:** `CompanionDeviceManager` has certain limitations (such as limited filtering and no support for random MAC addresses) that might not satisfy your needs depending on the implementation of the peripheral device.

### In the background

There is no limitation on using either of these APIs while the app is not
visible, but they do both need your app process to be alive. If the app process
is not running, you can use the following workarounds:

- For `BluetoothLeScanner`: Call [`startScan()`](https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner#startScan(java.util.List%3Candroid.bluetooth.le.ScanFilter%3E,%20android.bluetooth.le.ScanSettings,%20android.app.PendingIntent)) with a [`PendingIntent`](https://developer.android.com/reference/android/app/PendingIntent) object instead of a [`ScanCallback`](https://developer.android.com/reference/android/bluetooth/le/ScanCallback) object to get notified when a device matching your filter is scanned. ([Sample](https://github.com/android/platform-samples/blob/main/samples/connectivity/bluetooth/ble/src/main/java/com/example/platform/connectivity/bluetooth/ble/BLEScanIntentSample.kt#L163))
- For `CompanionDeviceManager`: Follow the guidance in [Keep companion apps
  awake](https://developer.android.com/develop/connectivity/bluetooth/companion-device-pairing#keep-awake) to wake the app and keep it awake while a previously associated device is in range. ([Sample](https://github.com/android/platform-samples/blob/main/samples/connectivity/bluetooth/companion/src/main/java/com/example/platform/connectivity/bluetooth/cdm/CompanionDeviceSampleService.kt#L40))

| **Note:** Scheduling periodic scans to find devices is discouraged. That approach is less efficient because it starts the app process periodically regardless of whether a device is in range. The methods described in this guide ensure that a device is in range before waking up the app process.

## Connect to a device

To connect to a device after you have found it, you need to get a
[`BluetoothDevice`](https://developer.android.com/reference/android/bluetooth/BluetoothDevice) instance for
the device from one of the following sources:

- A `BluetoothLeScanner` scan result as described in the [previous
  section](https://developer.android.com/develop/connectivity/bluetooth/ble/background#find-device).
- The bonded device list retrieved from [`BluetoothAdapter.getBondedDevices()`](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#getBondedDevices()).
- The `BluetoothAdapter` cache, using [`BluetoothAdapter.getRemoteLeDevice()`](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#getRemoteLeDevice(java.lang.String,%20int)).

After you have a `BluetoothDevice` instance, you can start a connection request
to the corresponding device by calling one of the
[`connectGatt()`](https://developer.android.com/reference/android/bluetooth/BluetoothDevice#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback))
methods. The value that you pass into the `autoConnect` boolean defines which of
the following two connection modes the GATT client uses:

- **Direct connect** (`autoconnect = false`): Try to connect to the peripheral device directly, and fail if the device isn't available. In case of disconnection, the GATT client doesn't automatically try to reconnect.
- **Auto connect** (`autoconnect = true`): Try to automatically connect to the peripheral device whenever it's available. In case of a disconnection initiated by the peripheral or because the peripheral is out of range, the GATT client automatically tries to reconnect when the peripheral is available.

| **Note:** Android versions below 10 allow only one connection request at a time and queue all subsequent requests. In Android 10 and higher, the system groups connection requests for batched execution.

### In the background

There is no restriction on connecting to a device while the app is in the
background, although the connection is closed if your process is killed. In
addition there are [restrictions on starting
activities](https://developer.android.com/guide/components/activities/background-starts) (in Android 10 and
higher) or [foreground
services](https://developer.android.com/about/versions/12/behavior-changes-12#foreground-service-launch-restrictions)
(in Android 12 and higher) from the background.

Thus, to perform a connection while in the background, apps can use the
following solutions:

- Use [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) to connect to your device.
  - You can set a [`PeriodicWorkRequest`](https://developer.android.com/reference/androidx/work/PeriodicWorkRequest) or a [`OneTimeWorkRequest`](https://developer.android.com/reference/androidx/work/OneTimeWorkRequest) to perform a defined action, although [app restrictions might
    apply](https://developer.android.com/topic/performance/appstandby).
  - Additionally, you can benefit from WorkManager features like [work
    constraints](https://developer.android.com/topic/libraries/architecture/workmanager#constraints), [expedited work](https://developer.android.com/topic/libraries/architecture/workmanager#expedited), [retry
    policy](https://developer.android.com/topic/libraries/architecture/workmanager#flexible), and more.
  - If the connection needs to be kept alive as long as possible to perform a task, such as data syncing or polling from the peripheral devices, you need to start a foreground service following the guidance in [Support for
    long-running
    workers](https://developer.android.com/develop/background-work/background-tasks/persistent/how-to/long-running#long-running). However, [foreground service launch restrictions](https://developer.android.com/develop/background-work/services/fgs/restrictions-bg-start) apply starting in Android 12.
- Start a foreground service with the `connectedDevice` type.
  - If the connection needs to be kept alive as long as possible to perform a task, such as data syncing or polling from the peripheral devices, you need to start a foreground service following the guidance in [Support for
    long-running
    workers](https://developer.android.com/develop/background-work/background-tasks/persistent/how-to/long-running#long-running). However, [foreground service launch restrictions](https://developer.android.com/develop/background-work/services/fgs/restrictions-bg-start) apply starting in Android 12.
- Call `startScan()` with a `PendingIntent` object as described in [Find a
  device](https://developer.android.com/develop/connectivity/bluetooth/ble/background#find-device) to wake your process up when the device is present. The peripheral device must be advertising.
  - We recommend that you start a Worker and a Job. This might be interrupted by the system and thus it can only support short duration communication.
  - In versions lower than Android 12 you can start a foreground service directly from the `PendingIntent` object.
- Use [`CompanionDeviceService`](https://developer.android.com/reference/android/companion/CompanionDeviceService) and either of the [`REQUEST_COMPANION_RUN_IN_BACKGROUND`](https://developer.android.com/reference/android/Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND) or [`REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND`](https://developer.android.com/reference/android/Manifest.permission#REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND) permissions to start the service from the background.

## Stay connected to a device

Ideally, apps should maintain connections to peripheral devices only as long as
necessary, and disconnect once the task is completed. However, there are two
cases where an app might need to keep a connection alive indefinitely:

- [While switching between apps](https://developer.android.com/develop/connectivity/bluetooth/ble/background#while-switching).
- [While listening to peripheral notifications](https://developer.android.com/develop/connectivity/bluetooth/ble/background#while-listening).

In both cases, the following options are available:

- Use [`CompanionDeviceService`](https://developer.android.com/reference/android/companion/CompanionDeviceService) with the [`REQUEST_COMPANION_RUN_IN_BACKGROUND`](https://developer.android.com/reference/android/Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND) permission and the [`CompanionDeviceManager.startObservingDevicePresence()`](https://developer.android.com/reference/android/companion/CompanionDeviceManager#startObservingDevicePresence(android.companion.ObservingDevicePresenceRequest)) method.
- [Start a foreground service](https://developer.android.com/develop/background-work/services/fgs/launch) while the app is in the foreground (or within one of the [exemptions](https://developer.android.com/develop/background-work/services/fgs/restrictions-bg-start#background-start-restriction-exemptions)) with the [`connectedDevice`](https://developer.android.com/about/versions/14/changes/fgs-types-required#connected-device) foreground type.

### While switching between apps

Finding a device, connecting to it, and transferring data is time consuming and
resource intensive. To avoid losing connection and having to perform the full
process every time the user switches between apps or performs simultaneous
tasks, you should keep the connection alive until the operation finishes. You
can use either a foreground service with the `connectedDevice` type or the
[companion device presence
API](https://developer.android.com/develop/connectivity/bluetooth/companion-device-pairing#keep-awake).

### While listening to peripheral notifications

To listen to peripheral notifications the app must call
[`setCharacteristicNotification()`](https://developer.android.com/reference/android/bluetooth/BluetoothGatt#setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic,%20boolean)),
listen to callbacks using
[`onCharacteristicChanged()`](https://developer.android.com/reference/android/bluetooth/BluetoothGattCallback#onCharacteristicChanged(android.bluetooth.BluetoothGatt,%20android.bluetooth.BluetoothGattCharacteristic,%20byte[])),
and keep the connection alive. For most apps, it's best to support this use case
with `CompanionDeviceService` because the app will likely need to keep listening
for long periods of time. However, you can also use a foreground service.

In either case, you can reconnect after a terminated process by following the
instructions in the [Connect to a device](https://developer.android.com/develop/connectivity/bluetooth/ble/background#connect-device) section.