Обнаруживать, будирует ли VideoVIew
Кто-нибудь знает, можно ли обнаружить, когда 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.
Любые идеи? Спасибо за чтение.
Ответы
Ответ 1
Поскольку API-уровень 17, теперь вы можете получить доступ к InfoListener из MediaPlayer:
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);
Ответ 2
Я пришел со следующим хаком, чтобы не реализовывать пользовательский VideoView. Идея состоит в том, чтобы проверять каждую секунду, если текущая позиция совпадает с предыдущей секундой. Если это так, видео буферизуется. Если нет, видео действительно воспроизводится.
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 с текстом "Буферизация...", размещенным в центре моего VideoView.
Ответ 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;
}
});
Ответ 4
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;
}
});
}
});
Ответ 5
Я работаю над чем-то похожим и не могу придумать отличное решение. Некоторые интересные решения были опубликованы здесь, что вы должны проверить, не видели ли вы их.
В любом случае, я придумал следующий хак, который намекнул в вышеупомянутом потоке и работает нормально.
@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
}
}
}
Ответ 6
Это сработало для меня
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);