This guide covers how to route audio for Bluetooth devices using the
[Telecom API](https://developer.android.com/develop/connectivity/telecom) and set the connection for
VoIP calls. Read the
[Build a calling app](https://developer.android.com/develop/connectivity/telecom/selfManaged) guide
before continuing.

By using the [`ConnectionService`](https://developer.android.com/reference/android/telecom/ConnectionService)
and [`Connection`](https://developer.android.com/reference/android/telecom/Connection) classes, you can access
the audio state and a list of available Bluetooth devices, and can route
audio to a selected Bluetooth device.

## VoIP Connection and ConnectionService

Create a `VoIPConnection` class that extends from
[`Connection`](https://developer.android.com/reference/android/telecom/Connection). This class controls the state of the current call. As the
[Build a calling app](https://developer.android.com/develop/connectivity/telecom/selfManaged) guide
states, make this a self-managed application and set the audio mode for a VoIP
application.  

### Kotlin

```kotlin
class VoIPConnection : Connection() {
  init {
    setConnectionProperties(PROPERTY_SELF_MANAGED)
    setAudioModeIsVoip(true)
  }
}
```

### Java

```java
public class VoIPConnection extends Connection {
  public VoIPConnection() {
    setConnectionProperties(PROPERTY_SELF_MANAGED);
    setAudioModeIsVoip(true);
  }
}
```

Next, return an instance of this class in
[`ConnectionService`](https://developer.android.com/reference/android/telecom/ConnectionService) when an
incoming or outgoing call occurs.  

### Kotlin

```kotlin
class VoIPConnectionService : ConnectionService() {
  override fun onCreateOutgoingConnection(
    connectionManagerPhoneAccount: PhoneAccountHandle,
    request: ConnectionRequest,
  ): Connection {
    return VoIPConnection()
  }
}
```

### Java

```java
public class VoIPConnectionService extends ConnectionService {
  @Override
  public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
    return new VoIPConnection();
  }
}
```

Ensure the manifest correctly points to the `VoIPConnectionService` class.  

    <service android:name=".voip.TelegramConnectionService" android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
      <intent-filter>
        <action android:name="android.telecom.ConnectionService"/>
      </intent-filter>
    </service>

With these custom [`Connection`](https://developer.android.com/reference/android/telecom/Connection) and
[`ConnectionService`](https://developer.android.com/reference/android/telecom/ConnectionService) classes, you
can control which device and what type of audio routing you wish to use during a
call.

## Get the current audio state

To get the current audio state, call
[`getCallAudioState()`](https://developer.android.com/reference/android/telecom/Connection#getCallAudioState()).
[`getCallAudioState()`](https://developer.android.com/reference/android/telecom/Connection#getCallAudioState())
returns if the device is streaming using Bluetooth, Earpiece, Wired, or
Speaker.  

    mAudioState = connection.getCallAudioState()

## On State Changed

Subscribe to changes in CallAudioState by overriding
[`onCallAudioStateChanged()`](https://developer.android.com/reference/android/telecom/Connection#onCallAudioStateChanged(android.telecom.CallAudioState)).
This alerts you of any changes to the state.  

### Kotlin

```kotlin
fun onCallAudioStateChanged(audioState: CallAudioState) {
  mAudioState = audioState
}
```

### Java

```java
@Override
public void onCallAudioStateChanged(CallAudioState audioState) {
  mAudioState = audioState;
}
```

## Get the current device

Get the current active device using
[`CallAudioState.getActiveBluetoothDevice()`](https://developer.android.com/reference/android/telecom/CallAudioState#getActiveBluetoothDevice()).
This function returns the active Bluetooth device.
**Note:** This feature is only available in API level 28 and higher.  

### Kotlin

```kotlin
val activeDevice: BluetoothDevice = mAudioState.getActiveBluetoothDevice()
```

### Java

```java
BluetoothDevice activeDevice = mAudioState.getActiveBluetoothDevice();
```

## Get Bluetooth devices

Get a list of Bluetooth devices that are available for call audio routing using
[`CallAudioState.getSupportedBluetoothDevices()`](https://developer.android.com/reference/android/telecom/CallAudioState#getSupportedBluetoothDevices()).  

### Kotlin

```kotlin
val availableBluetoothDevices: Collection =
  mAudioState.getSupportedBluetoothDevices()
```

### Java

```java
Collection availableBluetoothDevices = mAudioState.getSupportedBluetoothDevices();
```

## Route the call audio

### Using API level 28 and higher (recommended)

Route the call audio to an available Bluetooth device using
[`requestBluetoothAudio(BluetoothDevice)`](https://developer.android.com/reference/android/telecom/Connection#requestBluetoothAudio(android.bluetooth.BluetoothDevice)):  

    requestBluetoothAudio(availableBluetoothDevices[0]);

### Using API level 23 and higher

Enable
[`ROUTE_BLUETOOTH`](https://developer.android.com/reference/android/telecom/CallAudioState#ROUTE_BLUETOOTH)
without specifying the device using
[`setAudioRoute(int)`](https://developer.android.com/reference/android/telecom/Connection#setAudioRoute(int)).
This defaults routing to current, active bluetooth devices on Android 9 and higher.  

    setAudioRoute(CallAudioState.ROUTE_BLUETOOTH);

| **Note:** This step isn't required if the app already knows which Bluetooth device to route audio to.