解讀官方Android MediaPlayer API(1)
public class MediaPlayer
extends Object
MediaPlayer class 能夠用來使用來控制vudio/video(音訊或視訊)檔案和流檔案的播放.舉個例子可以在
VideoView 中瞭解怎麼樣使用這些方法。
請看Audio and Video 中附加的文件。
MedioPlayer狀態圖如下:
audio/video(音訊/視訊)檔案和流的控制是通過狀態機制管理的。以下圖示顯示了 MediaPlayer
物件在播
放控制操作支援下被執行的生命週期和狀態。橢圓代表MedioPlayer物件可能駐留的狀態。弧線代表播放控制
操作驅使物件的狀態間的轉換。這裡有兩種弧線型別。單箭頭的弧線代表同步的方法呼叫,而雙箭頭的弧線代
表非同步的方法呼叫。
從狀態圖,我們可以知道MedioPlayer物件有以下的狀態:
1
) 當使用new或呼叫reset()後MedioPlayer物件就會被建立,物件將處在Idle狀態;並且當release()被呼叫後,
物件將處於End狀態。 這兩種狀態之間是MedioPlayer物件的生命週期。
1.1) 這裡有點微妙但又很重要的不同是在MedioPlayer物件的建立和建立並呼叫reset()之後的MedioPlayer物件中。
在Idle狀態時呼叫例如getCurrentPosition()
, getDuration()
, getVideoHeight()
, getVideoWidth()
,
setAudioStreamType(int)
, setLooping(boolean)
, setVolume(float, float)
, pause()
, start()
, stop()
, seekTo(int)
,
prepare()
or prepareAsync() 這些方法,都
是
程式設計的錯誤。在MediaPlayer物件被構建後如果這些方法被呼叫,框架將無法被
內部的播放引擎回撥OnErrorListener.onError() 並且物件的狀態不會改變。但如果MediaPlayer物件呼叫了reset()之後,調
用這些方法,內部的播放引擎將能夠回撥 OnErrorListener.onError()方法,並且物件會轉入Error狀態。
1.2)並且推薦一旦MediaPlayer不再使用,就立即呼叫release()方法那麼內部播放引擎對這個MediaPlayer物件的關聯將會立即釋放資源。
資源包括單一
的資源例如計算機加速硬體元件(可理解為只能夠一個物件使用的資源),所以若沒有呼叫release()方法可能會導致後面
的MediaPlayer物件無法使用這單一資源
從而退回到軟體實現或執行失敗,一旦MediaPlayer物件進入了End狀態,它將不再被使
用,並且沒有辦法回到其他任何狀態。
1.3)此外,使用new建立的MediaPlayer物件將處於Idle狀態,然而那些通過過載的create()便利方法建立的MediaPlayer物件卻不是出在Idle狀態。
實際上,如果
成功呼叫create()方法,那麼這些物件將是處在
Prepared狀態。
2)通常,一些播放控制操作由於各種各樣的原因而執行失敗,例如 audio/video的格式不支援;缺少隔行掃描的audio/video;分表率太高;流超時等此類原因。
那麼,錯誤的報告和恢復在這些情況下是重要的。有時,由於程式設計的錯誤,在一個無效的狀態下呼叫一個播放控制操作也可能發生。在所有這些錯誤條件下,
內部的播放引擎會呼叫一個由客戶端程式設計師提供的OnErrorListener.onError()方法。客戶端程式設計師可以通過呼叫Medialayer.setOnErrorListener(android.media.
MediaPlayer.OnErrorListener)方法來註冊OnErrorListener.
2.1)一旦錯誤發生,值得注意的是,MediaPlayer物件會進入Error狀態,即使沒有註冊OnErrorListener,應用還是會進入Error狀態。
2.2)為了重新使用在Error狀態的MediaPlayer物件使它從Error狀態恢復,那麼reset()方法的呼叫能夠恢復物件到Idle狀態。
2.3)一個好的程式設計實踐你的應用,是有註冊一個OnErrorListener用來注意來自內部播放引擎的Error的通知。
2.4)在一個invalid狀態下, 例如呼叫prepare()
, prepareAsync()
,或者一個重寫的setDataSource方法。IlleglStateException異常被丟擲,可以防止程式設計的錯誤.。
3)呼叫setDataSource(FileDescriptor)方法,或setDataSource(String)方法,或setDataSource(Context,Uri)方法,
或setDataSource(FileDescriptor,long,long)方法會使處於Idle狀態的物件遷移到Initialized狀態。
3.1)若當物件在任何一個其他狀態下呼叫setDataSource()會丟擲 IllegalStateException 異常。
3.2)好的程式設計習慣是不要疏忽了呼叫setDataSource()方法的時候可能會丟擲的IllegalArgumentException異常和IOException異常。
4)一個MedioPlayer物件在播放開始之前必須首先進入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異常。
4.4)當MediaPlayer物件處於Prepared狀態的時候,可以呼叫相應的方法調整音訊/視訊的屬性,如音量,
播放時是否一直亮屏,迴圈播放等。
5)想要開始播放,start()必須需要呼叫。在
start()成功的呼叫之後,
MediaPlayer 物件將進入 Started的狀態,isPlaying()方法可
以被呼叫來測試某個MediaPlayer物件是否在Started狀態。
5.1)當在 Started狀態,內部播放引擎會呼叫客戶端程式設計師提供的OnBufferingUpdateListener.onBufferingUpdate()回撥方法,
通過setOnBufferingUpdateListener(OnBufferingUpdateListener)註冊監聽。
此回撥方法允許應用程式追蹤流播放的緩衝的狀態。
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)一旦MediaPlayer在Stopped狀態,mediaPlayer不能開始播放,直到prepare() or prepareAsync()呼叫後,
使MediaPlayer再次進入Prepared狀態之後。
7.2)對一個已經處於Stopped狀態的MediaPlayer物件stop()方法沒有影響。
8) 呼叫seekTo()方法可以調整播放的位置。
8.1)seekTo(int)方法是非同步執行的,所以它可以馬上返回,但是實際的定位播放操作可能需要一段時間才能完成,
尤其是播放流形式的音訊/視訊。當實際的定位播放操作完成之後,內部的播放引擎會呼叫客戶端程式設計師提供的
OnSeekComplete.onSeekComplete()回撥方法。可以通過setOnSeekCompleteListener(OnSeekCompleteListener)方法註冊。
8.2)注意,seekTo(int)方法也可以在其它狀態下呼叫,比如Prepared,Paused和PlaybackCompleted狀態。
8.3)此外,目前的播放位置,實際可以呼叫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狀態。
參考文獻:
1.谷歌官方Android SDK開發文件
2.http://my.oschina.net/zhangqingcai/blog/29660
相關文章
- 谷歌官方 Android MVP 模式程式碼解讀谷歌AndroidMVP模式
- Docker瞭解(官方解讀)Docker
- 解讀Android官方MVP專案單元測試AndroidMVP
- Android MediaPlayer的生命週期Android
- android音視訊指南-MediaPlayer概述Android
- Python 官方文件解讀(1):66 個內建函式Python函式
- Android音訊開發之MediaRecorder/MediaPlayerAndroid音訊
- FastDFS的配置、部署與API使用解讀(1)Get Started with FastDFSASTAPI
- Android官方多渠道方案詳解Android
- Android音視訊之MediaPlayer音視訊播放Android
- Node中Buffer 常用API解讀API
- vuex給getter傳參的官方例子解讀Vue
- 官方詳細介紹Android Studio 3.0 Canary 1Android
- WebUploader API 文件詳細解讀WebAPI
- Android Media Framework(三)OpenMAX API閱讀與分析AndroidFrameworkAPI
- NodeJS Stream(可讀流、可寫流) API解讀NodeJSAPI
- Android多媒體之視訊播放器(基於MediaPlayer)Android播放器
- Android官方導航欄ActionBar使用詳解Android
- Android鬼點子-通過Google官方示例學NDK(1)AndroidGo
- preact原始碼解讀(1)React原始碼
- Vue 原始碼解讀(5)—— 全域性 APIVue原始碼API
- Swift 官方 API 設計準則SwiftAPI
- [ARKit]3-蘋果官方AR變色龍Demo解讀蘋果
- Android -- 多媒體播放之MediaPlayer使用內部實現簡析Android
- 基於Android的MediaPlayer的音樂播放器的封裝Android播放器封裝
- 瞭解 Android API 中的 SharedPreferencesAndroidAPI
- Vue 原始碼解讀(1)—— 前言Vue原始碼
- PostgreSQL 原始碼解讀(1)- 插入資料#1SQL原始碼
- [ARKit]2-蘋果官方AR場景互動Demo解讀蘋果
- Oracle 官方教材閱讀整理Oracle
- 蘋果官方文件閱讀指南蘋果
- NPOI讀取Excel官方demoExcel
- SAP官方提供的人臉識別APIAPI
- Android Google MVP Demo TODO解讀AndroidGoMVP
- 讀解Android 系統原始碼?Android原始碼
- Android APIAndroidAPI
- android——apiAndroidAPI
- CQRS解構: 用讀寫分離設計APIAPI