天天看點

Android--使用VideoView播放視訊以及VideoView的api

前言     之前有講過如何使用SurfaceView配合MediaPlayer播放視訊,其實Android還為開發人員提供了另外一種更簡單的播放視訊媒體的方式,那就是VideoView,本篇部落格就來講講VideoView如何播放視訊,最後将以一個簡單的Demo示範。     本篇部落格的主要内容如下:   VideoView VideoView簡單的Demo MediaController MediaController簡單的Demo     VideoView     VideoView,用于播放一段視訊媒體,它繼承了SurfaceView,位于"android.widget.VideoView",是一個視訊控件。     既然是播放一段視訊,那麼不可避免的要涉及到一些開始、暫停、停止等操作,VideoView也為開發人員提供了對應的方法,這裡簡單介紹一些常用的:   int getCurrentPosition():擷取目前播放的位置。 int getDuration():擷取目前播放視訊的總長度。 isPlaying():目前VideoView是否在播放視訊。 void pause():暫停 void seekTo(int msec):從第幾毫秒開始播放。 void resume():重新播放。 void setVideoPath(String path):以檔案路徑的方式設定VideoView播放的視訊源。 void setVideoURI(Uri uri):以Uri的方式設定VideoView播放的視訊源,可以是網絡Uri或本地Uri。 void start():開始播放。 void stopPlayback():停止播放。 setMediaController(MediaController controller):設定MediaController控制器。 setOnCompletionListener(MediaPlayer.onCompletionListener l):監聽播放完成的事件。 setOnErrorListener(MediaPlayer.OnErrorListener l):監聽播放發生錯誤時候的事件。 setOnPreparedListener(MediaPlayer.OnPreparedListener l)::監聽視訊裝載完成的事件。   上面的一些方法通過方法名就可以了解用途。和MediaPlayer配合SurfaceView播放視訊不同,VideoView播放之前無需編碼裝載視訊,它會在start()開始播放的時候自動裝載視訊。并且VideoView在使用完之後,無需編碼回收資源。       VideoView簡單的Demo     VideoView其實沒有什麼難點,通過它自帶的API方法,即可完成一段視訊的播放,無非就是注意它方法的調用時機即可。下面通過一個簡單的Demo,示範VideoView如何播放一段SD卡上的視訊檔案。在Demo中提供了四個Button,分别表示播放、暫停、重播、停止,并配合進度條顯示。代碼注釋比較完整,細節部分這裡不再累述。     布局代碼:activity_videoview.xml    View Code   實作代碼:VideoViewActivity.java     

package cn.bgxt.videoviewdemo;
  
  import java.io.File;
 
  import android.app.Activity;
  import android.media.MediaPlayer;
  import android.media.MediaPlayer.OnCompletionListener;
  import android.media.MediaPlayer.OnErrorListener;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.View;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.SeekBar;
  import android.widget.Toast;
  import android.widget.VideoView;
  import android.widget.SeekBar.OnSeekBarChangeListener;
  
  public class VideoViewActivity extends Activity {
      private final String TAG = "main";
      private EditText et_path;
      private Button btn_play, btn_pause, btn_replay, btn_stop;
      private SeekBar seekBar;
      private VideoView vv_video;
      private boolean isPlaying;
  
      @Override
     protected void onCreate(Bundle savedInstanceState) {
          // TODO Auto-generated method stub
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_videoview);
 
         seekBar = (SeekBar) findViewById(R.id.seekBar);
         et_path = (EditText) findViewById(R.id.et_path);
         vv_video = (VideoView) findViewById(R.id.vv_videoview);
  
         btn_play = (Button) findViewById(R.id.btn_play);
         btn_pause = (Button) findViewById(R.id.btn_pause);
         btn_replay = (Button) findViewById(R.id.btn_replay);
         btn_stop = (Button) findViewById(R.id.btn_stop);
  
         btn_play.setOnClickListener(click);
         btn_pause.setOnClickListener(click);
         btn_replay.setOnClickListener(click);
         btn_stop.setOnClickListener(click);
  
         // 為進度條添加進度更改事件
          seekBar.setOnSeekBarChangeListener(change);
      }
 
      private OnSeekBarChangeListener change = new OnSeekBarChangeListener() {
 
          @Override
          public void onStopTrackingTouch(SeekBar seekBar) {
             // 當進度條停止修改的時候觸發
              // 取得目前進度條的刻度
              int progress = seekBar.getProgress();
             if (vv_video != null && vv_video.isPlaying()) {
                  // 設定目前播放的位置
                 vv_video.seekTo(progress);
              }
          }
 
          @Override
         public void onStartTrackingTouch(SeekBar seekBar) {
 
         }
  
          @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                  boolean fromUser) {
  
          }
      };
     private View.OnClickListener click = new View.OnClickListener() {
  
          @Override
          public void onClick(View v) {
  
              switch (v.getId()) {
              case R.id.btn_play:
                  play(0);
                  break;
              case R.id.btn_pause:
                 pause();
                  break;
              case R.id.btn_replay:
                  replay();
                  break;
             case R.id.btn_stop:
                  stop();
                  break;
              default:
                  break;
              }
          }
      };
  
      protected void play(int msec) {
        Log.i(TAG, " 擷取視訊檔案位址");
         String path = et_path.getText().toString().trim();
         File file = new File(path);
         if (!file.exists()) {
            Toast.makeText(this, "視訊檔案路徑錯誤", 0).show();
            return;
        }
        
         Log.i(TAG, "指定視訊源路徑");
         vv_video.setVideoPath(file.getAbsolutePath());
         Log.i(TAG, "開始播放");
         vv_video.start();
         
         // 按照初始位置播放
         vv_video.seekTo(msec);
         // 設定進度條的最大進度為視訊流的最大播放時長
         seekBar.setMax(vv_video.getDuration());
 
        // 開始線程,更新進度條的刻度
         new Thread() {
 
             @Override
            public void run() {
                 try {
                     isPlaying = true;
                     while (isPlaying) {
                         // 如果正在播放,沒0.5.毫秒更新一次進度條
                         int current = vv_video.getCurrentPosition();
                         seekBar.setProgress(current);
 
                         sleep(500);
                     }
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
             }
         }.start();
         // 播放之後設定播放按鈕不可用
         btn_play.setEnabled(false);
 
        vv_video.setOnCompletionListener(new OnCompletionListener() {
 
             @Override
             public void onCompletion(MediaPlayer mp) {
                // 在播放完畢被回調
                 btn_play.setEnabled(true);
             }
         });
 
         vv_video.setOnErrorListener(new OnErrorListener() {
 
            @Override
             public boolean onError(MediaPlayer mp, int what, int extra) {
                 // 發生錯誤重新播放
                 play(0);
                 isPlaying = false;
                 return false;
             }
         });
     }
 
     /**
      * 重新開始播放
      */
     protected void replay() {
         if (vv_video != null && vv_video.isPlaying()) {
             vv_video.seekTo(0);
            Toast.makeText(this, "重新播放", 0).show();
             btn_pause.setText("暫停");
            return;
         }
        isPlaying = false;
         play(0);
 
     }
 
     /**
      * 暫停或繼續
      */
     protected void pause() {
         if (btn_pause.getText().toString().trim().equals("繼續")) {
             btn_pause.setText("暫停");
             vv_video.start();
             Toast.makeText(this, "繼續播放", 0).show();
             return;
         }
         if (vv_video != null && vv_video.isPlaying()) {
             vv_video.pause();
             btn_pause.setText("繼續");
             Toast.makeText(this, "暫停播放", 0).show();
        }
     }
 
     /*
      * 停止播放
      */
     protected void stop() {
         if (vv_video != null && vv_video.isPlaying()) {
            vv_video.stopPlayback();
             btn_play.setEnabled(true);
             isPlaying = false;
         }
     }
 }
           

  效果展示:

