控制Android的音量與音頻播放

2018-08-02 17:32 更新

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

良好的用戶體驗應(yīng)該是可預(yù)期且可控的。如果我們的應(yīng)用可以播放音頻,那么顯然我們需要做到能夠通過硬件按鈕,軟件按鈕,藍牙耳麥等來控制音量。 同樣地,我們需要能夠?qū)?yīng)用的音頻流進行播放(Play),停止(Stop),暫停(Pause),跳過(Skip),以及回放(Previous)等動作,并且并確保其正確性。

鑒別使用的是哪個音頻流(Identify Which Audio Stream to Use)

為了創(chuàng)建一個良好的音頻體驗,我們首先需要知道應(yīng)用會使用到哪些音頻流。Android為播放音樂,鬧鈴,通知鈴,來電聲音,系統(tǒng)聲音,打電話聲音與撥號聲音分別維護了一個獨立的音頻流。這樣做的主要目的是讓用戶能夠單獨地控制不同的種類的音頻。上述音頻種類中,大多數(shù)都是被系統(tǒng)限制。例如,除非你的應(yīng)用需要做替換鬧鐘的鈴聲的操作,不然的話你只能通過STREAM_MUSIC來播放你的音頻。

使用硬件音量鍵來控制應(yīng)用的音量(Use Hardware Volume Keys to Control Your App’s Audio Volume)

默認情況下,按下音量控制鍵會調(diào)節(jié)當前被激活的音頻流,如果我們的應(yīng)用當前沒有播放任何聲音,那么按下音量鍵會調(diào)節(jié)響鈴的音量。對于游戲或者音樂播放器而言,即使是在歌曲之間無聲音的狀態(tài),或是當前游戲處于無聲的狀態(tài),用戶按下音量鍵的操作通常都意味著他們希望調(diào)節(jié)游戲或者音樂的音量。你可能希望通過監(jiān)聽音量鍵被按下的事件,來調(diào)節(jié)音頻流的音量。其實我們不必這樣做。Android提供了setVolumeControlStream()方法來直接控制指定的音頻流。在鑒別出應(yīng)用會使用哪個音頻流之后,我們需要在應(yīng)用生命周期的早期階段調(diào)用該方法,因為該方法只需要在Activity整個生命周期中調(diào)用一次,通常,我們可以在負責(zé)控制多媒體的Activity或者FragmentonCreate()方法中調(diào)用它。這樣能確保不管應(yīng)用當前是否可見,音頻控制的功能都能符合用戶的預(yù)期。

setVolumeControlStream(AudioManager.STREAM_MUSIC);

自此之后,不管目標Activity或Fragment是否可見,按下設(shè)備的音量鍵都能夠影響我們指定的音頻流(在這個例子中,音頻流是"music")。

使用硬件的播放控制按鍵來控制應(yīng)用的音頻播放(Use Hardware Playback Control Keys to Control Your App’s Audio Playback)

許多線控或者無線耳機都會有許多媒體播放控制按鈕,例如:播放,停止,暫停,跳過,以及回放等。無論用戶按下設(shè)備上任意一個控制按鈕,系統(tǒng)都會廣播一個帶有ACTION_MEDIA_BUTTON的Intent。為了正確地響應(yīng)這些操作,需要在Manifest文件中注冊一個針對于該Action的BroadcastReceiver,如下所示:

<receiver android:name=".RemoteControlReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

在Receiver的實現(xiàn)中,需要判斷這個廣播來自于哪一個按鈕,Intent通過EXTRA_KEY_EVENT這一Key包含了該信息,另外,KeyEvent類包含了一系列諸如KEYCODE_MEDIA_*的靜態(tài)變量來表示不同的媒體按鈕,例如KEYCODE_MEDIA_PLAY_PAUSE 與 KEYCODE_MEDIA_NEXT。

public class RemoteControlReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
            KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
            if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
                // Handle key press.
            }
        }
    }
}

因為可能會有多個程序在監(jiān)聽與媒體按鈕相關(guān)的事件,所以我們必須在代碼中控制應(yīng)用接收相關(guān)事件的時機。下面的例子顯示了如何使用AudioManager來為我們的應(yīng)用注冊監(jiān)聽與取消監(jiān)聽媒體按鈕事件,當Receiver被注冊上時,它將是唯一一個能夠響應(yīng)媒體按鈕廣播的Receiver。

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

// Start listening for button presses
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
...

// Stop listening for button presses
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);

通常,應(yīng)用需要在他們失去焦點或者不可見的時候(比如在onStop()方法里面)取消注冊監(jiān)聽。但是對于媒體播放應(yīng)用來說并沒有那么簡單,實際上,在應(yīng)用不可見(不能通過可見的UI控件進行控制)的時候,仍然能夠響應(yīng)媒體播放按鈕事件是極其重要的。為了實現(xiàn)這一點,有一個更好的方法,我們可以在程序獲取與失去音頻焦點的時候注冊與取消對音頻按鈕事件的監(jiān)聽。這個內(nèi)容會在后面的課程中詳細講解。


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號