安卓视频播放器(VideoView)
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标签,如果让该标签的父级标签为FramLayout,设置相应属性就可以实现视频居中播放和默认的播放控件 MediaController 在视频内显示效果,还可以在VidoView标签上层加入TextView标签,实现视频播放的一些状态显示,如播放卡顿、切换播放、播放失败等的提示信息显示。另外可加入ImageView标签,即可显示图片或gif图,更具人性化。
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>
需要添加的权限:
因为视频来源可以是网络或者本地,所以需要动态申请网络访问权限和本地文件读写权限,文件读写权限一般还需要手动获取
<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的一系列操作。
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();
视频播放进阶
利用FrameLayout的层叠效果,实现视频控件面板在视频层之上显示,利用视频控件的点击事件,实现视频点击监听然后改变视频控制面板的隐藏和显示。其他的视频播放控制代码基本以上相似
布局文件改变:
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>
寻找播放控件标签:
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