安卓视频播放器(VideoView)

时间:2020-12-20 09:23:16

VideoView是安卓自带的视频播放器类,该类集成有显示和控制两大部分,在布局文件中添加VideoView然后在java文件中简单的调用控制命令,即可实现本地或者网络视频的播放。本章实现视频的居中播放、网络视频播放、本地视频播放、视频卡顿监听、网络连接错误监听、视频外自定义视频控件、视频内自定义视频控件等。

 

支持的格式:flv、3gp、mp4

 

类的一些重要方法

void start();                 //开始播放

void pause();              //暂停

void resume();           //重新播放,使用时需要在本句后加上开始播放

void seekTo(int msec);       //从第几毫秒开始播放

void stopPlayback();          //停止播放并释放资源

int getCurrentPosition();    //获取当前播放的位置。

int getDuration();               //获取当前播放视频的总长度。

void setVideoPath(String path);    //以文件路径的方式设置VideoView播放的视频源。

void setVideoURI(Uri uri);            //以Uri的方式设置VideoView播放的视频源,可以是网络Uri或本地Uri

void isPlaying();                           //当前VideoView是否在播放视频

setMediaController(MediaController controller);                               //设置MediaController控制器

setOnCompletionListener(MediaPlayer.onCompletionListener l);     //监听播放完成的事件

setOnErrorListener(MediaPlayer.OnErrorListener l);                        //监听播放发生错误时候的事件

setOnPreparedListener(MediaPlayer.OnPreparedListener l);          //监听视频装载完成的事件

setOnInfoListener(new MediaPlayer.OnInfoListener(){});                 //视频卡顿监听

 

实现简单的视频播放

安卓视频播放器(VideoView)                     安卓视频播放器(VideoView)                        安卓视频播放器(VideoView)

布局文件:

实现视频播放重要在于VideoView标签,如果让该标签的父级标签为FramLayout,设置相应属性就可以实现视频居中播放和默认的播放控件 MediaController 在视频内显示效果,还可以在VidoView标签上层加入TextView标签,实现视频播放的一些状态显示,如播放卡顿、切换播放、播放失败等的提示信息显示。另外可加入ImageView标签,即可显示图片或gif图,更具人性化。

安卓视频播放器(VideoView)安卓视频播放器(VideoView)
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:paddingBottom="0dp"
 7     android:paddingLeft="0dp"
 8     android:paddingRight="0dp"
 9     android:orientation="vertical"
10     android:paddingTop="0dp"
11     tools:context="com.example.videodong.MainActivity">
12 
13     <TextView
14         android:layout_width="wrap_content"
15         android:layout_height="wrap_content"
16         android:text="视频播放器:\n"
17         android:textSize="15dp"
18         android:id="@+id/textView" />
19     <FrameLayout
20         android:layout_width="match_parent"
21         android:background="@color/colorBlack"
22         android:layout_height="300dp">
23        <VideoView
24         android:layout_width="match_parent"
25         android:layout_gravity="center"
26         android:layout_height="300dp"
27         android:id="@+id/videoView"
28         />
29 
30         <TextView
31             android:layout_width="wrap_content"
32             android:layout_height="wrap_content"
33             android:textSize="15dp"
34             android:text="点击播放"
35             android:textColor="@color/colorWhite"
36             android:id="@+id/vv_text"
37             android:layout_gravity="center" />
38     </FrameLayout>
39 
40     <ProgressBar
41         android:id="@+id/vv_bar"
42         style="?android:attr/progressBarStyleHorizontal"
43         android:layout_width="match_parent"
44         android:layout_height="wrap_content"/>
45 
46         <TextView
47             android:layout_width="wrap_content"
48             android:text="时间轴为:0.00/000"
49             android:id="@+id/vv_starttime"
50             android:layout_height="wrap_content" />
51 
52 
53      <LinearLayout
54          android:layout_width="match_parent"
55          android:orientation="horizontal"
56          android:layout_gravity="center"
57          android:layout_height="wrap_content">
58          <TextView
59              android:layout_width="wrap_content"
60              android:layout_weight="1"
61              android:layout_height="wrap_content" />
62          <Button
63              android:layout_width="wrap_content"
64              android:text="开始"
65              android:id="@+id/vv_start"
66              android:layout_height="wrap_content" />
67          <Button
68              android:layout_width="wrap_content"
69              android:text="暂停"
70              android:id="@+id/vv_pause"
71              android:layout_height="wrap_content" />
72          <Button
73              android:layout_width="wrap_content"
74              android:text="重播"
75              android:id="@+id/vv_restart"
76              android:layout_height="wrap_content" />
77          <Button
78              android:layout_width="wrap_content"
79              android:text="下一个"
80              android:id="@+id/vv_next"
81              android:layout_height="wrap_content" />
82          
83      </LinearLayout>
84     <TextView
85         android:layout_width="wrap_content"
86         android:id="@+id/vv_state"
87         android:layout_height="wrap_content" />
88 </LinearLayout>
View Code

