MediaPlayer:昨個回顧了一下

最近項(xiàng)目需要用到 MediaPlayer + SurfaceView 來播放短視頻框杜,回憶了一下之前的做法寫了一下狭园,但是出現(xiàn)不少問題爱态,這邊干脆就看了一下 api 從頭學(xué)習(xí)了一下挑格。


MediaPlayer

參考:鏈接

這個類主要用于音視頻的播放师幕,而使用它只要了解這個類的幾個狀態(tài)就能很好地運(yùn)用。上面鏈接中有相應(yīng)的狀態(tài)圖抹凳,我就不再費(fèi)時畫了遏餐。但是這個圖是一定要看的,比我這長篇容易理解得多赢底。


一失都、快速使用:播放功能

我們用 MediaPlayer 如果只是圖個省事,可以通過下面的方式快速實(shí)現(xiàn)播放功能:

  • 1.創(chuàng)建 MediaPlayer 對象
  • 2.確認(rèn)要加載的音視頻流或文件:setDataSource()
  • 3.加載音視頻流或文件:prepare()
  • 4.播放:start()

這之后可以通過 pause()幸冻、stop()粹庞、release() 等方法進(jìn)行控制,但是如果需要切換播放資源嘁扼,則需先調(diào)用 reset() 方法使 MediaPlayer 對象回到 Idle 狀態(tài)信粮,才能再次調(diào)用 setDataSource() 切換資源。

二趁啸、快速使用:setDataSource的使用

如果是正在學(xué)習(xí) Android 的新人强缘,初次使用對于 setDataSource() 這個方法應(yīng)該也會有疑惑督惰,這里也講解一下使用方法:

Sets the data source as a content Uri.
@param context the Context to use when resolving the Uri
@param uri the Content URI of the data you want to play
public void setDataSource(Context context, Uri uri)

Sets the data source (file-path or http/rtsp URL) to use.
@param path the path of the file, or the http/rtsp URL of the stream you want to play
public void setDataSource(String path)

Sets the data source (FileDescriptor) to use. It is the caller’s responsibility
to close the file descriptor. It is safe to do so as soon as this call returns.
@param fd the FileDescriptor for the file you want to play
public void setDataSource(FileDescriptor fd)

Sets the data source (FileDescriptor) to use. The FileDescriptor must be
seekable (N.B. a LocalSocket is not seekable). It is the caller’s responsibility
to close the file descriptor. It is safe to do so as soon as this call returns.
@param fd the FileDescriptor for the file you want to play
@param offset the offset into the file where the data to be played starts, in bytes
@param length the length in bytes of the data to be played
public void setDataSource(FileDescriptor fd, long offset, long length)

上面是這個方法的多個不同參數(shù)的重載,現(xiàn)在對上面方法的使用進(jìn)行說明:

  • setDataSource(Context context, Uri uri)
    假設(shè) test.mp3 放在 res/raw/ 目錄下
mMediaPlayer= new MediaPlayer(); 
Uri setDataSourceuri = Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.test);
mMediaPlayer.setDataSource(this, uri)
  • public void setDataSource(String path)
    這里可以直接填外部存儲路徑或者音視頻 Url
    1.播放本地音視頻:
mMediaPlayer.setDataSource("/mnt/sdcard/test.mp3");

2.播放網(wǎng)絡(luò)音視頻:

Uri uri = Uri.parse("http://**");  
mMediaPlayer.setDataSource(Context, uri);  
  • public void setDataSource(FileDescriptor fd, long offset, long length)
    假設(shè) test.mp3 文件放在 assets 目錄下
AssetManager assetMg = this.getApplicationContext().getAssets();
AssetFileDescriptor fileDescriptor = assetMg.openFd("test.mp3");  
mMediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getLength()); 

