使用VideoView播放视频

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<? xml  version = "1.0"  encoding = "utf-8" ?>
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
     android:layout_width = "match_parent"
     android:layout_height = "match_parent"
     android:orientation = "vertical"  >
    
     < EditText
         android:id = "@+id/et_path"
         android:layout_width = "match_parent"
         android:layout_height = "wrap_content"
         android:text = "/sdcard/ykzzldx.mp4"  />
    
     < SeekBar
         android:id = "@+id/seekBar"
         android:layout_width = "match_parent"
         android:layout_height = "wrap_content"  />
    
     < LinearLayout
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:orientation = "horizontal"  >
    
         < Button
             android:id = "@+id/btn_play"
             android:layout_width = "0dip"
             android:layout_height = "wrap_content"
             android:layout_weight = "1"
             android:text = "播放"  />
    
         < Button
             android:id = "@+id/btn_pause"
             android:layout_width = "0dip"
             android:layout_height = "wrap_content"
             android:layout_weight = "1"
             android:text = "暂停"  />
    
         < Button
             android:id = "@+id/btn_replay"
             android:layout_width = "0dip"
             android:layout_height = "wrap_content"
             android:layout_weight = "1"
             android:text = "重播"  />
    
         < Button
             android:id = "@+id/btn_stop"
             android:layout_width = "0dip"
             android:layout_height = "wrap_content"
             android:layout_weight = "1"
             android:text = "停止"  />
     </ LinearLayout >
    
     < VideoView
         android:id = "@+id/vv_videoview"
         android:layout_width = "fill_parent"
         android:layout_height = "fill_parent"  />
    
</ LinearLayout >

实现代码:VideoViewActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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

1
2
3
4
5
6
7
8
9
10
11
<? xml  version = "1.0"  encoding = "utf-8" ?>
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
     android:layout_width = "match_parent"
     android:layout_height = "match_parent"
     android:orientation = "vertical"  >
        
< VideoView
         android:id = "@+id/vv_video"
         android:layout_width = "match_parent"
         android:layout_height = "match_parent"  />
</ LinearLayout >

实现代码:ControllerActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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不光为我们增加了控制栏来控制播放、暂停、快进、快退、切换上一视频、切换下一视频,还增加了进度条显示。

总结

本篇博客就讲解了VideoView和MediaController的内容。虽然使用MediaController非常的方便,基本上所有的操作都帮我们封装好了,但是封装即表示不够灵活,必须按照既定的规则去实现。所以一般专业的视频播放应用,还是会使用SurfaceView去完成。


原文出处:http://www.bdqn.cn/news/201311/12100.shtml


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值