SeekBar y reproductor multimedia en Android

Tengo un reproductor y grabador simple. Todo funciona bien pero tiene un solo problema. Quiero agregar la barra de búsqueda para ver el progreso en la reproducción de registros y usar esta barra de búsqueda para establecer el lugar desde donde el jugador debería jugar. Tengo progreso pero sin efecto. Este es el código:

package com.example.recorder; import java.io.IOException; import android.app.Activity; import android.media.MediaPlayer; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; public class MainActivity extends Activity implements OnSeekBarChangeListener { private static final String LOG_TAG = "AudioRecordTest"; private static String mFileName = null; private SeekBar seekBar; private MediaRecorder mRecorder = null; private Button startRecord, startPlaying, stopPlaying; private MediaPlayer mPlayer = null; private void onRecord(boolean start) { if (start) { startRecording(); } else { stopRecording(); } } private void startPlaying() { if(mPlayer != null && mPlayer.isPlaying()){ mPlayer.pause(); } else if(mPlayer != null){ mPlayer.start(); }else{ mPlayer = new MediaPlayer(); try { mPlayer.setDataSource(mFileName); mPlayer.prepare(); mPlayer.start(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } } } private void stopPlaying() { mPlayer.release(); mPlayer = null; startPlaying.setText("Start playing"); } private void pausePlaying(){ if(mPlayer.isPlaying()){ mPlayer.pause(); } else { mPlayer.start(); } } private void startRecording() { mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mRecorder.setOutputFile(mFileName); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); try { mRecorder.prepare(); } catch (IOException e) { Log.e(LOG_TAG, "prepare() failed"); } mRecorder.start(); } private void stopRecording() { mRecorder.stop(); mRecorder.release(); mRecorder = null; } public MainActivity() { mFileName = Environment.getExternalStorageDirectory().getAbsolutePath(); mFileName += "/audiorecordtest.3gp"; } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.activity_main); startPlaying = (Button) findViewById(R.id.buttonStartPlay); stopPlaying = (Button) findViewById(R.id.buttonStopPlaying); startRecord = (Button) findViewById(R.id.buttonStartRecord); seekBar = (SeekBar) findViewById(R.id.seekBar); startRecord.setOnClickListener(new OnClickListener() { boolean mStartRecording = true; @Override public void onClick(View v) { onRecord(mStartRecording); if (mStartRecording) { startRecord.setText("Stop recording"); } else { startRecord.setText("Start recording"); } mStartRecording = !mStartRecording; } }); startPlaying.setOnClickListener(new OnClickListener() { boolean mStartPlaying = true; @Override public void onClick(View v) { //onPlay(mStartPlaying); startPlaying(); if (mStartPlaying) { startPlaying.setText("Stop playing"); } else { startPlaying.setText("Start playing"); } mStartPlaying = !mStartPlaying; } }); stopPlaying.setOnClickListener(new OnClickListener() { boolean mStartPlaying = true; @Override public void onClick(View v) { stopPlaying(); } }); } @Override public void onPause() { super.onPause(); if (mRecorder != null) { mRecorder.release(); mRecorder = null; } if (mPlayer != null) { mPlayer.release(); mPlayer = null; } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(fromUser){ mPlayer.seekTo(progress); seekBar.setProgress(progress); } else{ // the event was fired from code and you shouldn't call player.seekTo() } } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } } 

¿Alguna idea sobre cómo usar la barra de búsqueda para ver el progreso y establecer el lugar desde el registro debería jugarse?

Para crear una ‘conexión’ entre SeekBar y MediaPlayer , primero necesita obtener su duración máxima de grabación actual y establecerla en su barra de búsqueda.

 mSeekBar.setMax(mFileDuration); // where mFileDuration is mMediaPlayer.getDuration(); 

Después de inicializar su MediaPlayer y, por ejemplo, presionar el botón de reproducción, debe crear el manejador y el post runnable para que pueda actualizar su SeekBar (en el UI thread la UI thread ) con la posición actual de su MediaPlayer como esta:

 private Handler mHandler = new Handler(); //Make sure you update Seekbar on UI thread MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { if(mMediaPlayer != null){ int mCurrentPosition = mMediaPlayer.getCurrentPosition(); mSeekBar.setProgress(mCurrentPosition); } mHandler.postDelayed(this, 1000); } }); 

y actualiza ese valor cada segundo.

Si necesita actualizar la posición del MediaPlayer mientras el usuario arrastra su SeekBar , debe agregar OnSeekBarChangeListener a su SeekBar y hacerlo allí:

  mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(mMediaPlayer != null && fromUser){ mMediaPlayer.seekTo(progress * 1000); } } }); 