需要添加的权限:

因为视频来源可以是网络或者本地,所以需要动态申请网络访问权限和本地文件读写权限,文件读写权限一般还需要手动获取

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

寻找到VideoView控件:

vv=(VideoView)findViewById(R.id.videoView);

视频预装完成监听:

1 //视频准备完成时进入
2 vv.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
3             @Override
4             public void onPrepared(MediaPlayer mp) {
5                 //设置屏幕提示信息为空
6                 vv_text.setText("");
7             }
8 });

视频播放完成监听:

 1 vv.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
 2             @Override
 3             public void onCompletion(MediaPlayer mp) {
 4                 String strres="播放完成";
 5                 //判断视频的总长度与当前长度是否在误差区间内
 6                 if(Math.abs(vv.getDuration()-vv.getCurrentPosition())>1000){
 7 
 8                     strres="播放错误,可能无网络连接";
 9 
10                 }
11                 //设置屏幕提示信息
12                 vv_text.setText(strres);
13 
14             }
15 });

视频播放错误监听:

 1 vv.setOnErrorListener(new MediaPlayer.OnErrorListener() {
 2             @Override
 3             public boolean onError(MediaPlayer mp, int what, int extra) 
 4            {
 5                //设置屏幕显示信息
 6                 vv_text.setText("视频未知错误");
 7 
 8                 return false;
 9             }
10  });

视频卡顿和停止卡顿监听:

 1 vv.setOnInfoListener(new MediaPlayer.OnInfoListener(){
 2             @Override
 3             public boolean onInfo(MediaPlayer mp, int what, int extra){
 4 
 5                 switch(what){
 6                     case MediaPlayer.MEDIA_INFO_BUFFERING_START:
 7                         //设置屏幕显示信息,开始卡顿
 8                         vv_text.setText("视频卡顿,加载中.....");
 9                         break ;
10                     case MediaPlayer.MEDIA_INFO_BUFFERING_END:
11                         //设置屏幕显示信息,卡顿结束
12                         vv_text.setText("");
13                         break ;
14                 }
15              return true;
16             }
17 }) ;

设置播放资源:

1 //本地文件
2 vv.setVideoPath(Environment.getExternalStorageDirectory()+"/dongxiaodong/kk1.mp4");
3 
4 //URL形式,支持本地URL和网络URL
5 //vv.setVideoURI(Uri.parse("https://www.bilibili.com/video/xxxxx"));
6        
7 //设置自带的播放控件
8 //vv.setMediaController(new MediaController(this));

播放开始按钮监听:

 1 //开始播放视频按钮
 2 vv_start.setOnClickListener(new View.OnClickListener() {
 3             @Override
 4             public void onClick(View v) {
 5                 
 6                 //设置屏幕显示信息
 7                 vv_text.setText("");
 8 
 9                 //开始播放
10                 vv.start();
11 
12             }
13 });

播放暂停按钮监听:

 1 //暂停播放视频按钮
 2 vv_pause.setOnClickListener(new View.OnClickListener() {
 3             @Override
 4             public void onClick(View v) {
 5 
 6                 //设置屏幕显示信息
 7                 vv_text.setText("视频暂停中");
 8 
 9                 //暂停视频播放
10                 vv.pause();
11 
12             }
13 });

