Android音視頻開發-MediaPlayer的各種狀態詳解

最近纔開始看的Android音視頻開發,覺得裏面對MediaPlayer的各種狀態講解的比較詳細,做了一下筆記:
Android的MediaPlayer專門用於控制視頻/音頻的文件以及流的播放,有狀態機進行管理,相關的狀態週期可由10個狀態組成,如下圖:
在這裏插入圖片描述
圖中的橢圓代表 MediaPlayer 駐留的狀態,弧代表播放控制且聚動 MediaPlayer 狀態進行過渡.有兩種類型的弧,單箭頭弧表示的是同步函數調用,雙箭頭弧表示的是異步函數調用。
從圖中,我們能看到MediaPlayer 有下面的一些狀態。
ldle狀態及End狀態
在 MediaPlayer 創建實例或者調用 reset 函數後,播放器就被創建了,這時處於ldle (就 緒)狀態,調用 release函數後,就會變成 End(結束)狀態,在這兩種狀態之間的就是 MediaPlayer的生命週期。
Error 狀態
在構造一個新MediaPlayer 或者調用reset 函數後,上層應用程序調用的getCurrentPosition、 getVideoHeight 、 getDuration 、 getVideoWidth 、 setAudioStreamType(int)、 setLooping(boolean)、 setVolume(float,float)、 pause、 start、 stop、 seekTo(int)、 prepare、 prepareAsync 這些函數如果會出錯。如果調用 reset 函數後再調用它們,用戶提供的回調函數OnErrorListener.onError 將觸發 MediaPlayer 狀態到 Error(錯誤)狀態,所以一旦不再使用 MediaPlayer,就需要調用 release 函數,以便 MediaPlayer 資源得到合理釋放。
當 MediaPlayer 處於End(結束)狀態時,它將不能再被使用,這時不能再回到 MediaPlayer的其他狀態,因爲本次生命週期已經終止。
由於支持的音視頻格式分辨率過高,輸入數據流超時,或者其他各種各樣的原因將導致播放失敗。在這種錯誤的條件下,如果用戶事先通過setOnErrorListener 註冊過OnErrorListener, 當 player 內部調用OnErrorListener.onError 回調函數時,將會返回錯誤信息。一旦有錯誤, MediaPlayer 會進入 Error(錯誤)狀態,爲了重新使用MediaPlayer,調用 reset 函數,這時將重新恢復到Idle(就緒)狀態,所以需要給 MediaPlayer 設置錯誤監聽,出錯後就可以從播放器內部返回的信息中找到錯誤原因。
Initialized 狀態
當調用 setDataSource(FileDescriptor)s setDataSource(String)、 setDataSource(Context, Uri)、 setDataSource(FileDescriptor, long, long)其中一個函數時,將傳遞 MediaPlayer 的 Idle 狀態變成 Initialized(初始化)狀態,如果 setDataSource 在非 Idle狀態時調用,會拋出 IllegalStateException 異常。當重載setDataSource時,需要拋出IlegalArgumentException 和 IOException這兩個異常。 5. Prepared 狀態
MediaPlayer 有兩種途徑到達 Prepared 狀態,一種是同步方式,另一種是異步方式。同步方式主要使用本地音視頻文件,異步方式主要使用網絡數據,需要緩衝數據。調用 prepare (同步函數)將傳遞MediaPlayer 的 Initialized狀態變成Prepared狀態,或者調用 prepareAsync (異步函數)將傳遞MediaPlayer 的 Initialized狀態變成Preparing狀態,最後到Prepared狀態。 如果應用層事先註冊過setOnPreparedListener ,播放器內部將回調用戶設置的 OnPreparedListener 中的 onPrepared 回調函數。注意,Preparing是一個瞬間狀態(可理解爲時間比較短)。
Started 狀態
在 MediaPlayer 進入 Prepared 狀態後,上層應用即可設置一些屬性,如音視頻的音量、 sereenOnWhilePlaying、 looping 等。在播放控制開始之前,必須調用 start 函數併成功返回, MediaPlayer的狀態開始由 Prepared狀態變成Started狀態。當處於 Started狀態時,如果用戶事先註冊過setOnBufferingUpdateListener,播放器內部會開始回調OnBuferingUpdateListener.on BuferingUpdate,這個回調函數主要使應用程序保持跟蹤音視頻流的 bufering(緩衝) status如果MediaPlayer 已經處於 Started狀態,再調用start函數是沒有任何作用的。
Paused狀態
MediaPlayer在播放控制時可以是Paused (暫停)和Stopped (停止)狀態的,且當前的播 放時進度可以被調整,當調用 MediaPlayer.pause函數時,MediaPlayer 開始由 Started狀態變成 Paused狀態,這個從 Started 狀態到Paused狀態的過程是瞬間的,反之在播放器內部是異步過程的。在狀態更新並調用isPlaying函數前,將有一些耗時。已經緩衝過的數據流,也要耗費數秒。
當start函數從 Paused 狀態恢復回來時,playback恢復之前暫停時的位置,接着開始播放,這時MediaPlayer的 Paused狀態又變成Started狀態。如果MediaPlayer已經處於 Paused狀態,這時再調用 pause函數是沒有任何作用的,將保持Paused狀態。
Stopped 狀態
當調用stop 函數時,MediaPlayer 無論正處於Started 、 Paused 、Prepared 或 PlaybackCompleted 中的哪種狀態,都將進入 Stopped狀態。一旦處於Stopped狀態,playback將不能開始,直到重新調用 prepare 或 prepareAsync函數,且處於Prepared 狀態時纔可以開始。
如果 MediaPlayer 已經處於 Stopped狀態了,這時再調用 stop函數是沒有任何作用的,將 保持Stopped狀態。
在 Seek操作完成後,如果事先在MediaPlayer 註冊了setOnSeekCompleteListener,播放器內部將回調OnSeekComplete.onSeekComplete函數。當然seekTo函數也可以在其他狀態下被調用,如 Prepared、 Paused 及 PlaybackCompleted 狀態。
PlaybackCompleted 狀態
當前播放的位置可以通過 getCurrentPosition函數獲取,通過 getCurrentPosition函數,可以跟蹤播放器的播放進度。 當MediaPlayer 播放到數據流的末尾時,一次播放過程完成。在 MediaPlayer 中事先調用 setLooping(boolean)並設置爲true,表示循環播放,MediaPlayer 依然處於Started狀態。如果調用setLooping(boolean)並設置爲 false(表示不循環播放),並且事先在 MediaPlayer 上註冊過setOnCompletionListener,播放器內部將回調OnCompletion.onCompletion 函數,這就表明MediaPlayer 開始進入PlaybackCompleted(播放完成)狀態。當處於 PlaybackCompleted 狀態時,調用start函數,將重啓播放器從頭開始播放數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章