亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Android播放聲音MediaPlayer類詳細介紹

系統 1852 0

MediaPlayer類可用于控制音頻/視頻文件或流的播放。關于如何使用這個類的方法還可以閱讀 VideoView 類的文檔。


1.狀態圖

對播放音頻/視頻文件和流的控制是通過一個狀態機來管理的。下圖顯示一個 MediaPlayer 對象被支持的播放控制操作驅動的生命周期和狀態。橢圓代表 MediaPlayer 對象可能駐留的狀態。弧線表示驅動 MediaPlayer 在各個狀態之間遷移的播放控制操作。 這里有兩種類型的弧線。由一個箭頭開始的弧代表同步的方法調用,而以雙箭頭開頭的代表的弧線代表異步方法調用

Android播放聲音MediaPlayer類詳細介紹



通過這張圖,我們可以知道一個 MediaPlayer 對象有以下的狀態:

1)當一個 MediaPlayer 對象被剛剛用 new 操作符創建或是調用了 reset() 方法后,它就處于 Idle 狀態。當調用了 release() 方法后,它就處于 End 狀態。這兩種狀態之間是 MediaPlayer 對象的生命周期。

1.1) 在一個新構建的 MediaPlayer 對象和一個調用了 reset() 方法的 MediaPlayer 對象之間有一個微小的但是十分重要的差別。在處于 Idle 狀態時,調用 getCurrentPosition() , getDuration() , getVideoHeight() , getVideoWidth() , setAudioStreamType(int) , setLooping(boolean) , setVolume(float, float) , pause() , start() , stop() , seekTo(int) , prepare() 或者 prepareAsync() 方法都是編程錯誤。當一個 MediaPlayer 對象剛被構建的時候,內部的播放引擎和對象的狀態都沒有改變,在這個時候調用以上的那些方法,框架將無法回調客戶端程序注冊的 OnErrorListener.onError() 方法;但若這個MediaPlayer對象調用了 reset () 方法之后,再調用以上的那些方法,內部的播放引擎就會回調客戶端程序注冊的 OnErrorListener.onError() 方法了,并將錯誤的狀態傳入。

1.2) 我們建議,一旦一個 MediaPlayer 對象不再被使用,應立即調用 release() 方法來釋放在內部的播放引擎中與這個 MediaPlayer 對象關聯的資源。資源可能包括如硬件加速組件的單態組件,若沒有調用 release() 方法可能會導致之后的 MediaPlayer 對象實例無法使用這種單態硬件資源,從而退回到軟件實現或運行失敗。一旦 MediaPlayer 對象進入了 End 狀態,它不能再被使用,也沒有辦法再遷移到其它狀態。

1.3) 此外,使用 new 操作符創建的 MediaPlayer 對象處于 Idle 狀態,而那些通過重載的 create() 便利方法創建的 MediaPlayer 對象卻不是處于 Idle 狀態。事實上,如果成功調用了重載的 create() 方法,那么這些對象已經是 Prepare 狀態了。


2) 在一般情況下,由于種種原因一些播放控制操作可能會失敗,如不支持的音頻/視頻格式,缺少隔行掃描的音頻/視頻,分辨率太高,流超時等原因,等等。因此,錯誤報告和恢復在這種情況下是非常重要的。有時,由于編程錯誤,在處于無效狀態的情況下調用了一個播放控制操作可能發生。在所有這些錯誤條件下,內部的播放引擎會調用一個由客戶端程序員提供的 OnErrorListener.onError() 方法。客戶端程序員可以通過調用 MediaPlayer.setOnErrorListener(android.media.MediaPlayer.OnErrorListener) 方法來注冊 OnErrorListener .

2.1) 一旦發生錯誤, MediaPlayer 對象會進入到 Error 狀態。

2.2) 為了重用一個處于 Error 狀態的 MediaPlayer 對象,可以調用 reset() 方法來把這個對象恢復成 Idle 狀態。

2.3) 注冊一個 OnErrorListener 來獲知內部播放引擎發生的錯誤是好的編程習慣。

2.4) 在不合法的狀態下調用一些方法,如 prepare() prepareAsync() setDataSource() 方法會拋出 IllegalStateException 異常。


3) 調用 setDataSource(FileDescriptor) 方法,或 setDataSource(String) 方法,或 setDataSource(Context,Uri) 方法,或 setDataSource(FileDescriptor,long,long) 方法會使處于 Idle 狀態的對象遷移到 Initialized 狀態。


3.1) 若當此 MediaPlayer 處于其它的狀態下,調用 setDataSource() 方法,會拋出 IllegalStateException 異常。

3.2) 好的編程習慣是不要疏忽了調用 setDataSource() 方法的時候可能會拋出的 IllegalArgumentException 異常和 IOException 異常。


