2011-10-23 17 views
14

Czy ktoś wie, czy można wykryć buforowanie wideo?Wykrywanie, czy VideoVIew buforuje

Chcę pokazać ProgressDialog, gdy wideo buforuje.

Do tej pory próbowałem używać OnPreparedListener, ale działa tylko wtedy, gdy wideo jest ładowane po raz pierwszy. Jeśli wideo jest odtwarzane, a użytkownik przesuwa pasek szorowania w inne miejsce, film jest nadal "przygotowany", mimo że jest buforowany.

Próbowałem również (wiem, że to jest straszne) AsyncThread że właśnie zajęty czeka na 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... 
} 
} 

To nie działa, ponieważ tak szybko, jak to nazywasz początek (i) VideoView wydaje Uważa się, że gra, nawet jeśli jest buforowana.

Jedyne rozwiązanie, jakie mogę wymyślić to zbudowanie niestandardowej klasy typu VideoView, aby móc uzyskać dostęp do jej instancji MediaPlayer.

Wszelkie pomysły? Dziękuje za przeczytanie.

+1

Czy rozwiązano problem? –

Odpowiedz

1

Pracuję nad czymś podobnym i nie mogę wymyślić świetnego rozwiązania. Niektóre ciekawe rozwiązania zostały opublikowane here, które powinieneś sprawdzić, jeśli ich nie widziałeś.

W każdym razie, wymyśliłem następujący hack, który został wskazany w powyższym wątku i działa dobrze na teraz.

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

To nie może być używane w wideoView. – Rui

+2

Tak więc użyj go z MediaPlayer, który otrzymałeś z VideoView.setOnPreparedListener –

9

Przyszedłem z następującym hackerem, aby nie zaimplementować niestandardowego VideoView. Chodzi o to, aby sprawdzać co 1 sekundę, czy aktualna pozycja jest taka sama jak 1 sekundę wcześniej. Jeśli tak, wideo jest buforowane. Jeśli nie, wideo naprawdę gra.

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 to po prostu TextView z tekstem "Buforowanie ..." umieszczonym w centrum mojego VideoView.

+3

To wygląda jak rekurencyjny kawałek pamięci wykładniczej-konsumenta. Czyż nie? – Behnam

7

Od API level 17 można teraz uzyskać dostęp do InfoListener z 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); 
+1

Czy nie powinniśmy ukrywać postępu po zakończeniu buforowania? –

4

następujący kod pojawi się okno dialogowe buforujące każdym razem VideoView jest buforowanie.

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; 
     } 
    });