Search code examples
androidandroid-mediaplayerrunnable

Android report mediaplayer currentposition to progressbar or whatever


In my case I want to stream audio and show its progress on a simple ProgressBar, I couldn't find an event handler for playing progress, all I found on the internet is that i can make a Runnable and fire it on play() as follows

public void fireRunnable()
{
    Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {
            int duration = mediaPlayer.getDuration();
            while( mediaPlayer.isPlaying() )
            {
                Log.v("", mediaPlayer.getCurrentPosition()+"");
            }
        }
    };
    runnable.run();
}

And call it right after play in onPrepared()

@Override
public void onPrepared(MediaPlayer arg0)
{
    arg0.start();
    fireRunnable();
}

Now the song starts with no audio and application crash in like 5 seconds after that, is this a good approach, if yes how can I get it to work? or no what other options do I have?
Help would be appreciated.


Solution

  • If you choose to use a Runnable as you have shown, you will want to run it in another Thread and use post(Runnable) to make changes back on the UI thread. The crash you mentioned probably happens because there is a very active while loop on your UI thread. Even with starting a separate thread, you will want to call Thread.sleep(long) in your loop to yield some processor time since your progress bar doesn't need to be so incredibly accurate.

    Another method would be to use postDelayed(Runnable, long) with a Runnable that repeatedly re-posts itself after some small delay (e.g., 500 milliseconds). Depending on circumstances, this method is probably preferred as it avoids the extra thread.

    Also, you should take note that isPlaying() will be false if the MediaPlayer is paused. It would be better to use a boolean member as the condition to stop updating the progress bar. Set it to true before you begin updating the progress bar, and set it to false in the OnCompletionListener.onCompletion() callback of the MediaPlayer.

    Edit:

    When I mentioned post(Runnable) for the UI thread, I was referring to the fact that it is illegal to make changes to UI elements from other threads. In this case, you are probably not changing UI elements explicitly, only the state of the progress bar, which should be ok.

    Edit: (postDelayed version)

    In your Activity:

    private boolean mUpdateProgress = false;
    private Runnable mUpdateRunnable = new Runnable() {
        @Override
        public void run() {
            // update progress bar using getCurrentPosition()
            if (mUpdateProgress)
                postDelayed(mUpdateRunnable, 500);
        }
    }
    private MediaPlayer.OnCompletionListener mComplete =
        new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion() {
                mUpdateProgress = false;
            }
        }
    

    Wherever you create your MediaPlayer, call:

    mediaPlayer.setOnCompletionListener(mComplete);
    

    Wherever you start the MediaPlayer, do this:

    // update the duration of the progress bar
    mUpdateProgress = true;
    post(mUpdateRunnable); // or simply mRunnable.run() if you are on the main thread
    mediaPlayer.start();