Create a Music Player on Android: Song Playback

In this series, we are creating a music player on Android using the MediaPlayer and MediaController classes. In the first part, we created the app and prepared the user interface for playback. We presented the list of songs on the user device and specified a method to execute when the user makes a selection. In this part of the series, we will implement a Service class to execute music playback continuously, even when the user is not directly interacting with the application.

Looking for a Quick Solution?

This series takes you through the full process of creating an Android music player from scratch, but another option is to use one of the music player app templates on Envato Market, such as Android Music Player, which lets users browse and play music by albums, artists, songs, playlists, folders, and album artists.

Android Music Player
Android Music Player

Or, for more personalised help, you could hire a mobile app developer on Envato Studio. That way, you can get reliable, affordable help on any aspects of the development work you're not comfortable with, and focus your energy and time on areas in which you're stronger.

Introduction

We will need the app to bind to the music playing Service in order to interact with playback, so you will learn some of the basic aspects of the Service life cycle in this tutorial if you haven't explored them before. Here is a preview of the final result that we're working towards:

Android Music Player

In the final installment of this series, we'll add user control over the playback and we'll also make sure the app will continue to function in various application states. Later, we will follow the series up with additional enhancements that you may wish to add, such as audio focus control, video and streaming media playback, and alternate ways of presenting the media files.

1. Create a Service

Step 1

Add a new class to your app, naming it MusicService or another name of your choice. Make sure it matches the name you listed in the Manifest. When creating the class in Eclipse, choose android.app.Service as its superclass. Eclipse should enter an outline:

Extend the opening line of the class declaration to implement some interfaces we will use for music playback:

Eclipse will display an error over the class name. Hover over the error and choose Add unimplemented methods. We will add code to the methods in a few moments. The interfaces we are implementing will aid the process of interacting with the MediaPlayer class.

Your class will also need the following additional imports:

Step 2

Add the following instance variables to the new Service class:

We will pass the list of songs into the Service class, playing from it using the MediaPlayer class and keeping track of the position of the current song using the songPosn instance variable. Now, implement the onCreate method for the Service:

Inside onCreate, call the superclass method, instantiating the position and MediaPlayer instance variables:

Next, let's add a method to initialize the MediaPlayer class, after the onCreate method:

Inside this method, we configure the music player by setting some of its properties as shown below:

The wake lock will let playback continue when the device becomes idle and we set the stream type to music. Set the class as listener for (1) when the MediaPlayer instance is prepared, (2) when a song has completed playback, and when (3) an error is thrown:

Notice that these correspond to the interfaces we implemented. We will be adding code to the onPrepared, onCompletion, and onError methods to respond to these events. Back in onCreate, invoke initMusicPlayer:

Step 3

It's time to add a method to the Service class to pass the list of songs from the Activity:

We will call this method later in the tutorial. This will form part of the interaction between the Activity and Service classes, for which we also need a Binder instance. Add the following snippet to the Service class after the setList method:

We will also access this from the Activity class.

2. Start the Service

Step 1

Back in your app's main Activity class, you will need to add the following additional imports:

And you'll also need to declare three new instance variables:

We are going to play the music in the Service class, but control it from the Activity class, where the application's user interface operates. To accomplish this, we will have to bind to the Service class. The above instance variables represent the Service class and Intent, as well as a flag to keep track of whether the Activity class is bound to the Service class or not. Add the following to your Activity class, after the onCreate method:

The callback methods will inform the class when the Activity instance has successfully connected to the Service instance. When that happens, we get a reference to the Service instance so that the Activity can interact with it. It starts by calling the method to pass the song list. We set the boolean flag to keep track of the binding status. You will need to import the Binder class we added to the Service class at the top of your Activity class:

Don't forget to alter the package and class names to suit your own if necessary.

Step 2

We will want to start the Service instance when the Activity instance starts, so override the onStart method:

When the Activity instance starts, we create the Intent object if it doesn't exist yet, bind to it, and start it. Alter the code if you chose a different name for the Service class. Notice that we use the connection object we created so that when the connection to the bound Service instance is made, we pass the song list. We will also be able to interact with the Service instance in order to control playback later.

Return to your Service class to complete this binding process. Add an instance variable representing the inner Binder class we added:

Now amend the onBind method to return this object:

Add the onUnbind method to release resources when the Service instance is unbound:

This will execute when the user exits the app, at which point we will stop the service.

3. Begin Playback

Step 1

Let's now set the app up to play a track. In your Service class, add the following method:

Inside the method, start by resetting the MediaPlayer since we will also use this code when the user is playing subsequent songs:

Next, get the song from the list, extract the ID for it using its Song object, and model this as a URI:

We can now try setting this URI as the data source for the MediaPlayer instance, but an exception may be thrown if an error pops up so we use a try/catch block:

After the catch block, complete the playSong method by calling the asynchronous method of the MediaPlayer to prepare it:

Step 2

When the MediaPlayer is prepared, the onPrepared method will be executed. Eclipse should have inserted it in your Service class. Inside this method, start the playback:

In order for the user to select songs, we also need a method in the Service class to set the current song. Add it now:

We will call this when the user picks a song from the list.

Step 3

Remember that we added an onClick attribute to the layout for each item in the song list. Add that method to the main Activity class:

We set the song position as the tag for each item in the list view when we defined the Adapter class. We retrieve it here and pass it to the Service instance before calling the method to start the playback.

Before you run your app, implement the end button we added to the main menu. In your main Activity class, add the method to respond to menu item selection:

Inside the method, add a switch statement for the actions:

We will implement the shuffle function in the next tutorial. For the end button, we stop the Service instance and exit the app. Pressing the back button will not exit the app, since we will assume that the user wants playback to continue unless they select the end button. Use the same process if the the app is destroyed, overriding the activity's onDestroy method:

When you run the app at this point, you will be able to play songs by selecting them from the list and you can also exit the app using the end button.

Conclusion

We have now implemented basic playback of music tracks selected from the user's list of music files. In the final part of this series, we will add a media controller through which the user will be able to control playback. We will add a notification to let the user return to the app after navigating away from it and we will carry out some housekeeping to make the app cope with a variety of user actions.

Tags:

Comments

Related Articles