Mediaplayer actualización de progreso a seekbar no suave?
Estoy trabajando en una aplicación con grabadora y reproductor. Estoy usando mediaplayer para reproducir el archivo .wav grabado y mientras tanto quiero actualizar a un buscador. Todo está funcionando bien Pero mi problema es la actualización de progreso de mediaplayer a seekbar no está sucediendo suavemente, si somos playig un pequeño archivo, el pulgar de la barra de búsqueda salta en segundos o entre.
¿Puede alguien ayudarme con una solución para hacer que busque el progreso en seekbar. Mi código se muestra a continuación. Estoy totlay pegado aquí.
- Diálogo de progreso personalizado Android
- Excepción android.view.WindowLeaked
- Ancho horizontal de la barra de progreso en la barra de acciones
- Cómo mostrar la barra de progreso antes de reproducir el video
- Diálogo de progreso para AsyncTask - Android
mediaPlayerIntiate(); mediaPlayerSetSource(); mMediaPlayer.start(); task = new TimerTask() { @Override public void run() { Graphbar.post(new Runnable() { @Override public void run() { if (mMediaPlayer != null) { if (playButtonState == MediaMode.PLAY) { if (mMediaPlayer.isPlaying()) { Graphbar.setProgress(mMediaPlayer .getCurrentPosition()); mediaPlayerUpdateTimer(mMediaPlayer .getCurrentPosition()); enableRewindandForward(); } } } } }); } }; timer = new Timer(); timer.schedule(task, 0, 8);
- Android: Cómo ocultar el progreso de Seekbar?
- Progreso de la ventana de presentación pero no Progreso de ActionBar (utilizando la biblioteca v7 compat)
- Botón de retroceso de Android y cuadro de diálogo de progreso
- Reexcursión de exoplayer de Android cuando se realiza la búsqueda
- No se puede tomar el progreso en la carga de archivos POST HTTP (Android)
- No puedo ver el progreso de spinner en ProgressDialog en Lollipop
- Android ExoPlayer onProgressChanged
- Temporizador de cuenta atrás Android La barra de progreso circular no coincide con el temporizador
MMediaPlayer.getCurrentPosition () Devuelve el tiempo actual en milisegundos y lo estás actualizando a Seekbar cuya capacidad máxima es 100. Haz una fórmula con longitud de archivo y 100. prueba esta función
MediaPlayer mMediaPlayer = new MediaPlayer(); final SeekBar mSeelBar = new SeekBar(this); final int duration = mMediaPlayer.getDuration(); final int amoungToupdate = duration / 100; Timer mTimer = new Timer(); mTimer.schedule(new TimerTask() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { if (!(amoungToupdate * mSeelBar.getProgress() >= duration)) { int p = mSeelBar.getProgress(); p += 1; mSeelBar.setProgress(p); } } }); }; }, amoungToupdate);
Y este proceso se debe llamar cuando el jugador de medios comienza a jugar. dentro
mediaPlayer.setOnPreparedListener(new OnPreparedListener(){ @Override public void onPrepared(MediaPlayer mp) { **// call here** });
Actualizar
Actualizar 125 veces en segundos no es algo que debas hacer. Aumente su intervalo para actualizar SeekBar. Añadiendo esto después de leer los comentarios de NullPointer
Aquí es cómo manejar el buscador;
mediaPlayer.setOnPreparedListener(new OnPreparedListener(){ @Override public void onPrepared(MediaPlayer mp) { mediaPlayer.start(); new SeekBarHandler().execute(); });
Ahora tengo una tarea Async llamada SeekBarHandler que maneja el buscador como este:
public class SeekBarHandler extends AsyncTask<Void, Void, Void> { @Override protected void onPostExecute(Void result) { Log.d("##########Seek Bar Handler ################","###################Destroyed##################"); super.onPostExecute(result); } @Override protected void onProgressUpdate(Void... values) { seekBar.setProgress(mediaPlayer.getCurrentPosition()); super.onProgressUpdate(values); } @Override protected Void doInBackground(Void... arg0) { while(mediaPlayer.isPlaying()&&isViewOn==true) { try { Thread.sleep(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } onProgressUpdate(); } return null; } }
Ahora en mi onPause, termino el AsyncTask ya que no tiene sentido mantener el hilo en marcha cuando el usuario no puede ver la barra de búsqueda
protected void onPause() { isViewOn=false; super.onPause(); }
Y en onResume inicie el AsyncTaskAgain como este
protected void onResume() { isViewOn=true; new SeekBarHandler().execute(); super.onResume(); }
Como puedes ver, utilizo una bandera booleana isViewOn para comprobar si la vista está activada o no para manejar la barra de búsqueda.
player.prepare(); // or start() ScheduledExecutorService service = Executors.newScheduledThreadPool(1); service.scheduleWithFixedDelay(new Runnable() { @Override public void run() { progressBar.setProgress(player.getCurrentPosition()); } }, 1, 1, TimeUnit.MICROSECONDS);
Seekbar.setProgress () sólo acepta int. Por lo tanto, la mayoría de nosotros tiende a pasar el porcentaje transcurrido a este método. Sin embargo, si necesita una progresión mucho más suave, puede utilizar la duración en milisegundos como MAX. Entonces conseguimos actualizar la progresión del seekbar cada milisegundo. A continuación se muestra un ejemplo y he actualizado cada 15 milisegundos como casi todos los teléfonos Android viene con una tasa de actualización de 60 fps (frames por segundo).
try{ mediaPlayer.start(); seekbar.setProgress(0); seekbar.setMax(mediaPlayer.getDuration()); // Updating progress bar seekHandler.postDelayed(updateSeekBar, 15); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } /** * Background Runnable thread * */ private Runnable updateSeekBar = new Runnable() { public void run() { long totalDuration = mediaPlayer.getDuration(); long currentDuration = mediaPlayer.getCurrentPosition(); // Displaying Total Duration time remaining.setText(""+ milliSecondsToTimer(totalDuration-currentDuration)); // Displaying time completed playing elapsed.setText(""+ milliSecondsToTimer(currentDuration)); // Updating progress bar seekbar.setProgress((int)currentDuration); // Call this thread again after 15 milliseconds => ~ 1000/60fps seekHandler.postDelayed(this, 15); } }; /** * Function to convert milliseconds time to * Timer Format * Hours:Minutes:Seconds * */ public String milliSecondsToTimer(long milliseconds){ String finalTimerString = ""; String secondsString = ""; // Convert total duration into time int hours = (int)( milliseconds / (1000*60*60)); int minutes = (int)(milliseconds % (1000*60*60)) / (1000*60); int seconds = (int) ((milliseconds % (1000*60*60)) % (1000*60) / 1000); // Add hours if there if(hours > 0){ finalTimerString = hours + ":"; } // Prepending 0 to seconds if it is one digit if(seconds < 10) { secondsString = "0" + seconds; }else { secondsString = "" + seconds; } finalTimerString = finalTimerString + minutes + ":" + secondsString; // return timer string return finalTimerString; }
El problema que está experimentando tiene que ver con la forma en que se diseña / implementa SeekBar de Android. Si bien funciona muy bien, estás limitado por una combinación de segmentos utilizados (es decir, seekbar.setMax(int)
) y el tiempo de retardo de tu Handler.
Dicho esto, he subclasificado SeekBar para hacer mi propio SmoothSeekBar que utiliza ViewPropertyAnimators en lugar de un Handler.
Compruébelo aquí: https://github.com/Indatus/Android-SmoothSeekBar