4) 在開始播放之前, MediaPlayer 對象必須要進入 Prepared 狀態。

4.1) 有兩種方法(同步和異步)可以使 MediaPlayer 對象進入 Prepared 狀態:要么調用 prepare() 方法( 同步 ),此方法返回就表示該 MediaPlayer 對象已經進入了 Prepared 狀態;要么調用 prepareAsync() 方法( 異步 ),此方法會使此 MediaPlayer 對象進入 Preparing 狀態并返回,而內部的播放引擎會繼續未完成的準備工作。當同步版本返回時或異步版本的準備工作完全完成時就會調用客戶端程序員提供的 OnPreparedListener.onPrepared() 監聽方法。可以調用 MediaPlayer.setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener) 方法來注冊 OnPreparedListener .

4.2) Preparing 是一個中間狀態,在此狀態下調用任何具備邊影響的方法的結果都是未知的!

4.3) 在不合適的狀態下調用 prepare() prepareAsync() 方法會拋出 IllegalStateException 異常。當 MediaPlayer 對象處于 Prepared 狀態的時候,可以調整音頻/視頻的屬性,如音量,播放時是否一直亮屏,循環播放等。


5) 要開始播放,必須調用 start() 方法。當此方法成功返回時, MediaPlayer 的對象處于 Started 狀態。 isPlaying() 方法可以被調用來測試某個 MediaPlayer 對象是否在 Started 狀態。

5.1) 當處于 Started 狀態時,內部播放引擎會調用客戶端程序員提供的 OnBufferingUpdateListener.onBufferingUpdate() 回調方法,此回調方法允許應用程序追蹤流播放的緩沖的狀態。

5.2) 對一個已經處于 Started 狀態的 MediaPlayer 對象調用 start() 方法沒有影響。


6) 播放可以被暫停,停止,以及調整當前播放位置。當調用 pause() 方法并返回時,會使 MediaPlayer 對象進入 Paused 狀態。注意 Started Paused 狀態的相互轉換在內部的播放引擎中是異步的。所以可能需要一點時間在 isPlaying() 方法中更新狀態,若在播放流內容,這段時間可能會有幾秒鐘。

6.1) 調用 start() 方法會讓一個處于 Paused 狀態的 MediaPlayer 對象從之前暫停的地方恢復播放。當調用 start() 方法返回的時候, MediaPlayer 對象的狀態會又變成 Started 狀態。

6.2) 對一個已經處于 Paused 狀態的 MediaPlayer 對象 pause() 方法沒有影響。


7) 調用 stop() 方法會停止播放,并且還會讓一個處于 Started Paused Prepared PlaybackCompleted 狀態的 MediaPlayer 進入 Stopped 狀態。

7.1) 對一個已經處于 Stopped 狀態的 MediaPlayer 對象 stop() 方法沒有影響。


8) 調用 seekTo() 方法可以調整播放的位置。

8.1) seekTo(int) 方法是異步執行的,所以它可以馬上返回,但是實際的定位播放操作可能需要一段時間才能完成,尤其是播放流形式的音頻/視頻。當實際的定位播放操作完成之后,內部的播放引擎會調用客戶端程序員提供的 OnSeekComplete.onSeekComplete() 回調方法。可以通過 setOnSeekCompleteListener(OnSeekCompleteListener) 方法注冊。

8.2) 注意, seekTo(int) 方法也可以在其它狀態下調用,比如 Prepared Paused PlaybackCompleted 狀態。此外,目前的播放位置,實際可以調用 getCurrentPosition() 方法得到,它可以幫助如音樂播放器的應用程序不斷更新播放進度


9) 當播放到流的末尾,播放就完成了。

9.1) 如果調用了 setLooping(boolean) 方法開啟了循環模式,那么這個 MediaPlayer 對象會重新進入 Started 狀態。

9.2) 若沒有開啟循環模式,那么內部的播放引擎會調用客戶端程序員提供的 OnCompletion.onCompletion() 回調方法。可以通過調用 MediaPlayer.setOnCompletionListener(OnCompletionListener) 方法來設置。內部的播放引擎一旦調用了 OnCompletion.onCompletion() 回調方法,說明這個 MediaPlayer 對象進入了 PlaybackCompleted 狀態。

9.3) 當處于 PlaybackCompleted 狀態的時候,可以再調用 start() 方法來讓這個 MediaPlayer 對象再進入 Started 狀態。

?

#################################################################################################

這張狀態轉換圖清晰的描述了MediaPlayer的各個狀態,也列舉了主要的方法的調用時序,每種方法只能在一些特定的狀態下使用,如果使用時MediaPlayer的狀態不正確則會引發IllegalStateException異常。

?

