Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

Reproduce Audio with Media Player

Hi Im recording audio, reproducing it with Media Player and set the progress update of the audio on a Seek Bar, the problem is that the Audio and the Seek Bar dont reproduce and slide (respectively) smoothly, why is that happening guys?? Here´s my code:

 m = MediaPlayer.create(getActivity(), Uri.parse(outputFile));

                try {
                    //m.setDataSource(outputFile);
                    int duration = m.getDuration();
                    seekBarAudio.setMax(duration);
                    Log.d("Duration", "The duration of the audio is: " + duration);
                    //saveInParse();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                try {
                    m.prepare();
                    Toast.makeText(getActivity(), "Playing Audio ", Toast.LENGTH_SHORT).show();
                } catch (IOException | IllegalStateException e) { // This avoids to play a short audio.
                    e.printStackTrace();
                }
                m.start();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            while (m.isPlaying()) {
                                try {
                                    Thread.sleep(100);
                                    currentPosition = m.getCurrentPosition();
                                } catch (InterruptedException e) {
                                    return;
                                } catch (Exception e) {
                                    return;
                                }
                                currentPosition = m.getCurrentPosition();
                                final int total = m.getDuration();
                                m.seekTo(currentPosition);
                                seekBarAudio.setMax(total); //song duration
                                seekBarAudio.setProgress(currentPosition);  //for current song progress
                            }
                        }
                    }).start();

and here's the code of the Seek Bar:

seekBarAudio = (SeekBar) v.findViewById(R.id.seekBarAudio);

        seekBarAudio.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                position = m.getCurrentPosition();
                position = progress;
                m.seekTo(position);
                seekBarAudio.setProgress(position);  //for current song progress
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }

1 Answer

In the thread where you update the SeekBar to the current position of the media player, you are also telling the MediaPlayer go to a new position with seekTo(). Ideally the only thing that thread needs to do is call setProgress() to update the bar; every thing else is redundant.

The other issue is this:

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
                                          // note this last parameter^^^^^^^^

From the docs: "Notification that the progress level has changed. Clients can use the fromUser parameter to distinguish user-initiated changes from those that occurred programmatically." So this listener will be called whenever the progress is changed, whether by user input or calling setProgress(). And that setProgress() call you put at the end? It will cause onProgressChanged() to be called in an infinite loop. A version taking user vs. program changes into account would be:

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
   if (fromUser) {
      m.seekTo(progress);
   }
}

wow!!!!! you were totally true!!!!!!!!!!!!!!!!!!!!!!!!!!! Thank you so mucho!!! <3 !!!