MediaPlayer, ProgressBar

¿Es esta la forma correcta de actualizar una Barra de progreso cuando se reproducen medios? Pensé que habría una devolución de llamada en MediaPlayer, pero no pude encontrarlo.

<code>mediaPlayer.start();
final SeekBar progress = (SeekBar) dialog.findViewById(R.id.seekBar1);
progress.setMax(mediaPlayer.getDuration());
new CountDownTimer(mediaPlayer.getDuration(), 250) {
  public void onTick(long millisUntilFinished) {
    progress.setProgress(progress.getProgress() + 250);
  }
  public void onFinish() {}
}.start();
</code>

Atentamente.

Respuestas a la pregunta(3)

La forma más eficiente es usar la respuesta de JRaymond yEventBus

<code>private class MediaObserver implements Runnable {
    private AtomicBoolean stop = new AtomicBoolean(false);
    public void stop() {
        stop.set(true);
    }

    @Override public void run() {
        while (!stop.get()) {
            try {
              if (player.isPlaying())
                 sendMsgToUI(player.getCurrentPosition(),
                             player.getDuration());
            } catch (Exception e){e.printStackTrace();}
            try { 
              Thread.sleep(100);
            } catch (InterruptedException e) { e.printStackTrace(); }
        }
    }
}

private MediaObserver observer = null;

public void runMedia() {
    observer = new MediaObserver();
    new Thread(observer).start();
}

//handles all the background threads things for you
private void sendMsgToUI(int position) {
    ChangingEvent event = new ChangingEvent(position);
    EventBus.getDefault().post(event);
}
</code>

Cambiar la clase Evento se vería algo así:

<code>public class ChangingEvent {
  private int position;

  public ChangingEvent(int position) {
      this.position= position;
  }

  public int getPosition() {
      return position;
  }
}
</code>

y en tu Actividad o Fragmento todo lo que tienes que hacer es

<code>class YouClass extends Activity {
  private EventBus eventBus = EventBus.getDefault();
}

@Override protected void onCreate(Bundle savedInstanceState) {
    //your code
    eventBus.register(this);
}
//eventbus that updates UI
public void onEventMainThread(ChangingEvent event) {
    //seekbar or any other ui element
    seekBar.setProgress(event.getPosition());
}
</code>
 M Penades20 jul. 2015 17:32
Me gusta este enfoque, pero creo que se olvidó de agregar loop / while que hace que se ejecute run () más de una vez
 Fedor Tsyganov21 jul. 2015 03:11
Oh, sí, gracias por notarlo, lo corregiré ahora.

Personalmente, empiezo un hilo que comprueba.getCurrentPosition() cada 200 ms o menos hasta que elonCompletion() evento se dispara:

<code>private class MediaObserver implements Runnable {
  private AtomicBoolean stop = new AtomicBoolean(false);

  public void stop() {
    stop.set(true);
  }

  @Override
  public void run() {
    while (!stop.get()) {
      progress.setProgress(mediaPlayer.getCurrentPosition());
      Thread.sleep(200);
    }
  }
}

private MediaObserver observer = null;

public void runMedia() {
  mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener{
    @Override
    public void onCompletion(MediaPlayer mPlayer) {
      observer.stop();
      progress.setProgress(mPlayer.getCurrentPosition());
    }
  });
  observer = new MediaObserver();
  mediaPlayer.start();
  new Thread(observer).start();
}
</code>
 JRaymond26 feb. 2013 20:06
@ tobi.b En este caso, probablemente no sea necesario, ya que solo el hilo del observador está manipulando la variable de detención y está usando asignación pura. Sin embargo, en general, el uso de tipos atómicos previene las colisiones de hilos cuando varios hilos intentan manipular una variable al mismo tiempo, por lo que es un hábito
 pouzzler03 abr. 2012 22:43
Lo siento, señalé la otra respuesta, ya que es más útil para todos, aunque por ahora me quedaré con mis cosas que no son ICS.
 tobi.b26 feb. 2013 19:01
¿Por qué usaste una operación atómica para el bool en tu ejemplo?
 matdev03 nov. 2015 15:53
En aras de la precisión, el método MediaPlayer.OnCompletionListener se llama onCompletion (), no onComplete ()
 pouzzler03 abr. 2012 22:08
El temporizador no bloquea la interfaz de usuario, así que supongo que está en otro hilo. Así que supongo que es lo mismo. Desearía ser lo suficientemente inteligente como para resolver estas cosas.
 JRaymond03 abr. 2012 22:32
@pouzzler demasiado tarde ... pero de nada :)
 pouzzler03 abr. 2012 22:27
Ah no es necesario, lo entiendo. Gracias :)
 JRaymond03 abr. 2012 22:19
El temporizador de cuenta atrás de @pouzzler se ejecuta en otro hilo, la única diferencia es que no utiliza el progreso real. Voy a escribir un ejemplo con hilos
 pouzzler03 abr. 2012 22:36
El mismo problema que antes, usé tu sugerencia ... con CountDownTimer: progress.setProgress (mediaPlayer.getCurrentPosition ()); - Todavía no tengo idea de cuál es la mejor;) Y a la cama para mí y mis preguntas filosóficas.
Solución de preguntas

Echa un vistazo aandroid.widget.MediaController, tiene una barra de progreso.

Usan un manejador que se llama a sí mismo recursivamente si es apropiado. Puede configurar el retraso como quiera que quiera que se actualice la barra de progreso.

Tenga en cuenta que el usuario puede mostrar u ocultar el controlador, así como arrastrarlo y, por supuesto, el video puede detenerse. Estos son los motivos de los diversos controles (!mDragging && mShowing && mVideoView.isPlaying()) antes de otra llamada recursiva para actualizar la barra.

<code>protected Handler mHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        int pos;
        switch (msg.what)
        {
            // ...

            case SHOW_PROGRESS:
                pos = setProgress();
                if (!mDragging && mShowing && mVideoView.isPlaying())
                {
                    msg = obtainMessage(SHOW_PROGRESS);
                    sendMessageDelayed(msg, 1000 - (pos % 1000));
                }
                break;

             // ...
        }
    }
};
</code>

Para empezar a utilizarlo:

<code>mHandler.sendEmptyMessage(SHOW_PROGRESS);
</code>

Se detendrá solo, pero debe cancelar la última solicitud pendiente utilizando:

<code>mHandler.removeMessages(SHOW_PROGRESS);
</code>
 astromme19 mar. 2017 20:23
El segundo enlace se ha ido debido a una eliminación de DMCA:github.com/OESF/OHA-Android-4.0.1_r1.0
 pouzzler03 abr. 2012 22:43
Gracias, precisamente, por lo que estaba buscando.
 Peter Ajtai03 abr. 2012 23:16
@pouzzler - de nada! Ver la clase MediaController es excelente para darle ideas sobre cómo hacer un controlador personalizado.

Su respuesta a la pregunta