在穿戴式设备上播放音频

本指南将介绍 Wear OS 上的应用如何使用熟悉的 Android API 播放音频。

检测音频设备

Wear OS 应用首先必须检测穿戴式设备是否具有合适的音频输出方式。开发者可以指望穿戴式设备至少提供以下音频输出中的一种:

在以下示例中,应用结合使用 getDevices() 方法与 FEATURE_AUDIO_OUTPUT 的值,枚举所有音频输出方式。

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)

为了提供最佳用户体验,您的应用应确保仅在有蓝牙耳机或音箱连接到手表时播放媒体。

选择用于输出音频的首选设备

根据应用的使用情形以及音频对应用核心体验的重要性,选择您希望用户与应用音频输出之间的互动方式。

蓝牙耳机

与内置音箱(只要设备配备便始终可用)不同,蓝牙耳机可在应用运行时配对或取消配对。如果应用需要使用耳机才能继续操作,

注册一个回调,以检测用户何时使用 registerAudioDeviceCallback 连接和断开蓝牙耳机:

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)
  

如果您的应用在您想提供音频输出时检测到未连接蓝牙耳机,请不要显示错误消息,而是要提议将用户直接转到蓝牙设置,以便他们更轻松地建立连接。使用 ACTION_BLUETOOTH_SETTINGS 发送 intent 可以做到这一点:

  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)
  

音箱

大多数 Wear OS 设备都配有音箱。如果您的应用提供包含声音的非媒体使用情形,请考虑使用音箱来增加与用户互动的途径。例如,配有音箱的 Wear OS 设备可能会触发时钟闹钟或计时器闹钟,并辅以音频通知;健身应用可能会使用音箱提供锻炼指示。

注意:音箱并非专为此用途而设计,所以无法提供最佳媒体内容收听体验。

如需了解详情,请参阅 WearSpeakerSample

播放音频

检测到并选择合适的音频输出方式后,在 Wear OS 上播放音频的过程和在移动设备或其他设备上播放音频相同。如需了解详情,请参阅 MediaPlayer 概览。如果想更轻松地使用更为高级的功能(例如在线播放和下载媒体内容),不妨使用 ExoPlayer。请务必遵循针对音频应用的最佳实践,例如管理音频焦点

防止通过音箱意外播放媒体

媒体应用可遵循下列指南,以确保应用不会在无意中通过内置手表音箱播放媒体内容。具体指南因应用使用的播放器而异。

ExoPlayer

如果您的应用使用 ExoPlayer:

  1. 在构建 ExoPlayer 实例时,调用 setSuppressPlaybackOnUnseeableOutput(true)

      ExoPlayer exoplayer = ExoPlayer.Builder(context)
              .setAudioAttributes(...)
              .setSuppressPlaybackWhenUnsuitableOutput(true)
              // ...
              .build()
          
  2. 通过将 WearUnsureableOutputPlaybackSuppressionResolverListener 注册为 ExoPlayer 实例的监听器,以响应播放禁止事件:

  3.   exoPlayer.addListener(WearUnsuitableOutputPlaybackSuppressionResolverListener(context))
        

Horologist Media 工具包

Horologist Media 工具包已含有相应逻辑,可防止通过内置手表音箱意外播放媒体。

其他媒体播放器