MediaController     提到VideoView不得不再說一些MediaController。雖然VideoView為我們提供了友善的API用于播放、暫停、停止等操作,但是還是需要我們編碼完成,但是如果使用了MediaController的話,那麼這些操作都可以省去。     MediaController可以用于配合VideoView播放一段視訊,它為VideoView提供一個懸浮的操作欄,在操作欄中可以對VideoView播放的視訊進行控制,預設情況下,會懸浮顯示三秒。它通過MediaController.setMediaPlayer()方法進行指定需要控制的VideoView,但是僅僅這樣是不夠的,MediaController的控制需要類似于雙向控制,MediaController指定控制的VideoView,VideoView還需要指定那個MediaController來控制它,這需要使用VideoView.setMediaController()方法。     下面介紹一下MediaController的一些常用方法;   boolean isShowing():目前懸浮控制欄是否顯示。 void setMediaPlayer(MediaController.MediaPlayerControl player):設定控制的 元件。 void setPrevNextListeners(View.OnClickListener next,View.OnClickListener prev):設定上一個視訊、下一個視訊的切換事件。   通過上面的方法可以看出setMediaPlayer()并非指定的是一個VideoView,而是一個MediaPlayerControl接口,MediaPlayerControl接口内部定義了一些播放相關的播放、暫停、停止等操作,而VideoView實作了MediaPlayerControl。     預設情況下,如果不通過setPrevNextListeners()設定切換視訊的監聽器,MediaController是不會顯示這兩個按鈕的。       MediaController簡單的Demo     上面已經講過MediaController的一些内容,下面通過一個簡單的Demo來示範一下MediaController控制VideoView播放視訊。     布局代碼:activity_controller.xml    View Code   實作代碼:ControllerActivity.java  

package cn.bgxt.videoviewdemo;
 
 import java.io.File;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.MediaController;
 import android.widget.Toast;
 import android.widget.VideoView;
 
 public class ControllerActivity extends Activity {
     private VideoView vv_video;
     private MediaController mController;
     
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_controller);
         vv_video=(VideoView) findViewById(R.id.vv_video);
         // 執行個體化MediaController
         mController=new MediaController(this);
        File file=new File("/sdcard/ykzzldx.mp4");
         if(file.exists()){
             // 設定播放視訊源的路徑
             vv_video.setVideoPath(file.getAbsolutePath());
             // 為VideoView指定MediaController
             vv_video.setMediaController(mController);
             // 為MediaController指定控制的VideoView
             mController.setMediaPlayer(vv_video);
             // 增加監聽上一個和下一個的切換事件,預設這兩個按鈕是不顯示的
             mController.setPrevNextListeners(new OnClickListener() {
                 
                 @Override
                 public void onClick(View v) {                    
                     Toast.makeText(ControllerActivity.this, "下一個",0).show();
                 }
             }, new OnClickListener() {
                 
                 @Override
                 public void onClick(View v) {
                     Toast.makeText(ControllerActivity.this, "上一個",0).show();
                 }
             });
        }
     }
 }
           

  從上面展示的效果可以看出,MediaController不光為我們增加了控制欄來控制播放、暫停、快進、快退、切換上一視訊、切換下一視訊,還增加了進度條顯示。 原文位址: http://www.2cto.com/kf/201312/261877.html