有人知道是否可以检测VideoView何时缓冲?
我希望在视频缓冲时显示ProgressDialog。
到目前为止,我尝试使用OnPreparedListener,但这仅在首次加载视频时才有效。如果正在播放视频并且用户将滑动条移动到另一个点,则视频仍然“准备好”,即使它正在缓冲。
我也试过(我知道这很糟糕)AsyncThread只是忙着等待isPlaying():
private class BufferTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void...voids) {
final VideoView videoView = (VideoView)findViewById(R.id.video);
while (!videoView.isPlaying()) { }
return null;
}
protected void onPostExecute(Void v) {
// Hide the dialog here...
}
}
这不起作用,因为只要你调用start(),即使它正在缓冲,VideoView也会被视为正在播放。
我能想到的唯一解决方案是构建自定义VideoView类型类,以便我可以访问其MediaPlayer实例。
有什么想法吗?谢谢你的阅读。
答案 0 :(得分:12)
从API level 17开始,您现在可以从MediaPlayer访问InfoListener:
final MediaPlayer.OnInfoListener onInfoToPlayStateListener = new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
mProgressBar.setVisibility(View.GONE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
mProgressBar.setVisibility(View.VISIBLE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
mProgressBar.setVisibility(View.VISIBLE);
return true;
}
}
return false;
}
});
mVideoView.setOnInfoListener(onInfoToPlayStateListener);
答案 1 :(得分:10)
我带来了以下hack,以便不实现自定义VideoView。如果当前位置与之前的1秒相同,则每1秒检查一次。如果是,则视频正在缓冲。如果没有,视频真的在播放。
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
int duration = videoView.getCurrentPosition();
if (old_duration == duration && videoView.isPlaying()) {
videoMessage.setVisibility(View.VISIBLE);
} else {
videoMessage.setVisibility(View.GONE);
}
old_duration = duration;
handler.postDelayed(runnable, 1000);
}
};
handler.postDelayed(runnable, 0);
videoMessage只是一个TextView,文本“Buffering ...”放在我的VideoView的中心。
答案 2 :(得分:3)
以下代码将在每次VideoView缓冲时显示缓冲对话框。
final ProgressDialog bufferingDialog;
bufferingDialog = ProgressDialog.show(context,
"Buffering", "Please wait", true, true);
VideoView videoView;
videoView = (VideoView) findViewById(R.id.video_view);
videoView.setVideoPath(path);
videoView.setMediaController(new MediaController(context));
videoView.requestFocus();
videoView.start();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START)
bufferingDialog.show();
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END)
bufferingDialog.dismiss();
return false;
}
});
}
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
bufferingDialog.dismiss();
return false;
}
});
答案 3 :(得分:3)
VideoView showing Progress while Buffering
Below code worked for me
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(final MediaPlayer mp) {
mp.start();
mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
progressBar.setVisibility(View.GONE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
progressBar.setVisibility(View.VISIBLE);
return true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
progressBar.setVisibility(View.GONE);
return true;
}
}
return false;
}
});
}
});
答案 4 :(得分:1)
我正在做类似的事情,但无法提出一个很好的解决方案。发布了一些有趣的解决方案here,如果您还没有看到它们,请查看。
无论如何,我想出了上面提到的以下黑客攻击,现在可以正常工作。
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
float temp = ((float)mp.getCurrentPosition() / (float)mp.getDuration())*100;
if(Math.abs(percent - temp) < 1) {
buffer_fail++;
if(buffer_fail == 15) {
//buffer failed
}
}
}
答案 5 :(得分:0)
这对我有用
boolean b_start = true;
boolean b_end = true;
final MediaPlayer.OnInfoListener onInfoToPlayStateListener = new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START: {
dialog1.setVisibility(View.GONE);
b_end = false;
b_start = false;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_START: {
if (b_start){
dialog1.setVisibility(View.VISIBLE);
}
b_start = true;
}
case MediaPlayer.MEDIA_INFO_BUFFERING_END: {
if(b_end){
dialog1.setVisibility(View.VISIBLE);
}
b_end = true;
}
}
return false;
}
};
videoView.setOnInfoListener(onInfoToPlayStateListener);