Android MediaPlayer的生命周期
下面圖表表現出來生命周期和MediaPlayer類的控制操作,橢圓體描述了MediaPlayer 類的狀態,弧線描述了重放控制的運作,有兩種箭頭,單箭頭的弧線代表同步方法的調用,爽箭頭代表異步方法的調用。
從這個圖我們可以看出MediaPlayer類有如下的狀態:
l 當一個 MediaPlayer類 剛用new或者在reset()調用后創建,這時處于空閑狀態,在release() 調用后則處于結束狀態,在這兩個狀態之間就是MediaPlaye的生命周期。
Ø 新創建的MediaPlayer類和調用reset()后的MediaPlayer類,有著很微妙但很重要的區別:
在空閑狀態調用諸如getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioStreamType(int),setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int), prepare() or prepareAsync()會報錯。如果這些方法在MediaPlayer類正確創建以后,內部播放組件和類的狀態變化不能夠調用回調方法OnErrorListener.onError() 。但是,這些方法在reset()后被正確調用的話,內部播放組件就會調用用戶提供的回調方法OnErrorListener.onError(),并且類的狀態也會轉為Error 狀態。
Ø 一旦MediaPlayer類很長時間不被用到,則立即調用release(),使與MediaPlayer類關聯的內部播放組件所用到的資源能夠立即被釋放。 一旦MediaPlayer類處于end狀態,那樣的話MediaPlayer類就無法在被用到了,也不能夠回到其他任何狀態。
Ø 此外,MediaPlayer類用new創建處于空閑狀態,當用create創建時MediaPlayer類不在空閑狀態,事實上當成功調用create方法調用時,這個對象已經處于Prepared 狀態了。
l 總之,一些播放控制操作會失敗是有很多原因的,比如不支持的audio/video格式,不完整的audio/video,分 辨率太高,流超時等等。因此在這些情況下,錯誤報告和恢復很是重要。通常在無效的狀態下調用一個播放控制會導致程序錯誤。在所有錯誤的情況下,內部播放組 件調用用戶提供的OnErrorListener.onError() 方法,前提是OnErrorListener()被事先用setOnErrorListener(android.media.MediaPlayer.OnErrorListener)注冊過。
Ø 一旦錯誤發生記錄錯誤是很重要的,MediaPlayer類進入Error 狀態,即使error監聽病沒有在應用中注冊。
Ø 為了重新使用在錯誤狀態的MediaPlayer類和從錯誤中恢復,可以調用reset()恢復這個類到空閑狀態。
Ø 在應用中注冊OnErrorListener去發現內部播放組件的錯誤通知是很好的程序設計慣例。
Ø 拋出IllegalStateException去防止程序錯誤:如調用prepare()和prepareAsync(),或者在無效超載狀態調用setDataSource().
l MediaPlayer類在播放之前要首先進入Prepared狀態,有兩種方法可以到達Prepared狀態(異步方法和同步方法)。
一旦調用prepare()方法,類就進入Prepared狀態,調用prepareAsync()方法,直到處于休息狀態內部播放組件完成準備工作之前類一直處于Preparing狀態。當準備工作完成或者調用prepare()時,內部播放組件會調用用戶提供的回調方法:OnPreparedListener接口的onPrepared() 方法,前提是OnPreparedListener 被事先用setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener) 注冊)這時類進入Prepared狀態。
l 當調用start()方法成功后,MediaPlayer類進入Started狀態。
內部播放組件會調用OnBufferingUpdateListener.onBufferingUpdate() 回調方法,前提是
OnBufferingUpdateListener被事先用setOnBufferingUpdateListener(OnBufferingUpdateListener)注冊。這個回調方法允許應用跟蹤緩存狀態。
l 當調用seekTo(int),播放的位置就可以被調整。
Ø 調用seekTo(int)時,實際的尋求工作需要一段時間去完成,特別是視頻或者是音頻正在播放的時候。當實際的尋求工作完成時會調用OnSeekComplete.onSeekComplete(), 如果OnSeekCompleteListener提前用setOnSeekCompleteListener(OnSeekCompleteListener).注冊過。
Ø 需要注意的是,seekTo(int)可以在其他的狀態調用,例如 Prepared, Paused andPlaybackCompleted s這些狀態。
Ø 此外,用getCurrentPosition(),方法可以找到當前的播放位置。這個對應用很有幫助,例如音樂播放器需要跟蹤播放進度的時候。
l 當播放到達數據流的末尾,播放就完成了。
Ø 如果循環模式設置了setLooping(ture),那么MediaPlayer類保持Started狀態。
Ø 如果循環模式設置為false,播放組件就會調用OnCompletion.onCompletion(),前提是OnCompletionListener提前用 setOnCompletionListener(OnCompletionListener)注冊過,這時類進入PlaybackCompleted 狀態。
Ø 當進入PlaybackCompleted 狀態,調用start()方法,就會在音頻和視頻源的開頭重新開始播放。