This guide describes how apps on Wear OS can use familiar Android APIs to play audio.

## Detect audio devices


A Wear OS app must first detect whether the wearable device has an appropriate audio output.
Developers can expect wearables to have at least one of the following audio outputs available:

- [AudioDeviceInfo.TYPE_BUILTIN_SPEAKER](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BUILTIN_SPEAKER): on devices that have a built-in speaker
- [AudioDeviceInfo.TYPE_BLUETOOTH_A2DP](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BLUETOOTH_A2DP): when a Bluetooth headset is paired and connected
- [AudioDeviceInfo.TYPE_BLE_BROADCAST](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BLE_BROADCAST): when a Bluetooth Low Energy (BLE) broadcast group device is paired and connected
- [AudioDeviceInfo.TYPE_BLE_HEADSET](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BLE_HEADSET): when a BLE headset is paired and connected
- [AudioDeviceInfo.TYPE_BLE_SPEAKER](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BLE_SPEAKER): when a BLE speaker is paired and connected


In the following example, the app uses the
[getDevices()](https://developer.android.com/reference/android/media/AudioManager#getDevices(int))
method in conjunction with the value of `FEATURE_AUDIO_OUTPUT` to enumerate all audio
outputs.  

```kotlin
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

fun audioOutputAvailable(type: Int): Boolean {
    if (!packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
        return false
    }
    return audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS).any { it.type == type }
}

// True if the device has a speaker
audioOutputAvailable(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)

// True if a Bluetooth headset is paired and connected
audioOutputAvailable(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP)

// True if a BLE broadcast group device is paired and connected
audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_BROADCAST)

// True if a BLE headset is paired and connected
audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_HEADSET)

// True if a BLE speaker is paired and connected
audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_SPEAKER)
```

To give the best user experience, your app should make sure to only play media when Bluetooth
headphones or speakers are connected to the watch.

## Choose preferred device for audio output

Depending on your app's use case, and the importance of audio to your app's core experience,
choose how you'd like users to engage with your app's audio output.

### Let user choose media output device

Starting in Wear OS 5, the system provides a UI that lets users choose which
device should play media and show information about the currently-playing media
content.

If your app detects that there isn't a Bluetooth headset connected when you want
to provide audio playback on devices running Wear OS 5 or higher, offer to take
the user directly to media output switcher. On devices that don't support the
media output switcher, invoke the [`ACTION_BLUETOOTH_SETTINGS`](https://developer.android.com/reference/android/provider/Settings#ACTION_BLUETOOTH_SETTINGS) intent
action, which takes the user to the Bluetooth page in system settings.

The [`launchOutputSelection()`](https://github.com/google/horologist/blob/v0.5.26/media/audio/src/main/java/com/google/android/horologist/audio/SystemAudioRepository.kt#L108) method, part of the [Horologist](https://github.com/google/horologist) library
on GitHub, demonstrates how to let the user choose their media output device.

### Bluetooth headset


Unlike built-in speakers, which are always available if present on the device, a Bluetooth headset
can be paired or unpaired while an app runs. If the app requires a headset to continue,
register a callback to detect when
the user connects and disconnects a Bluetooth headset using
[registerAudioDeviceCallback](https://developer.android.com/reference/android/media/AudioManager#registerAudioDeviceCallback(android.media.AudioDeviceCallback,%20android.os.Handler)):

<br />

```kotlin
audioManager.registerAudioDeviceCallback(object : AudioDeviceCallback() {
    override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
        super.onAudioDevicesAdded(addedDevices)
        if (audioOutputAvailable(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP)
          || audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_BROADCAST)
          || audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_HEADSET)
          || audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_SPEAKER)) {
            // A Bluetooth or BLE device is connected and available for playback.
        }
    }
    override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
        super.onAudioDevicesRemoved(removedDevices)
        if (!(audioOutputAvailable(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP))
          && !(audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_BROADCAST))
          && !(audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_HEADSET))
          && !(audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_SPEAKER))) {
            // No Bluetooth or BLE devices are connected anymore.
        }
    }
}, null)
  
```

<br />

If your app detects that there isn't a Bluetooth headset connected when you want to provide audio
output, don't show an error message. Instead, offer to take the user directly to Bluetooth settings
to make it easier for them to connect. This can be done by sending an intent with
[ACTION_BLUETOOTH_SETTINGS](https://developer.android.com/reference/android/provider/Settings#ACTION_BLUETOOTH_SETTINGS):

<br />

```kotlin
  val intent = with (Intent(Settings.ACTION_BLUETOOTH_SETTINGS)) {
      addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
      putExtra("EXTRA_CONNECTION_ONLY", true)
      putExtra("EXTRA_CLOSE_ON_CONNECT", true)
      putExtra("android.bluetooth.devicepicker.extra.FILTER_TYPE", 1)
  }
  startActivity(intent)
  
```

<br />

<br />

### Built-in speakers


Most Wear OS devices have built-in speakers. If your app offers a non-media use case that incorporates
sound, consider using speakers to offer an extra dimension of engagement with the user. For
example, a speaker-equipped Wear OS device might trigger a clock or timer alarm, complete with
audio notification, and fitness apps might use the speaker to provide exercise instructions.

**Note:**Built-in speakers don't deliver the best experience for listening to media
content as they aren't designed for this purpose.


Refer to the [WearSpeakerSample](https://github.com/android/wear-os-samples/tree/main/WearSpeakerSample) for details.

<br />

## Play audio


Once you detect and choose a suitable audio output, the process for playing audio on Wear OS is the same
as on mobile or other devices. For more information, see [MediaPlayer overview](https://developer.android.com/guide/topics/media/mediaplayer).
For easier access to more advanced features, such as streaming and downloading media, use
[ExoPlayer](https://developer.android.com/guide/topics/media/exoplayer).
Make sure to follow best practices for Audio apps such as [Managing Audio focus.](https://developer.android.com/guide/topics/media/media-apps/audio-focus)

### Prevent unintended media playback through built-in speakers

| **Note:** If you are targeting Android 15 (API level 35) or higher, the media output switcher provides the watch built-in speakers as one of the selectable options on supported Wear OS devices. To support this feature when using Exoplayer, update to version 1.5.0 or later version.

<br />


Media apps can follow the following guidance to make sure the app does not unintentionally play
media content on built-in watch speakers. The guidance is different based on which player the
app is using.

#### ExoPlayer


If your app is using ExoPlayer:

<br />

<br />

1. Call [setSuppressPlaybackOnUnsuitableOutput(true)](https://developer.android.com/reference/kotlin/androidx/media3/exoplayer/ExoPlayer.Builder#setSuppressPlaybackOnUnsuitableOutput(boolean))
   while building the ExoPlayer instance:

   ```kotlin
     ExoPlayer exoplayer = ExoPlayer.Builder(context)
             .setAudioAttributes(...)
             .setSuppressPlaybackWhenUnsuitableOutput(true)
             // ...
             .build()
         
   ```
2. React to the playback suppression event by registering
   [WearUnsuitableOutputPlaybackSuppressionResolverListener](https://developer.android.com/reference/kotlin/androidx/media3/ui/WearUnsuitableOutputPlaybackSuppressionResolverListener)
   as a listener of the ExoPlayer instance:

```kotlin
  exoPlayer.addListener(WearUnsuitableOutputPlaybackSuppressionResolverListener(context))
    
```

<br />

<br />

#### Horologist Media toolkit


The [Horologist MediaToolkit](https://google.github.io/horologist/media-toolkit/) already contains logic to prevent unintended media playback on built-in watch speakers.

<br />

<br />

#### Other media players

- Make sure that media audio playback doesn't start unless a suitable output device, such as a headset or a set of external speakers, is [connected](https://developer.android.com/reference/android/media/AudioManager#getDevices(int)) to the watch. See the following list for suitable output devices for media apps:
  - [`TYPE_BLUETOOTH_A2DP`](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BLUETOOTH_A2DP)
  - [`TYPE_BLE_BROADCAST`](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BLE_BROADCAST)
  - [`TYPE_BLE_HEADSET`](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BLE_HEADSET)
  - [`TYPE_BLE_SPEAKER`](https://developer.android.com/reference/android/media/AudioDeviceInfo#TYPE_BLE_SPEAKER)
- Pause the playback if [AudioManager](https://developer.android.com/reference/android/media/AudioManager) notifies your app that an external audio output device [becomes disconnected from the watch](https://developer.android.com/reference/android/media/AudioDeviceCallback#onAudioDevicesRemoved(android.media.AudioDeviceInfo[])).
- When the user attempts to initiate media playback but hasn't connected an external audio device, [prompt the user to connect](https://developer.android.com/training/wearables/apps/audio#prompt-the-user-to-connect-a-headset) such a device to their watch.

<br />