[MUSIC] Welcome to Part 3 of the lesson on service lifecycle operations. After you complete this part of the lesson, you'll learn how the service lifecycle operations are applied in the musicPlayer app that we discussed earlier. Let's start by giving additional insight as to the structure and functionality of the MusicPlayer app itself. The MusicPlayer app plays music via a started service. To start the service a user needs to do two things via the MusicActivity shown here. One thing the user needs to do is provide a URL to a song. This is shown down here on this little menu bar. Once the song has been provided, the user then needs to push the play button, which will play the song. The music service will continue to play music even if the music activity leaves the foreground to be replaced by some other app. To stop the service, the user needs explicitly push the Stop button. As you can see, these are floating action buttons that change from playing and stopping depending on what state they're in. The MusicActivity sends an intent via a call to the startService method. This intent contains data that indicates which song to play in the form of a URL that identifies the resource in a remote server. The MusicService is started on-demand by the android Activity Manager Service. This is based, of course, on the activator pattern which efficiently and transparently automates scalable on-demand activation and deactivation of services accessed by multiple clients. OnCreate is called when the MusicService is first launched. OnStartCommand initiates playing the song that's requested via the MusicActivity using the intent that was passed to onStartCommand. The MusicService is also stopped on-demand by the Activity Manager Service. This happens by having the music activity make a call to stop service in response to a button pushed by the user. That causes the onDestroy method to be called to stop playing the music. Let's now give an overview of the MusicPlayer app design and implementation. The MusicPlayer app contains a music activity and a music service. We give a brief overview, here, and we'll walk through the details of the source code shortly. Key music activity methods include onCreate, which is a service lifecycle hook method called an activity is created. In this discussion, any method names that are colored red are lifecycle service hook methods called back automatically by the android activity manager service. PlaySong is a method that starts playing a song via the MusicService. StopSong stops playing a song via the MusicService. There's also a number of MusicService methods we'll cover including makeIntent, which is a factory method that returns an intent to play and stop playing a song. OnCreate, which is another lifecycle hook method called once when a new instance of the service is created. OnStartCommand, which of course is the lifecycle hook method that's called every time MusicService is started by StartServiceCall in the activity. OnPrepared is a method called when the media player is ready to play a song. We'll see that shortly when we look at the implementation details. And OnDestroy is a service lifecycle hook method called the the MusicService is stopped. OnDestroy in turn will call stopSong, which stops the media player from playing the song. The AndroidManifest.xml file exports both the MusicActivity and the MusicService components. Other apps could use these activity and service components if they so desire. Let's now go ahead and do more detailed walk-through of the MusicPlayer App source code, which is available at this link. We're now back inside the MusicPlayer apps android Studio Project file, and let's go ahead take a look at the activity and service implementations in more detail. We'll start with MusicActivity first. As you can see here, this activity extends the LifecycleLoggingActivity that we've looked at in previous MOOCs. That just provides a way to log the various lifecycle hook methods that are called, so you can see more easily in the logcat what's going on. We then define a number of fields that are used for the implementation. We have a default song which is actually something from my website that a friend of mine and I recorded with some Jimmy Hendricks music where I was playing bass guitar and my friend was playing guitar. We have an EditText field that's used to enter the desired URL to a song. We keep track of an intent that's used to start and stop the music service. We have a couple of floating action buttons, one's that's used to add a URL and one that's used to start or stop the playing of the song. We have another boolean that's used to keep track of whether or not the users entered a URL yet. Now, we come down to the various methods. Here's the onCreate hook method which of course is called back when Android creates the activity. As you can see here it does the canonical things. It calls up to the super class to say the instance state if necessary. If it's being restarted it sets the default content view and it initializes the various views. Here's the initializedViews method. This basically just goes ahead and gets the floating action buttons and the editText and so on. And it also registers a listener that's used to display the start or stop FAB when the user hits enter. So there's just a little code in there to do that. Here's the add URL button. This is called by the Android Activity Framework, when the user clicks the floating action button. And what it'll do is, it will go ahead and basically check to see whether the edit text is visible, and if it is visible, then it'll go ahead and set it to be hidden. And it'll rotate the floating action button. And then it'll go ahead and start the animation for all this. And if it's not visible, then it'll go ahead and reveal it, and we'll go ahead and do some other animations to rotate the fab button back and forth. Here is the startOrStopPlaying method. This is called back, of course, when the user touches the current floating action button which either is going to used to start playing the song or stop playing the song. If the music intent field is null then we're going to go ahead and play the song. Otherwise, we going to go ahead and stop the song. So that's how we figure out whether we need to play or stop. Here is playSong, as you can see, what play song does is it hides the keyboard. Gets the URL to the song, the user entered via the edit text window or at text field. And then it goes ahead and does a little sanity checking on the URL to make sure it's valid. Down here, we go ahead and call makeIntent which we'll see in a second that makes an intent to start the service. And then, we come down here and we use that intent to start the service. And then, we go ahead and rotate the FAB to display the stop icon which of course is what you see once you start playing. So you can go ahead and stop playing the music. If you click on the stop icon, when a song is playing, then that goes ahead and calls stopService. Passing in the intent that we got from makeIntent up here. It then nulls out that intent and then goes ahead and updates the floating action button to display the play icon. And then the final method here is getUrl and all this simply does is it goes and sees if the user entered anything in the editText. And if they did not, we choose the default song. And in either case, we go ahead and return the URI to what the user is going to have play. So that's the activity. Let's now go look at the service implementation. As we have discussed briefly before, you can see that MusicService extends the service class. And it goes ahead and implements the MediaPlayer.OnPreparedListener. This is used in order to prevent this service from having to implement its own concurrency mechanism to play the song. We'll see how that works in a second. It's a really cool asynchronous mechanism that's supported by the media player which is a class defined in android. We keep track of whether the song is currently playing, as a boolean, a static boolean. We keep track of the media player, that's used to play a song, in the background, that's another android component. Here's the makeIntent method. As you can see this is a factory method, that goes ahead and makes an explicit intent. And this will be used to start the music service. The intent is going to be associated with the music service class. And then we go ahead and use the fluent interface programming style to set the song URL that's passed here as a parameter, as the data of the intent that's returned. Notice that this call to makeIntent will always run in the same address base as the client activity. This is actually not run in a separate process. Here's the onCreate method which will in fact run in a separate process, because of the way that we have configured this particular music service to run in its own process via the manifest file we looked at earlier. The onCreate method calls up to the super class. Creates a new media player object that will be used to play the requested song. And then sets that media player into streaming mode. So it's going to go ahead and stream the music that's playing. Here's the onDestroy hook method. This gets called back when the service is shut down, when the user clicks that stop button. And that causes the stop service to be called on the intent. And as we see here that causes the stopSong method to be called. And we'll look at that in just a moment. And that'll stop playing the song. Before that occurs of course, here is the onStartCommand hook method. This is another one of these lifecycle hook methods that is called back by the activityManager service after the music service has been started. And when it's going to receive the intent that was passed by the client. And what we do here, is we go ahead and we fish out the URL from the data portion of the intent. So now we have a songURL. If we're currently playing a song, we're going to stop playing the current song. And in either case, we're going to go ahead and set that songURL as the data source. We'll then you're going to say setOnPreparedListener, passing ourselves in, passing in this. That means we're going to get a callback later. And we'll look at that in a minute. And then, we go ahead and we say to the media player object, please prepare yourself asynchronously which means, go ahead and start downloading portions of that song, but don't block the UI thread. And notice how we return the START_NOT_STICKY flag. We'll talk more about START_NOT_STICKY later. What that means is don't restart the service if it gets shut down involuntarily. Here is the onBind method. This is another hook method that's automatically called back by android's activity manager service. And this simply returns null to indicate that this is a started service, not a bound service. Down here we see the onPrepared method, which is what's implemented. If you go up here and take a quick look, you'll see that this class implements the media player onPreparedListener interface. And this is the hook method called onPrepared. It's called back, When the song has got enough content to start playing. And what we do here is we go ahead and set this thing to only play the song once rather than looping. Indicate the song is now playing, and then we start playing the song. And then at that point, the song will play out in the background. The final method here is the stopSong method. This is what gets called back from onDestroy. Just what we saw up here. There's onDestroy. You can see it calls stopSong. And what stopSong does is it tells the media player, please stop playing the song. Please reset the media player back to the beginning, and set a flag that says this song is no longer playing. So that's basically the implementation of our MusicActivity and our MusicService. And as you can see, it's a very simple implementation. Not much going on, just using the various hook methods and filling them out. We'll wrap up this lesson with a summary analysis of the MusicPlayer app. This app is a simple example of a started service. For example, it doesn't need to spawn internal threads explicitly. Instead it uses the MediaPlayer's asynchrony features. There's also no communication from the service back to the activity that invoked us. The ImageDownloader apps, we examine in the next module, are much more interesting examples of service concurrency. In particular, they extend service and intent service to download requests concurrently. There's also communication from the service back to the activity that invoked it. This concludes Part 3 of our lesson on service lifecycle operations. [MUSIC]