處理音訊輸出的變化

使用者會預期可以控制音訊應用程式的音量。標準行為包括使用音量控制 (按鈕、裝置的旋鈕,或是 UI 中的滑桿),避免在使用時未連接耳機 (如耳機) 時突然發出大聲。

使用音量控制

使用者在遊戲或音樂應用程式中按下音量鍵時,音量應該就會變更,即使玩家在不同歌曲之間暫停播放,或是目前遊戲位置沒有音樂,也會改變音量。

Android 會使用不同的音訊串流來播放音樂、鬧鐘、通知、來電響鈴、系統音效、通話音量和 DTMF 音調。如此一來,使用者就能單獨控制每個直播的音量。

根據預設,按下音量控制項會修改進行中音訊串流的音量。如果應用程式目前未播放任何內容,則按下音量鍵可調整音樂音量 (或在 Android 9 之前的鈴聲音量)。

除非應用程式為鬧鐘,否則應使用 AudioAttributes.USAGE_MEDIA 播放音訊。

為確保音量控制項調整正確的串流,您應呼叫 setVolumeControlStream() 中傳遞的串流類型傳遞,且該類型須符合您可以從 AudioAttributes.getVolumeControlStream 擷取的屬性。

Kotlin

setVolumeControlStream(AudioManager.STREAM_MUSIC)

Java

setVolumeControlStream(AudioManager.STREAM_MUSIC);

請在應用程式的生命週期中進行此呼叫,通常是透過控制媒體的活動或片段的 onResume() 方法。當目標活動或片段顯示時,這會將音量控制項連結至 STREAM_MUSIC

透過程式輔助方式控制串流音量

在極少數情況下,您可以透過程式輔助方式設定音訊串流的音量。例如應用程式取代了現有 UI 時。不建議這麼做,因為 Android AudioManager 會混合所有同類型的音訊串流。這些方法會變更所有使用該串流的應用程式音量。請避免使用這些憑證:

使用固定音量裝置

部分裝置 (例如 Chromebook) 提供音量控制功能,但不允許應用程式使用上述的 AudioManager 方法變更音訊串流的等級。這類裝置稱為固定音量裝置。您可以呼叫 isVolumeFixed(),探索應用程式是否在固定音量裝置上執行。

音訊應用程式應提供平衡輸出音量與可能在同一個串流中播放的其他應用程式平衡。在 fixed-Volume 裝置上,應用程式應將其自己的音量控制項連結至下表中的適當的 setVolume() 方法:

球員 方法
音軌 AudioTrack.setVolume()
媒體播放器 MediaPlayer.setVolume()
ExoPlayer 使用 SimpleExoPlayer.setVolume() 可設定基礎 AudioTrack 的音量。

不要吵雜

使用者在透過 Android 裝置享受音訊內容時,可採取多種替代方案。大多數裝置都具備內建喇叭、有線耳機的耳機插孔,許多裝置也提供藍牙連線和 A2DP 音訊支援。

如果耳機未接上電源或藍牙裝置連線中斷,音訊串流會自動重新轉送到內建喇叭。如果你用高音量聽音樂 這是大聲的驚喜

在這種情況下,使用者通常會預期應用程式內含音樂播放器,且該播放器會暫停播放。其他應用程式 (例如沒有控制項的遊戲) 應繼續播放內容。使用者可以透過裝置的硬體控制項調整音量。

當音訊輸出切換回內建喇叭時,系統會廣播 ACTION_AUDIO_BECOMING_NOISY 意圖。您應建立 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);
  }
}