三旅掂、狀態(tài)講解

  • Idle狀態(tài):當(dāng)使用new()方法創(chuàng)建一個MediaPlayer對象或者調(diào)用了其reset()方法時赏胚,該MediaPlayer對象處于idle狀態(tài)。在處于Idle狀態(tài)時商虐,調(diào)用getCurrentPosition(),getDuration(),getVideoHeight(),getVideoWidth(),setAudioStreamType(int), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int), prepare()或者 prepareAsync()方法都會出現(xiàn)相應(yīng)錯誤觉阅。這兩種方法的一個重要差別就是:當(dāng)一個MediaPlayer對象剛被構(gòu)建的時候,內(nèi)部的播放引擎和對象的狀態(tài)都沒有改變秘车,在這個時候調(diào)用以上的那些方法典勇,框架將無法回調(diào)客戶端程序注冊的OnErrorListener.onError()方法,所以不會進(jìn)入Error狀態(tài)叮趴;但若這個MediaPlayer對象調(diào)用了reset()方法之后割笙,再調(diào)用以上的那些方法,內(nèi)部的播放引擎就會回調(diào)客戶端程序注冊的OnErrorListener.onError()方法眯亦,這時MediaPlayer會進(jìn)入Error狀態(tài)伤溉。
    提示:使用new操作符創(chuàng)建的MediaPlayer對象處于Idle狀態(tài),而那些通過重載的create()便利方法創(chuàng)建的MediaPlayer對象卻不是處于Idle狀態(tài)妻率。事實(shí)上乱顾,如果成功調(diào)用了重載的create()方法,那么這些對象已經(jīng)是Prepare狀態(tài)了宫静。

  • End狀態(tài):通過release()方法可以進(jìn)入End狀態(tài)走净,只要MediaPlayer對象不再被使用,就應(yīng)當(dāng)盡快將其通過release()方法釋放掉囊嘉,以釋放相關(guān)的軟硬件組件資源温技,這其中有些資源是只有一份的(相當(dāng)于臨界資源)革为。如果MediaPlayer對象進(jìn)入了End狀態(tài)扭粱,則不會再進(jìn)入任何其他狀態(tài)了。

  • Initialized狀態(tài):這個狀態(tài)比較簡單震檩,MediaPlayer調(diào)用setDataSource()方法就進(jìn)入Initialized狀態(tài)琢蛤,表示此時要播放的文件已經(jīng)設(shè)置好了。
    提示:若當(dāng)此MediaPlayer處于其它的狀態(tài)下抛虏,調(diào)用setDataSource()方法博其,會拋出IllegalStateException異常。

  • Prepared狀態(tài):初始化完成之后還需要通過調(diào)用prepare()或prepareAsync()方法迂猴,這兩個方法一個是同步的一個是異步的慕淡,只有進(jìn)入Prepared狀態(tài),才表明MediaPlayer到目前為止都沒有錯誤沸毁,可以進(jìn)行文件播放峰髓。
    提示:在不合適的狀態(tài)下調(diào)用prepare()和prepareAsync()方法會拋出IllegalStateException異常傻寂。當(dāng)MediaPlayer對象處于Prepared狀態(tài)的時候,可以調(diào)整音頻/視頻的屬性携兵,如音量疾掰,播放時是否一直亮屏,循環(huán)播放等徐紧。

  • Preparing狀態(tài):這個狀態(tài)比較好理解静檬,主要是和prepareAsync()配合,如果異步準(zhǔn)備完成并级,會觸發(fā)OnPreparedListener.onPrepared()拂檩,進(jìn)而進(jìn)入Prepared狀態(tài)。

  • Started狀態(tài):顯然嘲碧,MediaPlayer一旦準(zhǔn)備好广恢,就可以調(diào)用start()方法,這樣MediaPlayer就處于Started狀態(tài)呀潭,這表明MediaPlayer正在播放文件過程中钉迷。可以使用isPlaying()測試MediaPlayer是否處于了Started狀態(tài)钠署。如果播放完畢糠聪,而又設(shè)置了循環(huán)播放,則MediaPlayer仍然會處于Started狀態(tài)谐鼎,類似的舰蟆,如果在該狀態(tài)下MediaPlayer調(diào)用了seekTo()或者start()方法均可以讓MediaPlayer停留在Started狀態(tài)。

  • Paused狀態(tài):Started狀態(tài)下MediaPlayer調(diào)用pause()方法可以暫停MediaPlayer狸棍,從而進(jìn)入Paused狀態(tài)身害,MediaPlayer暫停后再次調(diào)用start()則可以繼續(xù)MediaPlayer的播放,轉(zhuǎn)到Started狀態(tài)草戈,暫停狀態(tài)時可以調(diào)用seekTo()方法塌鸯,這是不會改變狀態(tài)的。

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

  • PlaybackCompleted狀態(tài):文件正常播放完畢费韭,而又沒有設(shè)置循環(huán)播放的話就進(jìn)入該狀態(tài)茧球,并會觸發(fā)OnCompletionListener的onCompletion()方法。此時可以調(diào)用start()方法重新從頭播放文件星持,也可以stop()停止MediaPlayer抢埋,或者也可以seekTo()來重新定位播放位置。

  • Error狀態(tài):在一般情況下,由于種種原因一些播放控制操作可能會失敗揪垄,如不支持的音頻/視頻格式鲤屡,缺少隔行掃描的音頻/視頻,分辨率太高福侈,流超時等原因酒来,等等會觸發(fā)會觸發(fā)OnErrorListener.onError()事件,此時MediaPlayer會進(jìn)入Error狀態(tài)肪凛,及時捕捉并妥善處理這些錯誤是很重要的堰汉,可以幫助我們及時釋放相關(guān)的軟硬件資源,也可以改善用戶體驗(yàn)伟墙。


本想自己看看順便翻譯一點(diǎn)翘鸭,結(jié)果撿了現(xiàn)成的翻譯,參考鏈接:
http://www.itnose.net/detail/6090452.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末戳葵,一起剝皮案震驚了整個濱河市就乓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拱烁,老刑警劉巖生蚁,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異戏自,居然都是意外死亡邦投,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進(jìn)店門擅笔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來志衣,“玉大人,你說我怎么就攤上這事猛们∧罡” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵弯淘,是天一觀的道長绿店。 經(jīng)常有香客問我,道長耳胎,這世上最難降的妖魔是什么惯吕? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任惕它,我火速辦了婚禮怕午,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘淹魄。我一直安慰自己郁惜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著兆蕉,像睡著了一般羽戒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虎韵,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天易稠,我揣著相機(jī)與錄音,去河邊找鬼包蓝。 笑死驶社,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的测萎。 我是一名探鬼主播亡电,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼硅瞧!你這毒婦竟也來了份乒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤腕唧,失蹤者是張志新(化名)和其女友劉穎或辖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枣接,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孝凌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了月腋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蟀架。...
    茶點(diǎn)故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖榆骚,靈堂內(nèi)的尸體忽然破棺而出片拍,到底是詐尸還是另有隱情,我是刑警寧澤妓肢,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布捌省,位于F島的核電站,受9級特大地震影響碉钠,放射性物質(zhì)發(fā)生泄漏纲缓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一喊废、第九天 我趴在偏房一處隱蔽的房頂上張望祝高。 院中可真熱鬧,春花似錦污筷、人聲如沸工闺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽陆蟆。三九已至雷厂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叠殷,已是汗流浹背改鲫。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留林束,地道東北人钩杰。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像诊县,于是被迫代替她去往敵國和親讲弄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內(nèi)容