2011-10-23 14 views
14

Qualcuno sa se è possibile rilevare quando un VideoView sta eseguendo il buffering?Rileva se un VideoVisualizzazione sta effettuando il buffering

Voglio mostrare una ProgressDialog quando il video è in fase di buffering.

Finora ho provato a utilizzare un OnPreparedListener, ma funziona solo quando il video viene caricato per la prima volta. Se un video è in riproduzione e l'utente sposta la barra di scorrimento in un punto diverso, il video è ancora "preparato" anche se è in fase di buffering.

Ho anche provato (so che questo è terribile) un AsyncThread che solo occupato aspetta su 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... 
} 
} 

Questo non funziona perché non appena si chiama start() un VideoView sembra essere considerato giocare anche se è in buffering.

L'unica soluzione che posso pensare è la creazione di una classe di tipo VideoView personalizzata in modo da poter accedere alla sua istanza MediaPlayer.

Qualche idea? Grazie per aver letto.

+1

Il problema è risolto? –

risposta

1

Sto lavorando a qualcosa di simile e non ho potuto trovare una soluzione eccezionale. Alcune soluzioni interessanti sono state pubblicate here che dovresti controllare se non le hai viste.

In ogni caso, ho trovato il seguente trucco che è stato suggerito nel thread precedente e funziona bene per ora.

@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

Questo non può essere utilizzato all'interno di una VideoView. – Rui

+2

Quindi utilizzalo con MediaPlayer che ottieni da VideoView.setOnPreparedListener –

9

Sono arrivato con il seguente trucco per non implementare un VideoView personalizzato. L'idea è di controllare ogni 1 secondo se la posizione corrente è la stessa di 1 secondo prima. Se lo è, il video è in buffering. In caso contrario, il video sta davvero giocando.

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

videomessaggio è solo un TextView con il testo "buffering ..." posto al centro della mia VideoView.

+3

Sembra un pezzo di codice ricorsivo di memoria esponenziale-consumatore. Non è vero? – Behnam

7

Dal API level 17, è ora possibile accedere al InfoListener dal 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

Non dovremmo nascondere i progressi sul buffer fine? –

4

seguito il codice mostrerà una finestra di dialogo buffer ogni volta che il VideoView è buffering.

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