Android音視頻開發(fā)之MediaPlayer使用教程
MediaPlayer
Android
多媒體框架支持播放提供了MediaPlayer
API,可以通過MediaPlayer
來實(shí)現(xiàn)媒體文件播放??梢哉fMediaPlayer
是非常方便使用的多媒體播放器,只需要簡(jiǎn)單設(shè)置就能實(shí)現(xiàn)對(duì)音頻和視頻播放功能,其內(nèi)部幫助開發(fā)者實(shí)現(xiàn)了播放對(duì)象獲取解碼以及播放功能。
簡(jiǎn)單使用
MediaPlayer
支持多種資源形式:本地資源、內(nèi)部URI、外部網(wǎng)址。
//播放器實(shí)例化 mediaPlayer = new MediaPlayer(); //準(zhǔn)備播放素材 Uri uri = Uri.fromFile(new File("sdcard/DCIM","Camera/test.mp4")); try { //播放器載入資源 mediaPlayer.setDataSource(this,uri); } catch (IOException e) { e.printStackTrace(); } //播放器異步準(zhǔn)備 mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { //播放操作 mediaPlayer.start(); } }); //播放窗口展示 SurfaceView surfaceView = new SurfaceView(this); surfaceView.post(new Runnable() { @Override public void run() { mediaPlayer.setSurface(surfaceView.getHolder().getSurface()); } });
以上代碼示例就是MediaPlayer
簡(jiǎn)單使用過程。其中prepareAsync()
是異步操作需要在回調(diào)setOnPreparedListener
方法了解最終播放器準(zhǔn)備結(jié)果然后再執(zhí)行播放操作。當(dāng)然播放器也支持同步準(zhǔn)備prepare
方法,但推薦使用異步操作,因?yàn)橘Y源獲取過程可能會(huì)涉及到解碼數(shù)據(jù)會(huì)是耗時(shí)操作,同步操作很有可能造成ANR錯(cuò)誤。
缺陷
MediaPlayer
雖然有內(nèi)部狀態(tài),某些操作只有在特定狀態(tài)下正確操作才能生效。若在非指定狀態(tài)下操作或許會(huì)導(dǎo)致播放器發(fā)生異常更有可能發(fā)生崩潰的情況。但播放器的內(nèi)部狀態(tài)機(jī)并沒有暴露接口給開發(fā)者,無法隨時(shí)能夠獲取到目前播放器當(dāng)前狀態(tài)。
AndroidMediaPlayer播放器封裝
因?yàn)槿毕菰蛑苯邮褂?code>MediaPlayer就不能很好的去管理狀態(tài)。因此可以自行對(duì)MediaPlayer
進(jìn)行封裝使用,可以將功能進(jìn)行整理并且增加狀態(tài)管理和方便錯(cuò)誤統(tǒng)一處理等邏輯。
狀態(tài)機(jī)編寫
根據(jù)MediaPlayer
狀態(tài)圖預(yù)設(shè)幾種狀態(tài)類型以暫存播放器內(nèi)部狀態(tài)。
private static final int IDLE = 0; // 空閑狀態(tài) private static final int INIT = 3;// 初始化狀態(tài) private static final int PREPARING = 4;// 準(zhǔn)備狀態(tài) private static final int PREPARED = 5;// 準(zhǔn)備狀態(tài) private static final int STARTED = 6;// 開始狀態(tài) private static final int PAUSED = 7;// 暫停狀態(tài) private static final int STOPPED = 8;// 停止?fàn)顟B(tài) private static final int END = 9; // 結(jié)束狀態(tài) private static final int ERROR = 10;// 錯(cuò)誤狀態(tài)
內(nèi)部類
使用mPlayerStatus
暫存播放器狀態(tài)
@IntDef({IDLE, END, ERROR, INIT, PREPARED, STARTED, PAUSED, STOPPED, }) public @interface STATUS { } MediaPlayer mMediaPlayer; Context mContext; @STATUS int mPlayerStatus = IDLE;
初始化函數(shù)
初始化函數(shù)實(shí)例化播放器并注冊(cè)基本播放所需要的回調(diào)函數(shù)
public AndroidMediaPlayer(Context context) { mContext = context; mMediaPlayer = new MediaPlayer(); mMediaPlayer.setOnErrorListener(this); mMediaPlayer.setOnCompletionListener(this); mMediaPlayer.setOnPreparedListener(this); mPlayerStatus = INIT; }
方法和回調(diào)
封裝播放器基礎(chǔ)方法可供播放調(diào)用并且進(jìn)行狀態(tài)機(jī)判斷,若不在可操作范圍內(nèi)則不可執(zhí)行對(duì)應(yīng)操作。同時(shí)對(duì)于資源設(shè)置方法通過原生api
可以看到有許多在形式,但這里就只是用URI
來做入?yún)⒘恕?/p>
//資源入?yún)? public void setSource(Uri uri){ try { mMediaPlayer.setDataSource(mContext,uri); mMediaPlayer.prepareAsync(); mPlayerStatus = PREPARING; } catch (IOException e) { e.printStackTrace(); } } // 設(shè)置可視化窗口 public void setSurface(Surface surface){ mMediaPlayer.setSurface(surface); } //開始播放 public void start(){ mMediaPlayer.start(); mPlayerStatus = STARTED; } //暫停 public void pause(){ if(mPlayerStatus > PAUSED) return; mMediaPlayer.pause(); mPlayerStatus = PAUSED; } //停止 public void stop(){ if(mPlayerStatus > STOPPED) return; mMediaPlayer.stop(); mPlayerStatus = STOPPED; } //釋放 public void release(){ if(mPlayerStatus >= INIT){ mMediaPlayer.release(); mMediaPlayer = null; mPlayerStatus = END; } } // 錯(cuò)誤回調(diào) @Override public boolean onError(MediaPlayer mp, int what, int extra) { mPlayerStatus = ERROR; return false; } // 播放回調(diào) @Override public void onCompletion(MediaPlayer mp) { } // 準(zhǔn)備成功回調(diào) @Override public void onPrepared(MediaPlayer mp) { mPlayerStatus = PREPARED; }
小結(jié)
MediaPlayer
作為官方提供封裝的播放器在使用上并沒有什么難度,可以說開發(fā)者直接開箱即用?;蛟S對(duì)于簡(jiǎn)單開發(fā)視頻播放已經(jīng)足夠了,能夠播放本地文件或是網(wǎng)絡(luò)文件等都能支持。但對(duì)于深入理解MediaPlayer
可能還遠(yuǎn)遠(yuǎn)不夠,后續(xù)去讀讀源碼來了解內(nèi)部實(shí)現(xiàn)。之后要自行實(shí)現(xiàn)編解碼來播放音視頻等能力去處理和添加其他效果的時(shí)候,那時(shí)MediaPlayer
或許就捉襟見肘了。
到此這篇關(guān)于Android音視頻開發(fā)之MediaPlayer使用教程的文章就介紹到這了,更多相關(guān)Android MediaPlayer內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解android在mob平臺(tái)實(shí)現(xiàn)qq登陸和分享
這篇文章主要介紹了詳解android在mob平臺(tái)實(shí)現(xiàn)qq登陸和分享,對(duì)接入第三方平臺(tái)SDK感興趣的同學(xué)們,可以參考下2021-04-04Android 中SwipeRefreshLayout與ViewPager滑動(dòng)事件沖突解決方法
這篇文章主要介紹了Android 中SwipeRefreshLayout與ViewPager滑動(dòng)事件沖突解決方法的相關(guān)資料,需要的朋友可以參考下2017-04-04webview添加參數(shù)與修改請(qǐng)求頭的user-agent實(shí)例
這篇文章主要介紹了webview添加參數(shù)與修改請(qǐng)求頭的user-agent實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03Flutter Android端啟動(dòng)白屏問題的解決
Flutter 應(yīng)用在 Android 端上啟動(dòng)時(shí)會(huì)有一段很明顯的白屏現(xiàn)象,白屏的時(shí)長(zhǎng)由設(shè)備的性能決定,設(shè)備性能越差,白屏?xí)r間越長(zhǎng)。這篇文章主要介紹了Flutter Android端啟動(dòng)白屏問題的解決。感興趣的小伙伴們可以參考一下2018-07-07Android編程學(xué)習(xí)之抽象類AbsListView用法實(shí)例分析
這篇文章主要介紹了Android編程學(xué)習(xí)之抽象類AbsListView用法,較為詳細(xì)的分析了抽象類AbsListView的功能、結(jié)構(gòu)、定義及使用注意事項(xiàng)等,需要的朋友可以參考下2015-10-10