处理音频输出变化

用户希望能够控制音频应用的音量。标准行为 包括使用音量控件(设备上的按钮或旋钮) 设备或滑块),并避免在音乐播放时 使用时,耳机等外围设备会断开连接。

使用音量控件

用户按游戏或音乐应用中的音量键时,音量应 即使播放器在歌曲间暂停或播放时没有音乐, 当前游戏位置。

Android 会使用单独的音频流来播放音乐、闹钟和 通知、来电铃声、系统提示音、通话音量和 DTMF 音调。这样,用户就可以独立控制每个音频流的音量。

默认情况下,按音量控件可调节当前音频的音量 。如果您的应用当前未播放任何内容,请按音量键 调节音乐音量(在 Android 9 之前,调节铃声音量)。

除非您的应用是闹钟,否则您应播放与使用情况相关的音频 AudioAttributes.USAGE_MEDIA

为了确保音量控件能够调节 正确的流,则应调用 setVolumeControlStream() 传入与属性匹配的流类型,您可以从中检索 AudioAttributes.getVolumeControlStream

Kotlin

setVolumeControlStream(AudioManager.STREAM_MUSIC)

Java

setVolumeControlStream(AudioManager.STREAM_MUSIC);

在应用的生命周期(通常从 onResume() 中)发出此调用 方法。这会将 每当目标 activity 或 fragment 将音量控制为 STREAM_MUSIC 可见。

以编程方式控制音频流音量

在极少数情况下,您可以通过编程方式设置音频流的音量。对于 例如,当应用替换现有界面时。我们不建议这样做,因为 Android AudioManager 会将所有相同类型的音频流混合在一起。 以下方法会改变使用该音频流的每个应用的音量。避免使用 :

使用固定音量设备

某些设备(例如 Chromebook)具有音量控件,但不允许应用使用 AudioManager 方法更改音频流的音量。这些称为 固定音量设备。您可以查看 应用正在通过调用 isVolumeFixed() 在固定音量设备上运行。

音频应用应该能够 与可能在同一音频流中播放的其他应用的输出音量相同。 在固定音量设备上,应用应将自己的音量控件连接到 下表中相应的 setVolume() 方法:

球手 方法
AudioTrack AudioTrack.setVolume()
MediaPlayer MediaPlayer.setVolume()
ExoPlayer 使用 SimpleExoPlayer.setVolume() 设置底层 AudioTrack 的音量。

不要发出噪音

用户可通过多种选择来欣赏 Android 设备的用户。大部分设备都有内置扬声器和耳机插孔 有线耳机,很多还具有蓝牙连接功能,并且支持 A2DP 音频。

当耳机被拔出或蓝牙设备断开连接时,音频流 自动路由到内置扬声器。如果您以较高的音量听音乐 这可能有点令人惊讶

用户通常希望应用包含支持屏幕播放的音乐播放器 用于暂停播放的控件。其他应用,例如 包含控件,应继续播放。用户可以使用 设备的硬件控件

当音频输出切换回内置扬声器时,系统会广播 ACTION_AUDIO_BECOMING_NOISY intent。您应该创建一个 BroadcastReceiver 。您的接收器应如下所示:

Kotlin

private class BecomingNoisyReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == AudioManager.ACTION_AUDIO_BECOMING_NOISY) {
            // Pause the playback
        }
    }
}

Java

private class BecomingNoisyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
      if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
          // Pause the playback
      }
    }
}

在开始播放时注册接收器,并在停止时取消注册接收器。 如果您按照本指南中的说明设计应用,这些调用应显示在 在 onPlay()onStop() 媒体会话回调中。

Kotlin

private val intentFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
private val myNoisyAudioStreamReceiver = BecomingNoisyReceiver()

private val callback = object : MediaSessionCompat.Callback() {

    override fun onPlay() {
        registerReceiver(myNoisyAudioStreamReceiver, intentFilter)
    }

    override fun onStop() {
        unregisterReceiver(myNoisyAudioStreamReceiver)
    }
}

Java

private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private BecomingNoisyReceiver myNoisyAudioStreamReceiver = new BecomingNoisyReceiver();

MediaSessionCompat.Callback callback = new
MediaSessionCompat.Callback() {
  @Override
  public void onPlay() {
    registerReceiver(myNoisyAudioStreamReceiver, intentFilter);
  }

  @Override
  public void onStop() {
    unregisterReceiver(myNoisyAudioStreamReceiver);
  }
}