重新播放按钮监听:

 1 //重新播放视频
 2 vv_restart.setOnClickListener(new View.OnClickListener() {
 3             @Override
 4             public void onClick(View v) {
 5                 //设置屏幕显示信息
 6                 vv_text.setText("正在重新播放中,请稍等");
 7 
 8                 //设置时间轴显示为0
 9                 vv_starttime.setText("时间轴为:0.00/0.00");
10 
11                 //设置进度条显示为0
12                 vv_bar.setProgress(0);
13                 
14                 //重新播放视频
15                 vv.resume();
16                 vv.start();
17 
18             }
19 });

播放下一个视频监听:

 1 vv_next.setOnClickListener(new View.OnClickListener() {
 2             @Override
 3             public void onClick(View v) {
 4                 //设置屏幕显示信息
 5                 vv_text.setText("正在切换,请稍等");
 6 
 7                 //设置时间轴为0
 8                 vv_starttime.setText("时间轴为:0.00/0.00");
 9 
10                 //设置进度条为0
11                 vv_bar.setProgress(0);
12                 
13                 //停止播放
14                 vv.pause();//暂停
15                 vv.stopPlayback();//停止播放并释放资源
16 
17                 //得到下一个视频的资源
18                 if(nextbool){
19                     nextbool=false;
20                     //网络资源,该url已经过期
21                     vv.setVideoURI(Uri.parse("http://193.112.87.88/video/xx.flv"));
22                 } else {
23                     nextbool=true;
24                     //本地资源
25                     vv.setVideoPath(Environment.getExternalStorageDirectory()+"/dongxiaodong/kk1.mp4");
26                 }
27 
28                 //开始播放下一个
29                 vv.start();
30 
31             }
32 });

时间轴时间显示和进度条更新实现:

时间轴时间显示计算将在后文给出解释,另外 %02d 可以实现自动补零效果,runOnUiThread可以在普通线程中进入UI线程,可以实现UI的一系列操作。

安卓视频播放器(VideoView)安卓视频播放器(VideoView)
 1 new Thread(new Runnable() {
 2             @Override
 3             public void run() {
 4                 while (true){
 5                     //延时1秒
 6                     try {
 7                         Thread.sleep(1);
 8                     } catch (InterruptedException e) {
 9                         e.printStackTrace();
10                     }
11 
12                     //进入主线程更新UI
13                     runOnUiThread(new Runnable() {
14                         @Override
15                         public void run() {
16                             if(vv.isPlaying()) {
17                                  
18                                 //获取到视频播放进度
19                                 int maxx=vv.getDuration();
20                                 int progress=vv.getCurrentPosition();
21 
22                                 //设置进度条信息
23                                 vv_bar.setMax(maxx);
24                                 vv_bar.setProgress(progress);
25 
26                                 //得到时间轴字符串
27                                 String strtime=String.format("时间轴为:%02d:%02d/%02d:%02d", (progress % 3600000) / 60000,(progress % 60000 ) / 1000, (maxx % 3600000) / 60000,(maxx % 60000 ) / 1000);
28                                 //显示时间轴信息
29                                 vv_starttime.setText(strtime);
30 
31                             }
32                         }
33                     });
34                     }
35 
36                 }
37  }).start();
View Code

 

视频播放进阶

利用FrameLayout的层叠效果,实现视频控件面板在视频层之上显示,利用视频控件的点击事件,实现视频点击监听然后改变视频控制面板的隐藏和显示。其他的视频播放控制代码基本以上相似

                          安卓视频播放器(VideoView)                                       安卓视频播放器(VideoView)            

 布局文件改变:

安卓视频播放器(VideoView)安卓视频播放器(VideoView)
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:layout_width="match_parent"
 5     android:layout_height="match_parent"
 6     android:paddingBottom="0dp"
 7     android:paddingLeft="0dp"
 8     android:paddingRight="0dp"
 9     android:orientation="vertical"
