Communicate in the background

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:

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:

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:

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:

Connect to a device

To connect to a device after you have found it, you need to get a BluetoothDevice instance for the device from one of the following sources:

After you have a BluetoothDevice instance, you can start a connection request to the corresponding device by calling one of the connectGatt() 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.

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 (in Android 10 and higher) or foreground services (in Android 12 and higher) from the background.

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

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:

In both cases, the following options are available:

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.

While listening to peripheral notifications

To listen to peripheral notifications the app must call setCharacteristicNotification(), listen to callbacks using onCharacteristicChanged(), 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 section.