使用者預期能夠控制音訊應用程式的音量。標準行為包括使用音量控制選項 (裝置上的按鈕或旋鈕,或 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
會將所有相同類型的音訊串流混合在一起。這些方法會變更使用串流的每個應用程式音量。請避免使用以下字詞:
adjustStreamVolume()
adjustSuggestedStreamVolume()
adjustVolume()
setStreamVolume() setStreamVolume()
setStreamSolo()
setStreamMute()
使用固定音量裝置
部分裝置 (例如 Chromebook 和 Android Automotive OS 汽車) 具有音量控制選項,但不允許應用程式使用前述的 AudioManager
方法來變更音訊串流的音量。這類裝置稱為固定音量裝置。您可以呼叫 isVolumeFixed()
,瞭解應用程式是否在固定音量的裝置上執行。
音訊應用程式應提供平衡功能,讓使用者調整輸出音量,以便與可能在同一串流中播放的其他應用程式保持平衡。在固定音量裝置上,應用程式應將其自身的音量控制項連結至適當的 setVolume()
方法:
球員 | 方法 |
---|---|
AudioTrack | AudioTrack.setVolume() |
MediaPlayer | MediaPlayer.setVolume() |
ExoPlayer | 使用 SimpleExoPlayer.setVolume() 設定基礎 AudioTrack 的音量。 |
網路 | 設定 HTMLMediaElement 的 volume 屬性 |
請勿製造噪音
使用者可以透過多種方式,透過 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); } }