10     android:paddingTop="0dp"
11     tools:context="com.example.videodong.MainActivity">
12 
13     <TextView
14         android:layout_width="wrap_content"
15         android:layout_height="wrap_content"
16         android:text="视频播放器:\n"
17         android:textSize="15dp"
18         android:id="@+id/textView" />
19     <FrameLayout
20         android:layout_width="match_parent"
21         android:background="@color/colorBlack"
22         android:layout_height="230dp">
23        <VideoView
24         android:layout_width="match_parent"
25         android:layout_gravity="center"
26         android:layout_height="230dp"
27         android:id="@+id/videoView"
28         />
29         <FrameLayout
30             android:layout_width="match_parent"
31             android:layout_gravity="bottom"
32             android:id="@+id/vv_framel"
33             android:layout_height="wrap_content">
34             <ImageView
35                 android:layout_width="match_parent"
36                 android:background="@color/colorWhite"
37                 android:alpha="0.5"
38                 android:layout_height="match_parent" />
39         <LinearLayout
40             android:layout_width="match_parent"
41             android:orientation="vertical"
42 
43             android:layout_height="wrap_content">
44             <ProgressBar
45                 android:id="@+id/vv_bar"
46                 style="?android:attr/progressBarStyleHorizontal"
47                 android:layout_width="match_parent"
48                 android:layout_height="wrap_content"/>
49             <LinearLayout
50                 android:layout_width="match_parent"
51                 android:orientation="horizontal"
52                 android:layout_gravity="center"
53                 android:layout_height="wrap_content">
54                 <TextView
55                     android:layout_width="wrap_content"
56                     android:text="时间轴为:0.00/000"
57                     android:id="@+id/vv_starttime"
58                     android:layout_weight="1"
59                     android:layout_height="wrap_content" />
60                 <Button
61                     android:layout_width="wrap_content"
62                     android:text="开始"
63                     style="?android:attr/buttonStyleSmall"
64                     android:id="@+id/vv_start"
65                     android:layout_height="wrap_content" />
66                 <Button
67                     android:layout_width="wrap_content"
68                     android:text="暂停"
69                     android:id="@+id/vv_pause"
70                     style="?android:attr/buttonStyleSmall"
71                     android:layout_height="wrap_content" />
72                 <Button
73                     android:layout_width="wrap_content"
74                     android:text="重播"
75                     style="?android:attr/buttonStyleSmall"
76                     android:id="@+id/vv_restart"
77                     android:layout_height="wrap_content" />
78                 <Button
79                     android:layout_width="wrap_content"
80                     android:text="下一个"
81                     style="?android:attr/buttonStyleSmall"
82                     android:id="@+id/vv_next"
83                     android:layout_height="wrap_content" />
84 
85             </LinearLayout>
86         </LinearLayout>
87         </FrameLayout>
88 
89         <TextView
90             android:layout_width="wrap_content"
91             android:layout_height="wrap_content"
92             android:textSize="15dp"
93             android:text="点击播放"
94             android:textColor="@color/colorWhite"
95             android:id="@+id/vv_text"
96             android:layout_gravity="center" />
97     </FrameLayout>
98 </LinearLayout>
View Code

寻找播放控件标签:

vv_framel=(FrameLayout)findViewById(R.id.vv_framel);

设置视频播放控件点击事件监听: 

 1 vv.setOnClickListener(new View.OnClickListener() {
 2     @Override
 3     public void onClick(View v) {
 4         //判断是否是显示
 5         if(vv_framel.getVisibility()==View.VISIBLE)
 6 
 7             //隐藏视频播放控件
 8             vv_framel.setVisibility(View.INVISIBLE);
 9 
10         else
11 
12             //显示视频播放控件
13             vv_framel.setVisibility(View.VISIBLE);
14 
15     }
16 });

 

内容补充:

视频播放时间轴时间计算:

如果只知道毫秒数,如何转换为对应的时、分、秒,因为1秒为1000毫秒,1分钟为60秒,1小时为60分,所以如果求秒则需要去掉分钟的值,如果求分钟则需要去掉小时的值。

得到秒:【(t % (60*1000) ) / 1000】

得到分:【(t % (60*60*1000)) / (60*1000)】

得到时:【(t / (60*60*1000))】

 

源码资源下载:点我下载

 


 参考:

https://www.jianshu.com/p/0c3ef72c20d1?from=timeline&isappinstalled=0

https://www.cnblogs.com/tangs/articles/5463347.html

https://blog.csdn.net/qq_30983519/article/details/54407122

https://blog.csdn.net/qq_29272491/article/details/80475788