標籤:list android 音樂 mediaplayer audio
實現音樂的播放。
為了快速實現音樂播放,我們使用MediaPlayer而不用SoundPool,據說SoundPool比MediaPlayer的自由度更大。不過,根據我的瞭解,soundpool並不支援音訊解碼,得自己去解碼,而MeidaPlayer已經內建了一些解碼方案,我看到的是,音頻除了ape無損格式,都能播放。
你需要閱讀:
MediaPlayer API:
http://developer.android.com/reference/android/media/MediaPlayer.html
MediaPlayer API Guide:
http://developer.android.com/guide/topics/media/mediaplayer.html
在此,不再介紹MediaPlayer的使用。
在途中,我們可以看到MediaPlayer的生命週期,其中,藍色橢圓內的是Mediaplayer的不同狀態。
如果在不允許的狀態執行了一些不應該的操作,會出現異常。在進行不同操作時候,合法的前提狀態和不合法的狀態,參考這個連結:
http://developer.android.com/reference/android/media/MediaPlayer.html#Valid_and_Invalid_States
我們聲明一個類來選項組。
public static class State { public static final int IDLE = 0, INITIALIZED = 1, PREPARED = 2, PREPARING = 3, STARTED = 4, PAUSED = 5, STOPPED = 6, COMPLETED = 7, END = -1, ERROR = -2; }
在我們的MainService中,可以這樣寫開始播放的代碼:
//這個方法用來初始化我們的MediaPlayerprivate void init () { if (mPlayer == null) { mPlayer = new MediaPlayer(); changeState(State.IDLE); } else { if (mCurrentState == State.IDLE || mCurrentState == State.INITIALIZED || mCurrentState == State.PREPARED || mCurrentState == State.STARTED || mCurrentState == State.PAUSED || mCurrentState == State.STOPPED || mCurrentState == State.COMPLETED || mCurrentState == State.ERROR) { mPlayer.reset(); changeState(State.IDLE);//注意狀態更改的代碼 } } mPlayer.setOnErrorListener(this);//MainService 要實現這三個介面 mPlayer.setOnPreparedListener(this); mPlayer.setOnCompletionListener(this); }
對外公開的一個開始播放的方法:
public void start (Audio audio) { init(); try { if (mCurrentState == State.IDLE) { mPlayer.setDataSource(this, audio.getUri()); //Valid Sates IDLE } changeState(State.INITIALIZED); if (mCurrentState != State.ERROR) { mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); //Invalid States ERROR } if (mCurrentState == State.INITIALIZED || mCurrentState == State.STOPPED) { mPlayer.prepareAsync();//Valid Sates{Initialized, Stopped} changeState(State.PREPARING); } } catch (IOException e) { e.printStackTrace(); } }
注意,在此方法中,我們不要直接去播放,而是使用mPlayer.prepareAsync()。讓MediaPlayer去做申請播放資源等工作,這個過程有可能有幾十毫秒的耗時,等到回調onPrepared回調成功後,在onPrepared中去做真正的開始播放,我們在onPrepared中調用一下doStart方法:
private void doStart () { mPlayer.start(); changeState(State.STARTED); }
這樣,就可以開始播放工作了。在以上代碼中,都出現了一個changeState方法。如下:
private void changeState (int state) { mCurrentState = state; if (mPlaybackListener != null) { mPlaybackListener.onStateChanged(mCurrentAudio, mCurrentState); } }/*這裡採用了setOnPlaybackListener的方法,如果有需要,也可以用一個List去儲存一個Listener集合,只要在適當的時候進行釋放,例如在Service的onDestroy方法中,去把這個List清空掉*/public void setOnPlaybackListener (OnPlaybackListener listener) { mPlaybackListener = listener; } public static interface OnPlaybackListener { public void onStateChanged (Audio source, int state); }
如何寫一個正經的Android音樂播放器 三