Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android播放視頻(二)

Android播放視頻(二)

編輯:關於Android編程

[java]   package cn.c;   import java.io.File;   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.MotionEvent;   import android.view.SurfaceHolder;   import android.view.SurfaceView;   import android.widget.LinearLayout;   import android.widget.MediaController;   import android.widget.MediaController.MediaPlayerControl;   /**   * 參考資料: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就建立起了關聯.   *    * MediaPlayer播放視頻步驟   * 1 設置MediaPlayer將要播放的視頻   *   mMediaPlayer.setDataSource(path);   * 2 設置MediaPlayer的視頻輸出界面   *   mMediaPlayer.setDisplay(mSurfaceHolder);   * 3 MediaPlayer解碼   *   mMediaPlayer.prepareAsync()且結合   *   public void onPrepared(MediaPlayer mediaPlayer)   * 4 MediaPlayer開始播放   *   mediaPlayer.start();   *    *    */      public class MainActivity extends Activity implements    OnCompletionListener,OnErrorListener,OnInfoListener,OnPreparedListener,   OnSeekCompleteListener,OnVideoSizeChangedListener,SurfaceHolder.Callback,MediaPlayerControl{       private SurfaceView mSurfaceView;       private SurfaceHolder mSurfaceHolder;       private MediaController mMediaController;       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 (Exception e) {               e.printStackTrace();               finish();           }           mMediaController=new MediaController(MainActivity.this);       }              @Override       public boolean onTouchEvent(MotionEvent event) {           if (mMediaController.isShowing()) {               mMediaController.hide();           } else {              mMediaController.show();           }           return false;       }              //來自於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准備好之後才可以對           //MediaController進行設置和使用           mMediaController.setMediaPlayer(this);           mMediaController.setAnchorView(findViewById(R.id.mainView));           mMediaController.setEnabled(true);           mMediaController.show();           //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();               }              //以下方法均來自MediaPlayerControl接口       public void start() {           mMediaPlayer.start();       }       public void pause() {           if (mMediaPlayer.isPlaying()) {               mMediaPlayer.pause();           }       }       public int getDuration() {           return mMediaPlayer.getDuration();       }       public int getCurrentPosition() {           return mMediaPlayer.getCurrentPosition();       }       public void seekTo(int pos) {           mMediaPlayer.seekTo(pos);       }       public boolean isPlaying() {           return mMediaPlayer.isPlaying();       }       public int getBufferPercentage() {           // TODO Auto-generated method stub           return 0;       }       public boolean canPause() {           return true;       }       public boolean canSeekBackward() {           return true;       }       public boolean canSeekForward() {           return true;       }             }  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved