管理Android音頻焦點(diǎn)

2018-08-02 17:32 更新

編寫:kesenhoo - 原文:http://developer.android.com/training/managing-audio/audio-focus.html

由于可能會有多個應(yīng)用可以播放音頻,所以我們應(yīng)當(dāng)考慮一下他們應(yīng)該如何交互。為了防止多個音樂播放應(yīng)用同時播放音頻,Android使用音頻焦點(diǎn)(Audio Focus)來控制音頻的播放——即只有獲取到音頻焦點(diǎn)的應(yīng)用才能夠播放音頻。

在我們的應(yīng)用開始播放音頻之前,它需要先請求音頻焦點(diǎn),然后再獲取到音頻焦點(diǎn)。另外,它還需要知道如何監(jiān)聽失去音頻焦點(diǎn)的事件并對此做出合適的響應(yīng)。

請求獲取音頻焦點(diǎn)(Request the Audio Focus)

在我們的應(yīng)用開始播放音頻之前,它需要獲取將要使用的音頻流的音頻焦點(diǎn)。通過使用requestAudioFocus() 方法可以獲取我們希望得到的音頻流焦點(diǎn)。如果請求成功,該方法會返回AUDIOFOCUS_REQUEST_GRANTED。

另外我們必須指定正在使用的音頻流,而且需要確定所請求的音頻焦點(diǎn)是短暫的(Transient)還是永久的(Permanent)。

  • 短暫的焦點(diǎn)鎖定:當(dāng)計(jì)劃播放一個短暫的音頻時使用(比如播放導(dǎo)航指示)。
  • 永久的焦點(diǎn)鎖定:當(dāng)計(jì)劃播放一個較長但時長可預(yù)期的音頻時使用(比如播放音樂)。

下面的代碼片段是一個在播放音樂時請求永久音頻焦點(diǎn)的例子,我們必須在開始播放之前立即請求音頻焦點(diǎn),比如在用戶點(diǎn)擊播放或者游戲中下一關(guān)的背景音樂開始前。

AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...

// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                                 // Use the music stream.
                                 AudioManager.STREAM_MUSIC,
                                 // Request permanent focus.
                                 AudioManager.AUDIOFOCUS_GAIN);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    am.registerMediaButtonEventReceiver(RemoteControlReceiver);
    // Start playback.
}

一旦結(jié)束了播放,需要確保調(diào)用了abandonAudioFocus()方法。這樣相當(dāng)于告知系統(tǒng)我們不再需要獲取焦點(diǎn)并且注銷所關(guān)聯(lián)的AudioManager.OnAudioFocusChangeListener監(jiān)聽器。對于另一種釋放短暫音頻焦點(diǎn)的情況,這會允許任何被我們打斷的應(yīng)用可以繼續(xù)播放。

// Abandon audio focus when playback complete    
am.abandonAudioFocus(afChangeListener);

當(dāng)請求短暫音頻焦點(diǎn)的時候,我們可以選擇是否開啟“Ducking”。通常情況下,一個應(yīng)用在失去音頻焦點(diǎn)時會立即關(guān)閉它的播放聲音。如果我們選擇在請求短暫音頻焦點(diǎn)的時候開啟了Ducking,那意味著其它應(yīng)用可以繼續(xù)播放,僅僅是在這一刻降低自己的音量,直到重新獲取到音頻焦點(diǎn)后恢復(fù)正常音量(譯注:也就是說,不用理會這個短暫焦點(diǎn)的請求,這并不會打斷目前正在播放的音頻。比如在播放音樂的時候突然出現(xiàn)一個短暫的短信提示聲音,此時僅僅是把歌曲的音量暫時調(diào)低,使得用戶能夠聽到短信提示聲,在此之后便立馬恢復(fù)正常播放)。

// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
                             // Use the music stream.
                             AudioManager.STREAM_MUSIC,
                             // Request permanent focus.
                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);

