Обнаруживать, если буферизация видеоизображения

Кто-нибудь знает, можно ли обнаружить, когда 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.

Есть идеи? Спасибо за прочтение.

Solutions Collecting From Web of "Обнаруживать, если буферизация видеоизображения"

Я пришел со следующим хаком, чтобы не реализовывать пользовательский 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.

Начиная с уровня 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); 

Следующий код будет показывать диалог буферизации каждый раз, когда 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; } }); 

Я работаю над чем-то подобным, и не мог придумать отличное решение. Здесь были размещены некоторые интересные решения, которые вы должны проверить, не видели ли вы их.

Во всяком случае, я придумал следующий хак, который намекнул в вышеупомянутой теме и работает нормально.

 @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 } } }