Cómo reproducir audio en wearables

En esta guía, se describe cómo puedes usar las APIs de Android conocidas para reproducir audio en apps de Wear OS.

Detecta los dispositivos de audio

Una app para Wear OS primero debe detectar si el dispositivo wearable tiene una salida de audio adecuada. Por lo general, los dispositivos wearables tienen, al menos, una de las siguientes salidas de audio:

  • AudioDeviceInfo.TYPE_BUILTIN_SPEAKER: En dispositivos con una bocina integrada
  • AudioDeviceInfo.TYPE_BLUETOOTH_A2DP: Cuando se vinculan y se conectan auriculares Bluetooth
  • AudioDeviceInfo.TYPE_BLE_BROADCAST: Cuando se vincula y conecta un dispositivo del grupo de transmisión Bluetooth de bajo consumo (BLE).
  • AudioDeviceInfo.TYPE_BLE_HEADSET: Cuando se vinculan y se conectan auriculares BLE
  • AudioDeviceInfo.TYPE_BLE_SPEAKER: Cuando se vincula y conecta una bocina BLE.

En el siguiente ejemplo, se usa el método getDevices() con el valor FEATURE_AUDIO_OUTPUT para verificar si hay disponible un tipo de salida de audio.

private val audioManager: AudioManager by lazy {
    getSystemService(AUDIO_SERVICE) as AudioManager
}

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 }
}

Luego, puedes usar este método para verificar si hay disponible un tipo de salida de audio.

val hasSpeaker = audioOutputAvailable(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)
val hasBluetoothHeadset = audioOutputAvailable(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP)
val hasBLEBroadcast = audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_BROADCAST)
val hasBLEHeadset = audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_HEADSET)
val hasBLESpeaker = audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_SPEAKER)

Para brindar la mejor experiencia del usuario, reproduce contenido multimedia solo cuando los auriculares o las bocinas Bluetooth estén conectados al reloj.

Cómo elegir el dispositivo preferido para la salida de audio

Según el caso de uso de tu app y la importancia del audio para su experiencia principal, elige cómo interactúan los usuarios con la salida de audio de tu app.

Permite que el usuario elija el dispositivo de salida de medios

A partir de Wear OS 5, el sistema proporciona una IU que permite a los usuarios elegir qué dispositivo reproduce contenido multimedia y muestra información sobre el contenido multimedia que se está reproduciendo.

Si tu app detecta que no hay auriculares Bluetooth conectados cuando quieres proporcionar reproducción de audio en dispositivos con Wear OS 5 o versiones posteriores, ofrece llevar al usuario directamente al selector de salida de medios. En los dispositivos que no admiten el selector de salida de medios, invoca la acción de intent ACTION_BLUETOOTH_SETTINGS, que lleva al usuario a la página de Bluetooth en la configuración del sistema.

El método launchOutputSelection(), que forma parte de la biblioteca Horologist en GitHub, muestra cómo permitir que los usuarios elijan su dispositivo de salida de contenido multimedia.

Auriculares Bluetooth

A diferencia de las bocinas integradas, que siempre están disponibles si el dispositivo cuenta con ellas, los auriculares Bluetooth se pueden vincular o desvincular mientras se ejecuta una app. Si tu app requiere auriculares para continuar, registra una devolución de llamada para detectar cuándo el usuario conecta y desconecta los auriculares Bluetooth con registerAudioDeviceCallback:

val audioDeviceCallback =
    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.
            }
        }
    }

audioManager.registerAudioDeviceCallback(audioDeviceCallback, /*handler=*/ null)

Si la app detecta que no hay auriculares Bluetooth conectados cuando quieres proporcionar una salida de audio, no muestres un mensaje de error. En cambio, ofrece llevar al usuario directamente a la configuración de Bluetooth para facilitar la conexión. Para ello, se envía un intent con ACTION_BLUETOOTH_SETTINGS:

fun Context.launchBluetoothSettings(closeOnConnect: Boolean = true) {
    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)
        if (closeOnConnect) {
            putExtra("EXTRA_CLOSE_ON_CONNECT", true)
        }
        putExtra("android.bluetooth.devicepicker.extra.FILTER_TYPE", FILTER_TYPE_AUDIO)
    }
    startActivity(intent)
}

internal const val FILTER_TYPE_AUDIO = 1

Bocinas integradas

La mayoría de los dispositivos Wear OS tienen bocinas integradas. Si tu app ofrece un caso de uso que no es multimedia y que usa sonido, considera usar bocinas para ofrecer una dimensión adicional de participación. Por ejemplo, un dispositivo Wear OS con bocina incorporada podría activar un reloj o una alarma de cronómetro con una notificación de audio, y las apps de fitness podrían usar la bocina para proporcionar instrucciones de ejercicio.

Consulta WearSpeakerSample para obtener más información.

Cómo reproducir audio

Después de detectar y elegir una salida de audio adecuada, la reproducción de audio en Wear OS es la misma que en el dispositivo móvil o algún otro dispositivo. Para obtener más información, consulta la descripción general de MediaPlayer. Para facilitar el acceso a funciones avanzadas, como la transmisión y la descarga de contenido multimedia, usa ExoPlayer. Sigue las prácticas recomendadas para las apps de audio, por ejemplo, cómo administrar el foco de audio.

Cómo evitar la reproducción involuntaria de contenido multimedia a través de las bocinas integradas

Las apps de música pueden seguir estas instrucciones para evitar que la app reproduzca contenido multimedia de manera accidental en las bocinas integradas del reloj. La guía varía según el reproductor que use tu app.

ExoPlayer

Si tu app usa ExoPlayer, haz lo siguiente:

  1. Llama al método setSuppressPlaybackOnUnsuitableOutput(true) mientras compilas la instancia de ExoPlayer:

val exoPlayer = ExoPlayer.Builder(context)
    .setAudioAttributes(AudioAttributes.DEFAULT, true)
    .setSuppressPlaybackOnUnsuitableOutput(true)
    .build()

  1. Como reacción al evento de supresión de reproducción, registra el objeto de escucha WearUnsuitableOutputPlaybackSuppressionResolverListener como objeto de escucha de la instancia de ExoPlayer:

exoPlayer.addListener(WearUnsuitableOutputPlaybackSuppressionResolverListener(context))

Kit de herramientas de contenido multimedia de Horologist

El Horologist MediaToolkit ya contiene lógica para evitar la reproducción de contenido multimedia involuntaria en las bocinas integradas del reloj.

Otros reproductores multimedia