实现功能:播放上下视频,暂停,停止,重新播放,列表循环播放
用到的权限:
<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("时间轴为:%02d:%02d/%02d:%02d", (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();