实现功能:播放上下视频,暂停,停止,重新播放,列表循环播放
用到的权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />直接贴代码吧
package com.fvideoview_android.view; import android.content.Context; import android.media.MediaPlayer; import android.os.Build; import android.os.Handler; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.VideoView; import com.danikula.videocache.HttpProxyCacheServer; import com.fvideoview_android.MyApplication; import com.fvideoview_android.R; import com.fvideoview_android.bean.VideoBean; import com.fvideoview_android.utils.ToastHelper; import java.util.List; public class MVideoView extends RelativeLayout { private Context context; private VideoView videoView; private TextView tvTips; private List<VideoBean> videoBeanList; private int currentPlayPosition = 0; private HttpProxyCacheServer proxy; //视频播放的进度 private int videoPosition = 0; private MVideoListener mVideoListener; private ProgressBar pbBar; //判断是否为停止 停止则重新播放 private boolean isStop = false; public MVideoView(Context context) { this(context, null); } public MVideoView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MVideoView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; init(); } public void init() { View view = LayoutInflater.from(context).inflate(R.layout.mvideoview_layout, this, false); initView(view); initVideoView(); addView(view); } //默认显示 public void isShowProgressBar(boolean isShow) { pbBar.setVisibility(isShow ? View.VISIBLE : View.GONE); } public void setVideoList(List<VideoBean> list) { if (list != null) { videoBeanList = list; } } private void initView(View view) { videoView = (VideoView) view.findViewById(R.id.videoView); tvTips = (TextView) view.findViewById(R.id.tvTips); pbBar = (ProgressBar) view.findViewById(R.id.pbBar); } public void initVideoView() { //设置自带的播放控件 // videoView.setMediaController(new MediaController(context)); //视频加载完成,准备好播放视频的回调 videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { //设置回调 mVideoListener.onPrepared(currentPlayPosition, mp); //设置屏幕提示信息为空 tvTips.setText(""); //设置进度条为0 pbBar.setProgress(0); //进度条显示 openProgressCheck(); //设置 MediaPlayer 的 OnSeekComplete 监听 mp.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() { @Override public void onSeekComplete(MediaPlayer mp) { // seekTo 方法完成时的回调 if (!mp.isPlaying()) { videoView.start(); } } }); } }); //视频完成回调 videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { //关闭检测 colseProgressCheck(); //设置回调 mVideoListener.onCompletion(currentPlayPosition, mp); String strres = ""; //判断视频的总长度与当前长度是否在误差区间内 if (Math.abs(videoView.getDuration() - videoView.getCurrentPosition()) > 1000) { strres = "播放错误,可能无网络连接"; } //设置屏幕提示信息 tvTips.setText(strres); //是否设置回调,否:自动播放list内容 if (mVideoListener == null) { videoLoopPlay(); } } }); videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { colseProgressCheck(); String errorStr = ""; switch (what) { case MediaPlayer.MEDIA_ERROR_SERVER_DIED: errorStr = "网络服务错误"; break; case MediaPlayer.MEDIA_ERROR_UNKNOWN: switch (extra) { case MediaPlayer.MEDIA_ERROR_IO: errorStr = "网络文件错误"; break; case MediaPlayer.MEDIA_ERROR_TIMED_OUT: errorStr = "网络超时"; break; } errorStr = "网络服务错误"; break; } //设置回调 mVideoListener.onError(currentPlayPosition, mp, what, extra, errorStr); //设置屏幕显示信息 tvTips.setText(errorStr); //延迟一秒播放下个视频 Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { videoLoopPlay(); } }, 1000); return true; } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { videoView.setOnInfoListener(new MediaPlayer.OnInfoListener() { @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { switch (what) { case MediaPlayer.MEDIA_INFO_BUFFERING_START: //设置屏幕显示信息,开始卡顿 tvTips.setText("加载中..."); break; case MediaPlayer.MEDIA_INFO_BUFFERING_END: //设置屏幕显示信息,卡顿结束 tvTips.setText(""); break; } return true; } }); } } //首次播放视频 public void videoFirstStart() { currentPlayPosition = 0; if (videoBeanList != null && videoBeanList.size() > 0) { videoStart(videoBeanList.get(0).getUrl()); } } //播放视频 public void videoStart(String url) { if (proxy == null) { proxy = MyApplication.getProxy(getContext().getApplicationContext()); } if (videoView.isPlaying()) { //停止播放释放 videoStopPlayback(); } String videoUrl = proxy.getProxyUrl(url); videoView.setVideoPath(videoUrl);//播放的是代理服务器返回的url,已经进行了封装处理 videoView.findFocus(); videoView.start(); } //播放视频 public void videoStart() { tvTips.setText(""); //判断是否停止视频 if (isStop) { if (videoView.isPlaying()) { //停止播放并释放资源 videoStopPlayback(); } videoStart(videoBeanList.get(currentPlayPosition).getUrl()); } else { if (!videoView.isPlaying()) { //是否继续上次进度,有时无效,setOnSeekCompleteListener if (videoPosition != 0) { videoView.seekTo(videoPosition); } else { videoView.start(); } } } isStop = false; } //暂停视频 public void videoPause() { tvTips.setText("视频暂停中"); if (!isStop) { // 先判断是否正在播放 if (videoView.isPlaying()) { // 如果正在播放我们就先保存这个播放位置 videoPosition = videoView.getCurrentPosition(); videoView.pause(); } } } //视频停止 public void videoStop() { tvTips.setText("视频停止中"); isStop = true; if (videoView.isPlaying()) { videoStopPlayback(); videoPosition = 0; } } //是否运行 public boolean isPlaying() { return videoView.isPlaying(); } //停止播放并释放资源 public void videoStopPlayback() { videoView.pause();//暂停 //当调用stopPlayback(),再点击start无效 videoView.stopPlayback();//停止播放并释放资源 } //销毁视频 public void videoDestroy() { if (videoView != null) { videoView.suspend(); } } //上一个视频 public void videoPrevious() { if (videoBeanList != null && videoBeanList.size() > 0) { if (currentPlayPosition == 0) { ToastHelper.ShowToast("没有上条视频", context); } else { tvTips.setText("正在切换,请稍等"); if (currentPlayPosition <= 0) { currentPlayPosition = 0; } else { currentPlayPosition--; } colseProgressCheck(); videoStart(videoBeanList.get(currentPlayPosition).getUrl()); } } else { ToastHelper.ShowToast("视频列表为空", context); } } //下一个视频 public void videoNext() { if (videoBeanList != null && videoBeanList.size() > 0) { int videoListSize = videoBeanList.size(); //判断是否最后一条视频 if (videoListSize - 1 == currentPlayPosition) { ToastHelper.ShowToast("最后一条视频", context); } else { //设置屏幕显示信息 tvTips.setText("正在切换,请稍等"); if (currentPlayPosition < videoListSize - 1) { currentPlayPosition++; } else { currentPlayPosition = videoListSize - 1; } colseProgressCheck(); videoStart(videoBeanList.get(currentPlayPosition).getUrl()); } } else { ToastHelper.ShowToast("视频列表为空", context); } } //视频循环 public void videoLoopPlay() { int videoListSize = videoBeanList.size(); if (currentPlayPosition != videoListSize - 1) { videoNext(); } else { videoFirstStart(); } } public void setMVideoListener(MVideoListener mVideoListener) { this.mVideoListener = mVideoListener; } public interface MVideoListener { //视频加载完成,准备好播放视频的回调 void onPrepared(int position, MediaPlayer mp); //视频播放完成后的回调 void onCompletion(int position, MediaPlayer mp); //信息回调 void onError(int position, MediaPlayer mp, int what, int extra, String error); } // -------------------------------------进度条检测------------------------------------------------ private static final long HEART_BEAT_RATE = 1 * 1000;//1秒 private Handler mHandler; private Runnable runnable; //开始进度检测 public void openProgressCheck() { if (mHandler == null) { mHandler = new Handler(); } if (runnable == null) { runnable = new Runnable() { @Override public void run() { if (videoView.isPlaying()) { //获取到视频播放进度 int maxx = videoView.getDuration(); int progress = videoView.getCurrentPosition(); //设置进度条信息 pbBar.setMax(maxx); pbBar.setProgress(progress); //得到时间轴字符串 // String strtime=String.format("时间轴为:d:d/d:d", (progress % 3600000) / 60000,(progress % 60000 ) / 1000, (maxx % 3600000) / 60000,(maxx % 60000 ) / 1000); } mHandler.postDelayed(this, HEART_BEAT_RATE); } }; } if (mHandler != null) { mHandler.postDelayed(runnable, HEART_BEAT_RATE); } } //关闭检测 public void colseProgressCheck() { if (runnable != null) { //关闭心跳检测 mHandler.removeCallbacks(runnable); } } }layout使用:
<com.fvideoview_android.view.MVideoView android:id="@+id/mVideoView" android:layout_width="match_parent" android:layout_height="200dp" android:layout_centerInParent="true" android:background="@drawable/video_bg" android:paddingTop="2dp" android:paddingBottom="2dp" />activity中使用:设置监听
mVideoView.setMVideoListener(new MVideoView.MVideoListener() { @Override public void onPrepared(int position, MediaPlayer mp) { LogUtil.i("哈哈--onPrepared:" + position); } @Override public void onCompletion(int position, MediaPlayer mp) { LogUtil.i("哈哈--onCompletion:" + position); // if (position == selectVideoListSize - 1) { // //停止播放并释放资源 // mVideoView.videoStopPlayback(); // OtherActivity.start(context); // } else { // mVideoView.videoLoopPlay(); // } mVideoView.videoLoopPlay(); } @Override public void onError(int position, MediaPlayer mp, int what, int extra, String error) { LogUtil.i("哈哈--onError:" + position); ToastHelper.ShowToast("视频" + (position + 1) + ":" + error, context); } });给videoview设置播放源并播放:
mVideoView.setVideoList(videoBeanList); mVideoView.videoFirstStart(); 下一个视频:mVideoView.videoNext(); 上一个视频:mVideoView.videoPrevious(); 暂停:mVideoView.videoPause(); 播放:mVideoView.videoStart(); 停止:mVideoView.videoStop(); 销毁:mVideoView.videoDestroy();