前言



 



  之前有讲过如何使用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 
  
 
  

      
  
 
  

    复制代码 
  
 
  

      1 package cn.bgxt.videoviewdemo; 
  
 
  

      2  
  
 
  

      3 import java.io.File; 
  
 
  

      4  
  
 
  

      5 import android.app.Activity; 
  
 
  

      6 import android.media.MediaPlayer; 
  
 
  

      7 import android.media.MediaPlayer.OnCompletionListener; 
  
 
  

      8 import android.media.MediaPlayer.OnErrorListener; 
  
 
  

      9 import android.os.Bundle; 
  
 
  

     10 import android.util.Log; 
  
 
  

     11 import android.view.View; 
  
 
  

     12 import android.widget.Button; 
  
 
  

     13 import android.widget.EditText; 
  
 
  

     14 import android.widget.SeekBar; 
  
 
  

     15 import android.widget.Toast; 
  
 
  

     16 import android.widget.VideoView; 
  
 
  

     17 import android.widget.SeekBar.OnSeekBarChangeListener; 
  
 
  

     18  
  
 
  

     19 public class VideoViewActivity extends Activity { 
  
 
  

     20     private final String TAG = "main"; 
  
 
  

     21     private EditText et_path; 
  
 
  

     22     private Button btn_play, btn_pause, btn_replay, btn_stop; 
  
 
  

     23     private SeekBar seekBar; 
  
 
  

     24     private VideoView vv_video; 
  
 
  

     25     private boolean isPlaying; 
  
 
  

     26  
  
 
  

     27     @Override 
  
 
  

     28     protected void onCreate(Bundle savedInstanceState) { 
  
 
  

     29         // TODO Auto-generated method stub 
  
 
  

     30         super.onCreate(savedInstanceState); 
  
 
  

     31         setContentView(R.layout.activity_videoview); 
  
 
  

     32  
  
 
  

     33         seekBar = (SeekBar) findViewById(R.id.seekBar); 
  
 
  

     34         et_path = (EditText) findViewById(R.id.et_path); 
  
 
  

     35         vv_video = (VideoView) findViewById(R.id.vv_videoview); 
  
 
  

     36  
  
 
  

     37         btn_play = (Button) findViewById(R.id.btn_play); 
  
 
  

     38         btn_pause = (Button) findViewById(R.id.btn_pause); 
  
 
  

     39         btn_replay = (Button) findViewById(R.id.btn_replay); 
  
 
  

     40         btn_stop = (Button) findViewById(R.id.btn_stop); 
  
 
  

     41  
  
 
  

     42         btn_play.setOnClickListener(click); 
  
 
  

     43         btn_pause.setOnClickListener(click); 
  
 
  

     44         btn_replay.setOnClickListener(click); 
  
 
  

     45         btn_stop.setOnClickListener(click); 
  
 
  

     46  
  
 
  

     47         // 为进度条添加进度更改事件 
  
 
  

     48         seekBar.setOnSeekBarChangeListener(change); 
  
 
  

     49     } 
  
 
  

     50  
  
 
  

     51     private OnSeekBarChangeListener change = new OnSeekBarChangeListener() { 
  
 
  

     52  
  
 
  

     53         @Override 
  
 
  

     54         public void onStopTrackingTouch(SeekBar seekBar) { 
  
 
  

     55             // 当进度条停止修改的时候触发 
  
 
  

     56             // 取得当前进度条的刻度 
  
 
  

     57             int progress = seekBar.getProgress(); 
  
 
  

     58             if (vv_video != null && vv_video.isPlaying()) { 
  
 
  

     59                 // 设置当前播放的位置 
  
 
  

     60                 vv_video.seekTo(progress); 
  
 
  

     61             } 
  
 
  

     62         } 
  
 
  

     63  
  
 
  

     64         @Override 
  
 
  

     65         public void onStartTrackingTouch(SeekBar seekBar) { 
  
 
  

     66  
  
 
  

     67         } 
  
 
  

     68  
  
 
  

     69         @Override 
  
 
  

     70         public void onProgressChanged(SeekBar seekBar, int progress, 
  
 
  

     71                 boolean fromUser) { 
  
 
  

     72  
  
 
  

     73         } 
  
 
  

     74     }; 
  
 
  

     75     private View.OnClickListener click = new View.OnClickListener() { 
  
 
  

     76  
  
 
  

     77         @Override 
  
 
  

     78         public void onClick(View v) { 
  
 
  

     79  
  
 
  

     80             switch (v.getId()) { 
  
 
  

     81             case R.id.btn_play: 
  
 
  

     82                 play(0); 
  
 
  

     83                 break; 
  
 
  

     84             case R.id.btn_pause: 
  
 
  

     85                 pause(); 
  
 
  

     86                 break; 
  
 
  

     87             case R.id.btn_replay: 
  
 
  

     88                 replay(); 
  
 
  

     89                 break; 
  
 
  

     90             case R.id.btn_stop: 
  
 
  

     91                 stop(); 
  
 
  

     92                 break; 
  
 
  

     93             default: 
  
 
  

     94                 break; 
  
 
  

     95             } 
  
 
  

     96         } 
  
 
  

     97     }; 
  
 
  

     98  
  
 
  

     99     protected void play(int msec) { 
  
 
  

    100         Log.i(TAG, " 获取视频文件地址"); 
  
 
  

    101         String path = et_path.getText().toString().trim(); 
  
 
  

    102         File file = new File(path); 
  
 
  

    103         if (!file.exists()) { 
  
 
  

    104             Toast.makeText(this, "视频文件路径错误", 0).show(); 
  
 
  

    105             return; 
  
 
  

    106         } 
  
 
  

    107          
  
 
  

    108         Log.i(TAG, "指定视频源路径"); 
  
 
  

    109         vv_video.setVideoPath(file.getAbsolutePath()); 
  
 
  

    110         Log.i(TAG, "开始播放"); 
  
 
  

    111         vv_video.start(); 
  
 
  

    112          
  
 
  

    113         // 按照初始位置播放 
  
 
  

    114         vv_video.seekTo(msec); 
  
 
  

    115         // 设置进度条的最大进度为视频流的最大播放时长 
  
 
  

    116         seekBar.setMax(vv_video.getDuration()); 
  
 
  

    117  
  
 
  

    118         // 开始线程,更新进度条的刻度 
  
 
  

    119         new Thread() { 
  
 
  

    120  
  
 
  

    121             @Override 
  
 
  

    122             public void run() { 
  
 
  

    123                 try { 
  
 
  

    124                     isPlaying = true; 
  
 
  

    125                     while (isPlaying) { 
  
 
  

    126                         // 如果正在播放,没0.5.毫秒更新一次进度条 
  
 
  

    127                         int current = vv_video.getCurrentPosition(); 
  
 
  

    128                         seekBar.setProgress(current); 
  
 
  

    129  
  
 
  

    130                         sleep(500); 
  
 
  

    131                     } 
  
 
  

    132                 } catch (Exception e) { 
  
 
  

    133                     e.printStackTrace(); 
  
 
  

    134                 } 
  
 
  

    135             } 
  
 
  

    136         }.start(); 
  
 
  

    137         // 播放之后设置播放按钮不可用 
  
 
  

    138         btn_play.setEnabled(false); 
  
 
  

    139  
  
 
  

    140         vv_video.setOnCompletionListener(new OnCompletionListener() { 
  
 
  

    141  
  
 
  

    142             @Override 
  
 
  

    143             public void onCompletion(MediaPlayer mp) { 
  
 
  

    144                 // 在播放完毕被回调 
  
 
  

    145                 btn_play.setEnabled(true); 
  
 
  

    146             } 
  
 
  

    147         }); 
  
 
  

    148  
  
 
  

    149         vv_video.setOnErrorListener(new OnErrorListener() { 
  
 
  

    150  
  
 
  

    151             @Override 
  
 
  

    152             public boolean onError(MediaPlayer mp, int what, int extra) { 
  
 
  

    153                 // 发生错误重新播放 
  
 
  

    154                 play(0); 
  
 
  

    155                 isPlaying = false; 
  
 
  

    156                 return false; 
  
 
  

    157             } 
  
 
  

    158         }); 
  
 
  

    159     } 
  
 
  

    160  
  
 
  

    161     /** 
  
 
  

    162      * 重新开始播放 
  
 
  

    163      */ 
  
 
  

    164     protected void replay() { 
  
 
  

    165         if (vv_video != null && vv_video.isPlaying()) { 
  
 
  

    166             vv_video.seekTo(0); 
  
 
  

    167             Toast.makeText(this, "重新播放", 0).show(); 
  
 
  

    168             btn_pause.setText("暂停"); 
  
 
  

    169             return; 
  
 
  

    170         } 
  
 
  

    171         isPlaying = false; 
  
 
  

    172         play(0); 
  
 
  

    173  
  
 
  

    174     } 
  
 
  

    175  
  
 
  

    176     /** 
  
 
  

    177      * 暂停或继续 
  
 
  

    178      */ 
  
 
  

    179     protected void pause() { 
  
 
  

    180         if (btn_pause.getText().toString().trim().equals("继续")) { 
  
 
  

    181             btn_pause.setText("暂停"); 
  
 
  

    182             vv_video.start(); 
  
 
  

    183             Toast.makeText(this, "继续播放", 0).show(); 
  
 
  

    184             return; 
  
 
  

    185         } 
  
 
  

    186         if (vv_video != null && vv_video.isPlaying()) { 
  
 
  

    187             vv_video.pause(); 
  
 
  

    188             btn_pause.setText("继续"); 
  
 
  

    189             Toast.makeText(this, "暂停播放", 0).show(); 
  
 
  

    190         } 
  
 
  

    191     } 
  
 
  

    192  
  
 
  

    193     /* 
  
 
  

    194      * 停止播放 
  
 
  

    195      */ 
  
 
  

    196     protected void stop() { 
  
 
  

    197         if (vv_video != null && vv_video.isPlaying()) { 
  
 
  

    198             vv_video.stopPlayback(); 
  
 
  

    199             btn_play.setEnabled(true); 
  
 
  

    200             isPlaying = false; 
  
 
  

    201         } 
  
 
  

    202     } 
  
 
  

    203 } 
  
 
  

    复制代码 
  
 
  

      效果展示: 
  
 
  

      
  
 
  

      
  
 
  

      
  
 
  

      
  
 
  

      
  
 
  

    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 
  
 
  

      
  
 
  

    复制代码 
  
 
  

     1 package cn.bgxt.videoviewdemo; 
  
 
  

     2  
  
 
  

     3 import java.io.File; 
  
 
  

     4  
  
 
  

     5 import android.app.Activity; 
  
 
  

     6 import android.os.Bundle; 
  
 
  

     7 import android.view.View; 
  
 
  

     8 import android.view.View.OnClickListener; 
  
 
  

     9 import android.widget.MediaController; 
  
 
  

    10 import android.widget.Toast; 
  
 
  

    11 import android.widget.VideoView; 
  
 
  

    12  
  
 
  

    13 public class ControllerActivity extends Activity { 
  
 
  

    14     private VideoView vv_video; 
  
 
  

    15     private MediaController mController; 
  
 
  

    16      
  
 
  

    17     @Override 
  
 
  

    18     protected void onCreate(Bundle savedInstanceState) { 
  
 
  

    19         super.onCreate(savedInstanceState); 
  
 
  

    20         setContentView(R.layout.activity_controller); 
  
 
  

    21         vv_video=(VideoView) findViewById(R.id.vv_video); 
  
 
  

    22         // 实例化MediaController 
  
 
  

    23         mController=new MediaController(this); 
  
 
  

    24         File file=new File("/sdcard/ykzzldx.mp4"); 
  
 
  

    25         if(file.exists()){ 
  
 
  

    26             // 设置播放视频源的路径 
  
 
  

    27             vv_video.setVideoPath(file.getAbsolutePath()); 
  
 
  

    28             // 为VideoView指定MediaController 
  
 
  

    29             vv_video.setMediaController(mController); 
  
 
  

    30             // 为MediaController指定控制的VideoView 
  
 
  

    31             mController.setMediaPlayer(vv_video); 
  
 
  

    32             // 增加监听上一个和下一个的切换事件,默认这两个按钮是不显示的 
  
 
  

    33             mController.setPrevNextListeners(new OnClickListener() { 
  
 
  

    34                  
  
 
  

    35                 @Override 
  
 
  

    36                 public void onClick(View v) {                     
  
 
  

    37                     Toast.makeText(ControllerActivity.this, "下一个",0).show(); 
  
 
  

    38                 } 
  
 
  

    39             }, new OnClickListener() { 
  
 
  

    40                  
  
 
  

    41                 @Override 
  
 
  

    42                 public void onClick(View v) { 
  
 
  

    43                     Toast.makeText(ControllerActivity.this, "上一个",0).show(); 
  
 
  

    44                 } 
  
 
  

    45             }); 
  
 
  

    46         } 
  
 
  

    47     } 
  
 
  

    48 } 
  
 
  

    复制代码



 



  从上面展示的效果可以看出,MediaController不光为我们增加了控制栏来控制播放、暂停、快进、快退、切换上一视频、切换下一视频,还增加了进度条显示。