if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // Start playback.
}

Ducking對于那些間歇性使用音頻焦點(diǎn)的應(yīng)用來說特別合適,比如語音導(dǎo)航。

如果有另一個應(yīng)用像上述那樣請求音頻焦點(diǎn),它所請求的永久音頻焦點(diǎn)或者短暫音頻焦點(diǎn)(支持Ducking或不支持Ducking),都會被你在請求獲取音頻焦點(diǎn)時所注冊的監(jiān)聽器接收到。

處理失去音頻焦點(diǎn)(Handle the Loss of Audio Focus)

如果應(yīng)用A請求獲取了音頻焦點(diǎn),那么在應(yīng)用B請求獲取音頻焦點(diǎn)的時候,A獲取到的焦點(diǎn)就會失去。如何響應(yīng)失去焦點(diǎn)事件,取決于失去焦點(diǎn)的方式。

在音頻焦點(diǎn)的監(jiān)聽器里面,當(dāng)接受到描述焦點(diǎn)改變的事件時會觸發(fā)onAudioFocusChange()回調(diào)方法。如之前提到的,獲取焦點(diǎn)有三種類型,我們同樣會有三種失去焦點(diǎn)的類型:永久失去,短暫失去,允許Ducking的短暫失去。

  • 失去短暫焦點(diǎn):通常在失去短暫焦點(diǎn)的情況下,我們會暫停當(dāng)前音頻的播放或者降低音量,同時需要準(zhǔn)備在重新獲取到焦點(diǎn)之后恢復(fù)播放。

  • 失去永久焦點(diǎn):假設(shè)另外一個應(yīng)用開始播放音樂,那么我們的應(yīng)用就應(yīng)該有效地將自己停止。在實(shí)際場景當(dāng)中,這意味著停止播放,移除媒體按鈕監(jiān)聽,允許新的音頻播放器可以唯一地監(jiān)聽那些按鈕事件,并且放棄自己的音頻焦點(diǎn)。此時,如果想要恢復(fù)自己的音頻播放,我們需要等待某種特定用戶行為發(fā)生(例如按下了我們應(yīng)用當(dāng)中的播放按鈕)。

在下面的代碼片段當(dāng)中,如果焦點(diǎn)的失去是短暫型的,我們將音頻播放對象暫停,并在重新獲取到焦點(diǎn)后進(jìn)行恢復(fù)。如果是永久型的焦點(diǎn)失去事件,那么我們的媒體按鈕監(jiān)聽器會被注銷,并且不再監(jiān)聽音頻焦點(diǎn)的改變。

OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT
            // Pause playback
        } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
            // Resume playback 
        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
            am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
            am.abandonAudioFocus(afChangeListener);
            // Stop playback
        }
    }
};

在上面失去短暫焦點(diǎn)的例子中,如果允許Ducking,那么除了暫停當(dāng)前的播放之外,我們還可以選擇使用“Ducking”。

Duck!

在使用Ducking時,正常播放的歌曲會降低音量來凸顯這個短暫的音頻聲音,這樣既讓這個短暫的聲音比較突出,又不至于打斷正常的聲音。

下面的代碼片段讓我們的播放器在暫時失去音頻焦點(diǎn)時降低音量,并在重新獲得音頻焦點(diǎn)之后恢復(fù)原來音量。

OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
    public void onAudioFocusChange(int focusChange) {
        if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
            // Lower the volume
        } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
            // Raise it back to normal
        }
    }
};

音頻焦點(diǎn)的失去是我們需要響應(yīng)的最重要的事件廣播之一,但除此之外還有很多其他重要的廣播需要我們正確地做出響應(yīng)。系統(tǒng)會廣播一系列的Intent來向你告知用戶在使用音頻過程當(dāng)中的各種變化。下節(jié)課會演示如何監(jiān)聽這些廣播并提升用戶的整體體驗(yàn)。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號