android mediaPlayer的基本使用

1、MediaPlayer的生命周期

MediaPlayer的狀態(tài)圖

有兩種類型的弧,單箭頭表示的是同步方法調(diào)用,有兩個(gè)箭頭代表異步方法調(diào)用

1、Idle 狀態(tài)及End 狀態(tài)
當(dāng)使用new()方法創(chuàng)建一個(gè)MediaPlayer對(duì)象或者調(diào)用了其reset()方法時(shí),該MediaPlayer對(duì)象處于idle狀態(tài)。release()方法調(diào)用后進(jìn)入End狀態(tài)。

2、Initialized 狀態(tài)
setDataSource()調(diào)用之后,MediaPlayer就進(jìn)入Initialized狀態(tài),表示要播放的文件已經(jīng)設(shè)置好了。如果setDataSource()在MediaPlayer的非Idle 狀態(tài)調(diào)用,會(huì)拋出IllegalStateException異常

3、Prepared狀態(tài)
MediaPlayer準(zhǔn)備好了

  • prepare():同步方法,調(diào)用這個(gè)方法,MediaPlayer就進(jìn)入Prepared狀態(tài)
  • prepareAsync():異步方法,經(jīng)過Preparing 狀態(tài),在準(zhǔn)備工作結(jié)束之后,進(jìn)入Prepared狀態(tài),會(huì)回調(diào)OnPreparedListener.onPrepared()。

在Prepared狀態(tài)之后,就可以調(diào)用MediaPlayer的一些set方法了,如,setScreenOnWhilePlaying()、setVolume()、setLooping()。

4、Started 狀態(tài),Paused 狀態(tài)
MediaPlayer準(zhǔn)備好之后,調(diào)用start()方法,此時(shí)MediaPlayer就處于Started狀態(tài);調(diào)用pause()方法,MediaPlayer進(jìn)入Paused狀態(tài)。

如果注冊(cè)過OnBufferingUpdateListener,在Started 狀態(tài)時(shí),MediaPlayer就會(huì)回調(diào)onBufferingUpdate()方法,可以使應(yīng)用程序保持跟蹤視頻流的緩沖

5、Stopped 狀態(tài)
當(dāng)MediaPlayer處于Started 、Paused 、Prepared、PlaybackCompleted狀態(tài)下,均可調(diào)用stop()停止MediaPlayer,而處于Stopped狀態(tài)的MediaPlayer要想重新播放,需要通過prepareAsync()(prepare())方法回到Prepared狀態(tài)才可以。

6、PlaybackCompleted狀態(tài)
文件正常播放完畢,而又沒有設(shè)置循環(huán)播放的話就進(jìn)入該狀態(tài),并會(huì)觸發(fā)OnCompletionListener的onCompletion()方法。

7、Error 狀態(tài)
如果由于某種原因MediaPlayer出現(xiàn)了錯(cuò)誤,會(huì)觸發(fā)OnErrorListener.onError()事件,此時(shí)MediaPlayer即進(jìn)入Error狀態(tài)

注意:
1、MediaPlayer會(huì)消耗系統(tǒng)的資源,需要在適當(dāng)?shù)臅r(shí)候把不需要的資源釋放掉。例如,如果在Activity中調(diào)用onStop()方法時(shí),需要釋放MediaPlayer。當(dāng)Activity恢復(fù)或者重新啟動(dòng)時(shí),需要?jiǎng)?chuàng)建一個(gè)新的MediaPlayer并且重新準(zhǔn)備。

釋放MediaPlayer

   mediaPlayer.release(); 
   mediaPlayer = null;

2、SurfaceView

SurfaceView是配合MediaPlayer,將一幀一幀的圖像,顯示在界面上。

指定MediaPlayer顯示圖像

void setDisplay(SurfaceHolder holder)
  • SurfaceHolder可以理解為SurfaceView裝載需要顯示的一幀幀圖像的容器,它可以通過SurfaceHolder.getHolder()方法獲得。
  • SurfaceView,通過雙緩沖的機(jī)制來顯示幀圖像。雙緩沖可以理解為有兩個(gè)線程輪番去 解析視頻流的幀圖像,當(dāng)一個(gè)線程解析完幀圖像后,把圖像渲染到界面中,同時(shí)另一線程開始解析下一幀圖像,使得兩個(gè)線程輪番配合去解析視頻流,以達(dá)到流暢播放的效果。
  • SurfaceView內(nèi)部實(shí)現(xiàn)了雙緩沖的機(jī)制,但是實(shí)現(xiàn)這個(gè)功能是非常消耗系統(tǒng)內(nèi)存的。因?yàn)橐苿?dòng)設(shè)備的局限性,Android在設(shè)計(jì)的時(shí)候規(guī) 定,SurfaceView如果為用戶可見的時(shí)候,創(chuàng)建SurfaceView的SurfaceHolder用于顯示視頻流解析的幀圖片,如果發(fā)現(xiàn) SurfaceView變?yōu)橛脩舨豢梢姷臅r(shí)候,則立即銷毀SurfaceView的SurfaceHolder,以達(dá)到節(jié)約系統(tǒng)資源的目的。所以,需要去維護(hù)一個(gè)SurfaceHolder,需要用到它的一個(gè)回調(diào),SurfaceHolder.Callback()
   public interface Callback {
       public void surfaceCreated(SurfaceHolder holder);
       public void surfaceChanged(SurfaceHolder holder, int format, int width, int height);
       public void surfaceDestroyed(SurfaceHolder holder);
   }

3、使用

   /**
    * todo public
    * 加載視頻
    */
   public void loadAndPlay(String videoUrl){
       this.videoUrl=videoUrl;
       surfaceView.getHolder().setKeepScreenOn(true);
       surfaceView.getHolder().addCallback(new SurfaceViewCallback());
   }


   /**
    * 當(dāng)用戶不可見的時(shí)候 ,SurfaceHolder 就會(huì)銷毀,當(dāng)再次可見的時(shí)候,會(huì)創(chuàng)建新的SurfaceHolder;
    * 使用SurfaceHolder.Callback()維護(hù)一個(gè)SurfaceHolder
    */
   class SurfaceViewCallback implements SurfaceHolder.Callback {
       @Override
       public void surfaceCreated(SurfaceHolder holder) {
           if(mediaPlayer==null){
               mediaPlayer=new MediaPlayer();
               mediaPlayer.setDataSource(videoUrl);
               mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
               mediaPlayer.setOnPreparedListener(this);
               mediaPlayer.setOnBufferingUpdateListener(this);
               mediaPlayer.setOnErrorListener(this);
               mediaPlayer.setOnCompletionListener(new MediaPlayerCompletion());
               mediaPlayer.prepareAsync();
               mediaPlayer.setDisplay(surfaceView.getHolder());
           }
       }

       @Override
       public void surfaceDestroyed(SurfaceHolder holder) {
           isVideoPrepared=false;
           if(mediaPlayer!=null){
               mediaPlayer.release();
               mediaPlayer=null;
           }
         
       }

   }

   /**
    * 視頻準(zhǔn)備好回調(diào)
    */
   @Override
   public void onPrepared(MediaPlayer mp) {
       isVideoPrepared=true;
       mediaPlayer.start();
       mediaPlayer.setScreenOnWhilePlaying(true);
   }

   private boolean isVideoPrepared;

S70326-182808.jpg

Android Multimedia框架總結(jié)(一)MediaPlayer介紹之狀態(tài)圖及生命周期Android Multimedia框架總結(jié)(三)MediaPlayer中創(chuàng)建到setDataSource過程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容