android音視訊指南-處理音訊輸出的變化

DamonRen發表於2019-03-01

翻譯自Handling changes in audio output

使用者希望能夠控制音量的音訊應用。標準行為包括使用音量控制的能力(裝置上的按鈕或旋鈕或滑塊在UI中),並避免突然大聲播放如果外圍像耳機斷開連線時使用

使用音量控制

當使用者在遊戲或音樂應用程式中按下音量鍵時,音量應該會發生變化,即使播放器在歌曲之間暫停,或者當前遊戲位置沒有音樂。

Android使用單獨的音訊流來播放音樂、警報、通知、來電鈴聲、系統聲音、來電音量和DTMF音調。這允許使用者獨立地控制每個流的音量。

預設情況下,按下音量控制將修改活動音訊流的音量。如果你的應用程式當前沒有播放任何內容,點選音量鍵可以調整鈴聲音量。

除非你的應用程式是鬧鐘,否則你應該使用STREAM_MUSIC流播放音訊。

為了確保音量控制調整正確的流,您應該呼叫傳入AudioManager.STREAM_MUSIC的setVolumeControlStream()

setVolumeControlStream(AudioManager.STREAM_MUSIC);
複製程式碼

在應用程式的生命週期中進行此呼叫,通常來自控制媒體的活動或fragment的onResume()方法。這將在目標活動或fragment可見時將volume控制連線到STREAM_MUSIC

以程式設計方式控制stream volume

在很少的情況下,您可以通過程式設計方式設定音訊流的音量。例如,當應用程式替換現有UI時。這是不推薦的,因為Android AudioManager將所有相同型別的音訊流混合在一起。這些方法改變了使用流的每個應用程式的音量。避免使用以下方法:

  • adjustStreamVolume()
  • adjustSuggestedStreamVolume()
  • adjustVolume()
  • setStreamVolume() setStreamVolume()
  • setStreamSolo()
  • setStreamMute()

使用固定容量裝置

有些裝置(比如Chromebooks)有音量控制,但不允許應用程式使用上面描述的AudioManager方法來改變音訊流的級別。這些被稱為固定容量裝置。通過呼叫isVolumeFixed(),您可以發現您的應用程式是否在固定容量裝置上執行。

一個音訊應用程式應該能夠平衡它的輸出音量和其他可能在同一流上播放的應用程式。在固定容量裝置上,應用程式應該將自己的音量控制連線到下表中相應的setVolume()方法:

Player Method
AudioTrack AudioTrack.setVolume()
MediaPlayer MediaPlayer.setVolume()
ExoPlayer 使用SimpleExoPlayer.setVolume(),它可以設定底層AudioTrack的volume。

不要太吵

在享受安卓裝置的音訊時,使用者有很多選擇。大多數裝置都有內建揚聲器、有線耳機插孔,許多裝置還具有藍芽連線功能,並支援A2DP音訊。

當耳機拔出或藍芽裝置斷開時,音訊流自動重新路由到內建揚聲器。如果你在高音量下聽音樂,這可能是一個嘈雜的驚喜。

幸運的是,當發生這種情況時,系統會廣播一個ACTION_AUDIO_BECOMING_NOISY意圖。當你播放音訊時,你應該建立一個廣播接收器來監聽這個意圖。對於音樂播放器,使用者通常希望回放暫停。對於遊戲應用程式,你可以選擇大幅降低音量。你的接收器應該是這樣的:

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()媒體會話回撥中。

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);
  }
}
複製程式碼

相關文章