¡Y eso debería hacer el truco! 🙂

EDITAR: Una cosa que he notado en tu código, no lo hagas:

 public MainActivity() { mFileName = Environment.getExternalStorageDirectory().getAbsolutePath(); mFileName += "/audiorecordtest.3gp"; } 

hacer todas las inicializaciones en su onCreate(); , no crees constructores de tu Activity .

Utilicé este tutorial con éxito, es realmente fácil de entender: http://www.androidhive.info/2012/03/android-building-audio-player-tutorial/

Esta es la parte interesante:

 /** * Update timer on seekbar * */ public void updateProgressBar() { mHandler.postDelayed(mUpdateTimeTask, 100); } /** * Background Runnable thread * */ private Runnable mUpdateTimeTask = new Runnable() { public void run() { long totalDuration = mp.getDuration(); long currentDuration = mp.getCurrentPosition(); // Displaying Total Duration time songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration)); // Displaying time completed playing songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration)); // Updating progress bar int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration)); //Log.d("Progress", ""+progress); songProgressBar.setProgress(progress); // Running this thread after 100 milliseconds mHandler.postDelayed(this, 100); } }; /** * * */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { } /** * When user starts moving the progress handler * */ @Override public void onStartTrackingTouch(SeekBar seekBar) { // remove message Handler from updating progress bar mHandler.removeCallbacks(mUpdateTimeTask); } /** * When user stops moving the progress hanlder * */ @Override public void onStopTrackingTouch(SeekBar seekBar) { mHandler.removeCallbacks(mUpdateTimeTask); int totalDuration = mp.getDuration(); int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration); // forward or backward to certain seconds mp.seekTo(currentPosition); // update timer progress again updateProgressBar(); } 

Después de inicializar su MediaPlayer y SeekBar , puede hacer esto:

  Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { mSeekBar.setProgress(mMediaPlayer.getCurrentPosition()); } },0,1000); 

Esto actualiza SeekBar cada segundo (1000 ms)

Y para actualizar MediaPlayer , si el usuario arrastra SeekBar , debe agregar OnSeekBarChangeListener a su SeekBar :

 mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { mMediaPlayer.seekTo(i); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); 

FELIZ CODIFICACIÓN !!!

mira esto, debes dar argumentos en msecs, no solo enviar el progress a seekTo (int)

y también verifique esto getCurrentPostion () y getDuration () .

Puede hacer algunas calcuaciones, es decir, convertir el progress en mseg como msce = (progress/100)*getDuration() luego seekTo(msec)

De lo contrario, tengo una idea fácil, no necesita cambiar ningún código, simplemente agregue seekBar.setMax(mPlayer.getDuration()) una vez que su reproductor esté preparado.

y aquí está el enlace exactamente lo que desea buscar barra de actualización

  int pos = 0; yourSeekBar.setMax(mPlayer.getDuration()); 

Después de que inicie su MediaPlayer es decir, mplayer.start()