Idle 狀態:當使用new()方法創建一個MediaPlayer對象或者調用了其reset()方法時,該MediaPlayer對象處于idle狀態。這兩種方法的一個重要差別就是:如果在這個狀態下調用了getDuration()等方法(相當于調用時機不正確),通過reset()方法進入idle狀態的話會觸發OnErrorListener.onError(),并且MediaPlayer會進入Error狀態;如果是新創建的MediaPlayer對象,則并不會觸發onError(),也不會進入Error狀態。

?

End 狀態:通過release()方法可以進入End狀態,只要MediaPlayer對象不再被使用,就應當盡快將其通過release()方法釋放掉,以釋放相關的軟硬件組件資源,這其中有些資源是只有一份的(相當于臨界資源)。如果MediaPlayer對象進入了End狀態,則不會在進入任何其他狀態了。

Initialized 狀態:這個狀態比較簡單,MediaPlayer調用setDataSource()方法就進入Initialized狀態,表示此時要播放的文件已經設置好了。

Prepared 狀態:初始化完成之后還需要通過調用prepare()或prepareAsync()方法,這兩個方法一個是同步的一個是異步的,只有進入Prepared狀態,才表明MediaPlayer到目前為止都沒有錯誤,可以進行文件播放。

?

Preparing 狀態:這個狀態比較好理解,主要是和prepareAsync()配合,如果異步準備完成,會觸發OnPreparedListener.onPrepared(),進而進入Prepared狀態。

?

Started 狀態:顯然,MediaPlayer一旦準備好,就可以調用start()方法,這樣MediaPlayer就處于Started狀態,這表明MediaPlayer正在播放文件過程中。可以使用isPlaying()測試MediaPlayer是否處于了Started狀態。如果播放完畢,而又設置了循環播放,則MediaPlayer仍然會處于Started狀態,類似的,如果在該狀態下MediaPlayer調用了seekTo()或者start()方法均可以讓MediaPlayer停留在Started狀態。

?

Paused 狀態:Started狀態下MediaPlayer調用pause()方法可以暫停MediaPlayer,從而進入Paused狀態,MediaPlayer暫停后再次調用start()則可以繼續MediaPlayer的播放,轉到Started狀態,暫停狀態時可以調用seekTo()方法,這是不會改變狀態的。

?

Stop 狀態:Started或者Paused狀態下均可調用stop()停止MediaPlayer,而處于Stop狀態的MediaPlayer要想重新播放,需要通過prepareAsync()和prepare()回到先前的Prepared狀態重新開始才可以。

?

PlaybackCompleted狀態:文件正常播放完畢,而又沒有設置循環播放的話就進入該狀態,并會觸發OnCompletionListener的onCompletion()方法。此時可以調用start()方法重新從頭播放文件,也可以stop()停止MediaPlayer,或者也可以seekTo()來重新定位播放位置。

?

Error狀態:如果由于某種原因MediaPlayer出現了錯誤,會觸發OnErrorListener.onError()事件,此時MediaPlayer即進入Error狀態,及時捕捉并妥善處理這些錯誤是很重要的,可以幫助我們及時釋放相關的軟硬件資源,也可以改善用戶體驗。通過setOnErrorListener(android.media.MediaPlayer.OnErrorListener)可以設置該監聽器。如果MediaPlayer進入了Error狀態,可以通過調用reset()來恢復,使得MediaPlayer重新返回到Idle狀態。

Android播放聲音MediaPlayer類詳細介紹


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产目拍亚洲精品一区麻豆 | www.色婷婷| 欧美成人亚洲 | 天堂网一区二区 | 国产亚洲欧美一区二区 | 免费视频爱爱太爽在线观看 | 香蕉视频在线观看免费 | 亚洲精品国产第一区二区多人 | 日日操夜夜操视频 | 久久夜夜 | 性生生活网站免费 | 日韩城人网站 | 久久久久国产精品免费网站 | 欧美乱码 | 国产专区日韩精品欧美色 | 日本不卡视频免费 | 欧美成人xx免费视频 | 在线播放精品一区二区啪视频 | 澳门成人免费永久视频 | 在线观看一级毛片免费 | 国产亚洲精品热视频在线观看 | 免费四影虎ww4hu10 | 欧美日本免费观看αv片 | 久热免费在线视频 | 国产无套乱子伦精彩是白视频 | 免费一级欧美毛片 | 日韩精品中文字幕视频一区 | 日本在线三级 | 精品亚洲在线 | 91在线免费视频观看 | 精品国产高清a毛片无毒不卡 | 国产亚洲精品久久精品6 | 97久久国产一区二区三区四区 | 欧美与黑人午夜性猛交久久久 | 久久精品中文字幕不卡一二区 | 国产一区二区三区视频在线观看 | 国精品在亚洲_欧美 | 亚洲综合一区二区三区 | 欧美一级片网 | 日本一级高清不卡视频在线 | 国产精品v欧美精品∨日韩 国产精品v一区二区三区 |