Como gerenciar mudanças na saída de áudio

Os usuários esperam poder controlar o volume de um app de áudio. O comportamento padrão inclui a capacidade de usar os controles de volume (botões no dispositivo ou controles deslizantes na IU) e evitar a reprodução repentina em volume alto quando um periférico, como fones de ouvido, for desconectado enquanto estiver em uso.

Como usar os controles de volume

Quando um usuário pressiona uma tecla de volume em um jogo ou app de música, o volume muda, mesmo se o player tiver pausado entre as músicas ou se não há música no local atual do jogo.

O Android usa streams de áudio separados para reproduzir músicas, alarmes, notificações, campainha de chamada recebida, sons do sistema, volume de chamada e tons DTMF. Isso permite que os usuários controlem o volume de cada stream de forma independente.

Por padrão, pressionar o controle de volume modifica o volume do stream de áudio ativo. Se o app não estiver reproduzindo nada, pressionar as teclas de volume ajusta o volume da música (ou o volume da campainha em versões anteriores à do Android 9).

A menos que seu app seja um despertador, você reproduzirá o áudio com o uso de AudioAttributes.USAGE_MEDIA.

Para garantir que os controles de volume ajustem o stream correto, chame setVolumeControlStream() transmitindo o tipo de stream correspondente aos atributos que você pode recuperar AudioAttributes.getVolumeControlStream.

Kotlin

    setVolumeControlStream(AudioManager.STREAM_MUSIC)
    

Java

    setVolumeControlStream(AudioManager.STREAM_MUSIC);
    

Faça essa chamada no ciclo de vida do app, normalmente no método onResume() da atividade ou fragmento que controla a mídia. Isso conecta os controles de volume ao STREAM_MUSIC, sempre que a atividade de destino ou fragmento estiver visível.

Como controlar o volume de stream de maneira programática

Em casos raros, você pode definir o volume de um stream de áudio programaticamente. Por exemplo, quando o app substitui uma IU. Isso não é recomendado porque o AudioManager do Android mistura todos os streams de áudio do mesmo tipo. Esses métodos mudam o volume de cada app que usa o stream. Evite usá-los:

Como trabalhar com dispositivos de volume fixo

Alguns dispositivos, como os Chromebooks, têm controles de volume, mas não permitem que os apps usem os métodos AudioManager descritos acima para mudar o nível de um stream de áudio. Esses dispositivos são chamados de volume fixo. Você pode descobrir se seu app está sendo executado em um dispositivo de volume fixo chamando isVolumeFixed().

Um app de áudio precisa ser capaz de equilibrar o volume de saída com outros apps que podem estar sendo reproduzidos no mesmo stream. Em dispositivos de volume fixo, o app precisa conectar os próprios controles de volume ao método setVolume() apropriado na tabela abaixo:

Player Método
Faixa de áudio AudioTrack.setVolume()
MediaPlayer MediaPlayer.setVolume()
ExoPlayer Use SimpleExoPlayer.setVolume(), que define o volume da faixa de áudio subjacente.

Não seja barulhento

Os usuários têm uma série de alternativas quando se trata de aproveitar o áudio dos dispositivos Android. A maioria dos dispositivos tem um alto-falante integrado, entrada para fone de ouvido com fio, e muitos também apresentam conectividade Bluetooth e compatibilidade com áudio A2DP.

Quando um fone de ouvido ou um dispositivo Bluetooth é desconectado, o stream de áudio é redirecionado automaticamente para o alto-falante integrado. Se você ouve música em volume alto, essa pode ser uma surpresa barulhenta.

Os usuários geralmente esperam que os app que incluem um player de música com controles de reprodução na tela pausem a reprodução nesse caso. Outros apps, como jogos que não incluem controles, continuam sendo reproduzidos. O usuário pode ajustar o volume com os controles de hardware do dispositivo.

Quando a saída de áudio volta para o alto-falante integrado, o sistema transmite um intent de ACTION_AUDIO_BECOMING_NOISY. Crie um BroadcastReceiver que escute esse intent sempre que estiver reproduzindo áudio. Seu receptor terá esta aparência:

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

Registre o receptor quando começar a reprodução e cancele o registro quando parar. Se você criar o app conforme descrito neste guia, essas chamadas aparecerão nos callbacks da sessão de mídia onPlay() e 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);
      }
    }