Prueba este código

 while(mPlayer!=null){ try { Thread.sleep(1000); pos = mPlayer.getCurrentPosition(); } catch (Exception e) { //show exception in LogCat } yourSeekBar.setProgress(pos); } 

Antes de agregar este código, debe crear el recurso xml para SeekBar y usarlo en su clase de Activity de su onCreate() ur onCreate() .

Para agregar a la respuesta de @ hardartcore.

  1. En lugar de llamar a postDelayed en un controlador, lo mejor sería obtener devoluciones de llamada del MediaPlayer durante la reproducción y luego actualizar el seekBar con el progreso.

  2. Además, pause su MediaPlayer en onStartTrackingTouch(SeekBar seekBar) del OnSeekBarChangeListener y luego onStopTrackingTouch(SeekBar seekBar) .

Según declaraciones anteriores, para un mejor rendimiento, también puede agregar una condición if

 if (player.isPlaying() { handler.postDelayed(..., 1000); } 

El siguiente código funcionó para mí.

Creé un método para la barra de búsqueda

 @Override public void onPrepared(MediaPlayer mediaPlayer) { mp.start(); getDurationTimer(); getSeekBarStatus(); } //Creating duration time method public void getDurationTimer(){ final long minutes=(mSongDuration/1000)/60; final int seconds= (int) ((mSongDuration/1000)%60); SongMaxLength.setText(minutes+ ":"+seconds); } //creating a method for seekBar progress public void getSeekBarStatus(){ new Thread(new Runnable() { @Override public void run() { // mp is your MediaPlayer // progress is your ProgressBar int currentPosition = 0; int total = mp.getDuration(); seekBar.setMax(total); while (mp != null && currentPosition < total) { try { Thread.sleep(1000); currentPosition = mp.getCurrentPosition(); } catch (InterruptedException e) { return; } seekBar.setProgress(currentPosition); } } }).start(); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { int progress=0; @Override public void onProgressChanged(final SeekBar seekBar, int ProgressValue, boolean fromUser) { if (fromUser) { mp.seekTo(ProgressValue);//if user drags the seekbar, it gets the position and updates in textView. } final long mMinutes=(ProgressValue/1000)/60;//converting into minutes final int mSeconds=((ProgressValue/1000)%60);//converting into seconds SongProgress.setText(mMinutes+":"+mSeconds); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } 

SongProgress y SongMaxLength son TextView para mostrar la duración de la canción y la duración de la canción.

Esto funciona para mí:

 seekbarPlayer.setMax(mp.getDuration()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { if(mp != null){ seekbarPlayer.setProgress(mp.getCurrentPosition()); } mHandler.postDelayed(this, 1000); } }); 

Pruebe este Código:

 public class MainActivity extends AppCompatActivity { MediaPlayer mplayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //You create MediaPlayer variable ==> set the path and start the audio. mplayer = MediaPlayer.create(this, R.raw.example); mplayer.start(); //Find the seek bar by Id (which you have to create in layout) // Set seekBar max with length of audio // You need a Timer variable to set progress with position of audio final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar); seekBar.setMax(mplayer.getDuration()); new Timer().scheduleAtFixedRate(new TimerTask() { @Override public void run() { seekBar.setProgress(mplayer.getCurrentPosition()); } }, 0, 1000); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // Update the progress depending on seek bar mplayer.seekTo(progress); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } 

Código en Kotlin:

 var updateSongTime = object : Runnable { override fun run() { val getCurrent = mediaPlayer?.currentPosition startTimeText?.setText(String.format("%d:%d", TimeUnit.MILLISECONDS.toMinutes(getCurrent?.toLong() as Long), TimeUnit.MILLISECONDS.toSeconds(getCurrent?.toLong()) - TimeUnit.MINUTES.toSeconds( TimeUnit.MILLISECONDS.toMinutes(getCurrent?.toLong())))) seekBar?.setProgress(getCurrent?.toInt() as Int) Handler().postDelayed(this, 1000) } } 

Para cambiar el archivo de audio del reproductor de medios cada segundo

Si el usuario arrastra la barra de búsqueda, se puede usar el siguiente fragmento de código

 Statified.seekBar?.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) { if(b && Statified.mediaPlayer != null){ Statified.mediaPlayer?.seekTo(i) } } override fun onStartTrackingTouch(seekBar: SeekBar) {} override fun onStopTrackingTouch(seekBar: SeekBar) {} })