Android播放視頻(三)

來源:互聯網
上載者:User

[java]  package cn.c;  import java.io.File;  import java.io.IOException;  import android.app.Activity;  import android.media.MediaPlayer;  import android.media.MediaPlayer.OnCompletionListener;  import android.media.MediaPlayer.OnErrorListener;  import android.media.MediaPlayer.OnInfoListener;  import android.media.MediaPlayer.OnPreparedListener;  import android.media.MediaPlayer.OnSeekCompleteListener;  import android.media.MediaPlayer.OnVideoSizeChangedListener;  import android.os.Bundle;  import android.os.Environment;  import android.view.Display;  import android.view.SurfaceHolder;  import android.view.SurfaceView;  import android.widget.LinearLayout;  /**  * 利用MidiaPlayer播放視頻  * 涉及到SurfaceView和SurfaceHolder  * MediaPlayer主要用於播放音頻,它沒有提供輸出映像的輸出介面  * 此時我們可用SurfaceView控制項將它與MediaPlayer結合起來  * 就能達到視頻的輸出.如果說SurfaceView是用來繪製(顯示)視頻的  * 那麼SurfaceHolder就是用來控制SurfaceView的  * 流程:  * 1 設定MediaPlayer將要播放的視頻  *   mMediaPlayer.setDataSource(path);  * 2 設定MediaPlayer的視頻輸出介面  *   mMediaPlayer.setDisplay(mSurfaceHolder);  * 3 MediaPlayer進行解碼工作  *   mMediaPlayer.prepareAsync();  * 4 MediaPlayer開始播放   *   mMediaPlayer.start();  */    /**  * 參考資料:http://www.embedu.org/Column/Column503.htm  * 利用MidiaPlayer播放視頻大致的流程:  * 建立播放器對象-->設定需要播放的視頻的來源-->  * 對視頻進行解碼等準備工作-->開始播放-->(暫停/重啟)停止播放  * 對應這些流程,在MediaPlayer中都定義了相關方法;  * 而且,在調用這些方法後,MediaPlayer可以進入不同的狀態.  * 這些方法和狀態都很好理解,讀者可以參照來瞭解.  * 另外,因為在設定播放的視頻的視頻資料來源之後,它需要對其進行解碼(調用prepare()方法)  * 這是一個比較耗時的操作,為了避免應用程式阻止,  * 可以使用它的prepareAsync()方法配合OnPreparedListener監聽器來讓其非同步作業.  * 注意,只有MediaPlayer的準備工作做完後,才能開始播放   * MediaPlayer本身不能顯示視頻內容,它只能控制視頻的播放  * 如果要使用MediaPlayer來播放視頻,還需要配合SurfaceView來顯示視頻  * 且將MediaPlayer中解碼的視頻資料在SurfaceView中播放,需要調用MediaPlayer中的setDisplay()  * 它接受一個SurfaceHolder對象,可將我們用於  * 播放視頻的SurfaceView對應的SurfaceHolder對象作為參數  * 這樣,MediaPlayer和SurfaceView就建立起了關聯.  */    public class MainActivity extends Activity implements   OnCompletionListener,OnErrorListener,OnInfoListener,OnPreparedListener,  OnSeekCompleteListener,OnVideoSizeChangedListener,SurfaceHolder.Callback{      private SurfaceView mSurfaceView;      private SurfaceHolder mSurfaceHolder;      private Display mDisplay;      private MediaPlayer mMediaPlayer;      int videoWidth=0;      int videoHeight=0;            @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.main);          mDisplay=getWindowManager().getDefaultDisplay();          mSurfaceView=(SurfaceView) findViewById(R.id.surfaceView);          mSurfaceHolder=mSurfaceView.getHolder();          //SurfaceHolder是用於管理SurfaceView對象          //那它是怎麼做到管理的呢?即用mSurfaceHolder          //添加回調即addCallback.          //該類實現了SurfaceHolder.Callback介面,所以addCallback(this)          //在SurfaceHolder.Callback介面中一共有三個方法來實現對於          //SurfaceView對象的管理,即:          //surfaceCreated()          //surfaceChanged()          //surfaceDestroyed()          //概況:SurfaceHolder主要作用是監控底層的情況          mSurfaceHolder.addCallback(this);          mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);                    mMediaPlayer=new MediaPlayer();          mMediaPlayer.setOnCompletionListener(this);          mMediaPlayer.setOnErrorListener(this);          mMediaPlayer.setOnInfoListener(this);          mMediaPlayer.setOnPreparedListener(this);          mMediaPlayer.setOnSeekCompleteListener(this);          mMediaPlayer.setOnVideoSizeChangedListener(this);          String path=Environment.getExternalStorageDirectory().getPath()          +File.separator+"Test_Movie.m4v";          try {              //設定MediaPlayer將要播放的視頻              mMediaPlayer.setDataSource(path);          } catch (IllegalArgumentException e) {              e.printStackTrace();              finish();          } catch (IllegalStateException e) {              e.printStackTrace();              finish();          } catch (IOException e) {              e.printStackTrace();              finish();          }      }      //來自於SurfaceHolder.Callback介面      //建立SurfaceView完成時,會調用該方法      public void surfaceCreated(SurfaceHolder holder) {          //設定MediaPlayer的視頻輸出介面          //只顯示音頻而不顯示視頻時可不調用這個方法          mMediaPlayer.setDisplay(mSurfaceHolder);          try {              //準備播放,調用mMediaPlayer.prepareAsync();              //方法後會執行覆寫後的              //public void onPrepared(MediaPlayer mp)              //注意:              //也可調用prepare()解碼,但為一個同步的操作              mMediaPlayer.prepareAsync();          } catch (Exception e) {              e.printStackTrace();              finish();          }      }      //來自於SurfaceHolder.Callback介面      //當SurfaceView的寬度,高度或其他參數發生變化時,會調用該方法      public void surfaceChanged(SurfaceHolder holder,               int format, int width,int height) {                }      //來自於SurfaceHolder.Callback介面      //當SurfaceView摧毀時,會調用該方法      public void surfaceDestroyed(SurfaceHolder holder) {                }      //來自於MediaPlayer.OnVideoSizeChangedListener介面      //當視頻的寬度或高度發生變化時調用該方法      public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {                }      //來自於MediaPlayer.OnSeekCompleteListener介面      public void onSeekComplete(MediaPlayer mp) {                }      //來自於MediaPlayer.OnPreparedListener介面      //一旦調用該方法,MediaPlayer就進入了"準備就緒"      //狀態,準備開始播放.      //此處可用於動態設定SurfaceView的寬和高!!!      public void onPrepared(MediaPlayer mediaPlayer) {          videoWidth=mediaPlayer.getVideoWidth();          videoHeight=mediaPlayer.getVideoHeight();          if (videoWidth > mDisplay.getWidth()|| videoHeight > mDisplay.getHeight()) {              float heightRatio = (float) videoHeight/ (float) mDisplay.getHeight();              float widthRatio = (float) videoWidth/ (float) mDisplay.getWidth();              if (heightRatio > 1 || widthRatio > 1) {                  if (heightRatio > widthRatio) {                      videoHeight = (int) Math.ceil((float) videoHeight/ (float) heightRatio);                      videoWidth = (int) Math.ceil((float) videoWidth/ (float) heightRatio);                  } else {                      videoHeight = (int) Math.ceil((float) videoHeight/ (float) widthRatio);                      videoWidth = (int) Math.ceil((float) videoWidth/ (float) widthRatio);                  }              }          }          //設定SurfaceView的寬和高          mSurfaceView.setLayoutParams          (new LinearLayout.LayoutParams(videoWidth,videoHeight));          //MediaPlayer開始播放          mediaPlayer.start();      }      //來自於MediaPlayer.OnInfoListener介面      //當出現關於播放媒體的特定資訊或者需要發出警告的時候      //將調用該方法      //比如開始緩衝、緩衝結束、下載速度變化(該行待驗證)      //小結:這些Info都是以MediaPlayer.MEDIA_INFO_開頭的      public boolean onInfo(MediaPlayer mp, int what, int extra) {          if (what==MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING) {              //音頻和視頻資料不正確地交錯時將出現該提示資訊.在一個              //正確交錯的媒體檔案中,音頻和視頻樣本將依序排列,從而              //使得播放可以有效和平穩地進行          }          if (what==MediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {              //當媒體不能正確定位時將出現該提示資訊.              //此時意味著它可能是一個線上流          }          if (what==MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING) {              //當裝置無法播放視頻時將出現該提示資訊              //比如視頻太複雜或者碼率過高          }          if (what==MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {              //當新的中繼資料可用時將出現該提示資訊          }          if (what==MediaPlayer.MEDIA_INFO_UNKNOWN) {              //其餘不可知提示資訊          }          return false;      }      //來自於MediaPlayer.OnErrorListener介面      //MediaPlayer發生錯誤時會調用該方法      //只有如下這三種錯誤.      //小結:這些錯誤都是以MediaPlayer.MEDIA_ERROR.開頭的      public boolean onError(MediaPlayer mp, int what, int extra) {          if (what==MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {              System.out.println("第一種錯誤");          }          if (what==MediaPlayer.MEDIA_ERROR_SERVER_DIED) {              System.out.println("第二種錯誤");          }          if (what==MediaPlayer.MEDIA_ERROR_UNKNOWN) {              System.out.println("第三種錯誤");          }          return false;      }      //來自於MediaPlayer.OnCompletionListener介面      //當MediaPlayer播放完檔案時,會調用該方法.      //此時可以進行一些其他的操作比如:播放下一個視頻      public void onCompletion(MediaPlayer mp) {             finish();              }  }   

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.