Building a simple audio app in Android (Part 3/3)
Synchronizing with the SeekBar

Introduction
The goal of this series of articles is to get you started with the Android MediaPlayer API by going thru the journey of creating a very basic audio playback application called “A Simple MediaPlayer” app. This is the last part of a 3 part series that includes:
- MediaPlayer introduction
- Building the app
- Synchronizing with the SeekBar (this article)
Part 3/3 — Synchronizing with the SeekBar
This article will cover the following:
- How to synchronize the audio playback position, and duration with a
SeekBar. - How to use the
SeekBarto jump to different time positions in the audio during playback.
What does the app look like, and where is the source code?
Please checkout Part 2 of the series to see the app in action, and get the source on GitHub.
Synchronize with Seekbar
The app’s UI also has a SeekBar. This does 2 things:
- It provides visual feedback to the user as media playback is progressing (by moving the scrubber in the
SeekBarforwards as audio plays). - Allows the user to jump to any specific time location in the media by touching and dragging the scrubber. This ends up calling
seekTo()in theMediaPlayerto change its audio playback position.
1. Scrubber updating the UI to reflect playback position — PlaybackInfoListener interface
In order for the MediaPlayerHolder to provide updates to the UI (in MainActivity) that the playback position is progressing, the PlaybackInfoListener interface is used. The MainActivity implements this callback. It allows the MediaPlayerHolder and MainActivity to be decoupled.
- The
MediaPlayerHolderreports its progress and duration, without concerning itself with how the UI displays this information. - The
MediaPlayerHolderalso reports its current state (which can bePLAYING,PAUSED,RESET,COMPLETED). - The
MainActivitytakes care of displaying the duration and progress in the UI via theSeekBar.
1.1. Setting the SeekBar max to match the playback duration
The SeekBar is used to display a range of values along a horizontal line. To configure the SeekBar (which is the MainActivity) we need to tell it what its maximum value should be. In our simple app, we will set the maximum value to the duration of our audio track in milliseconds. This happens in the MediaPlayerHolder as follows after the MediaPlayer is created, and the MP3 file is loaded.
1.2. Provide visual feedback as audio playback progresses
As the audio playback progresses, the SeekBar’s setProgress(time) method has to be called with the amount of time that has elapsed during playback. There’s no listener that can be attached to the MediaPlayer to get this information, so we have to poll. There are 2 strategies for polling — using Handler, or Executor. This app uses an Executor as it makes the code easier to read.
An SingleThreadScheduledExecutor dispatches a Runnable to execute every 500 ms (PLAYBACK_POSITION_REFRESH_INTERVAL_MS). This means that at this regular interval this task is executed which paints the UI with the current position of MediaPlayer position. You can try changing this to different numbers and press the PLAY button to see how this changes the UI behavior.
2. User moving the scrubber — PlayerAdapter interface
In order to change the playback position you can use the the PlayerAdapter interface. The MediaPlayerHolder implements this interface, and here’s what it looks like partially.
2.1. Jump to any position in the media using seekTo
While the app is playing audio, if the user drags the scrubber in the SeekBar (in MainActivity), two things have to happen:
- The
Executorthat was running to provide playback progress updates has to be terminated. Otherwise it will move the scrubber and fight with the user as they are trying to move the scrubber themselves. - Once, the user completes dragging the scrubber, the position must be reported to the
MediaPlayerusingseekTo().
Methods to handle both of these situations are provided in the PlayerAdapter interface, which is implemented by MediaPlayerHolder.
Here’s the code from MainActivity where the case of the user moving the scrubber is handled. Note: mPlayerAdapter is of type PlayerAdapter, which is an interface implemented by MediaPlayerHolder.
State Machine
The MediaPlayer has a sophisticated state machine. You don’t need to fully understand it to get started. For deeper integration into MediaPlayer’s capabilities, please refer to the state machine diagram on developers.android.com.

