Bound and Started7:08 with Ben Deitch
In this video we’ll see why sometimes we need to both bind to and start a Service!
Finally, we've hooked up our app to play and pause music when we tap on a button. 0:00 Before we move on, let's review how this all works. 0:05 We begin in the onStart method of main activity with a call to bindService, 0:10 and we pass in a service connection object. 0:15 Then onCreate will be called in our service, followed by onBind. 0:18 Then the onServiceConnected method of our service connection 0:25 gets notified when we are successfully connected. 0:31 And we set mBound to true, and retrieve our PlayerService variable 0:34 by casting the provided iBinder to a local binder and calling getService on it. 0:40 Later on, when we tap the PlayButton for the first time, 0:47 mBound should be true and isPlaying should return false. 0:50 So we'll end up calling the play method of our player service and 0:56 start hearing some music. 1:01 Pretty cool, right? 1:03 Definitely, and even though we've correctly implemented binding, 1:04 our app still isn't quite right. 1:09 Let's launch the app again and hit the PLAY button. 1:12 [MUSIC] 1:18 Then, let's go back to the home screen. 1:20 And what's that? 1:24 The music stopped. 1:26 That's no good, 1:27 we're supposed to be using a service to let us play music in the background. 1:29 So why did it stop? 1:34 When we leave our app, the onStop method of main activity is triggered, and 1:36 we unbind from our service. 1:41 And now that our service doesn't have any clients left, 1:43 it's onUnbind method will be called, followed by onDestroy. 1:46 We can even see these calls in the log. 1:51 And when onDestroy is called, we release our media player, and 1:56 it stops playing our song. 2:00 Okay, but which part of that was the problem? 2:04 Well, it depends on what you're trying to do. 2:07 Since we're trying to make a music player app, 2:11 we'd like the music to keep playing even when our activity is long gone. 2:14 So the problem is that our service is getting destroyed 2:19 when we leave our activity. 2:22 However, this is exactly what we'd expect from a bound service. 2:25 When the last client unbinds, it gets destroyed. 2:29 So what we really need is for 2:33 our player service to allow both binding and the starting. 2:35 Let's take a closer look at why this is. 2:40 Right now our service is basically created and destroyed right along with our 2:43 activity [SOUND], just like we would expect from a bound service [SOUND]. 2:48 But if music is playing while we leave the activity, 2:53 we need our service not to be destroyed. 2:56 That way, if we open the activity again, 3:00 it'll bind to the same service and we'll be able to control the music. 3:03 We can keep our service from being destroyed by starting our service and 3:08 not stopping it until it's done playing. 3:12 This way, our service won't be destroyed until it both doesn't have any clients, 3:15 and is done playing, just what we're looking for. 3:21 In the OnClick listener of our PlayButton, 3:24 let's start our PlayerService when we start playing our song. 3:28 Right above the call to mPlayerService.play, 3:32 let's create an intent for our PlayerService. 3:36 Intent intent = new Intent(MainActivity.this, 3:40 PlayerService.class). 3:48 Remember, that if we just use the this keyword, 3:53 we'd be referring to this anonymous OnClickListener class. 3:56 Next, let's start our players service by calling startService and 4:02 passing in the intent Nice, 4:06 over in our PlayerService class, let's override the onStart command method so 4:15 our call to startService will actually start our service. 4:21 Add a couple lines below onCreate, and 4:26 let's use Ctrl+O to override onStartCommand, and 4:29 change the return value to Service.START_NOT_STICKY. 4:34 We only want our service to be in a started state while our song is playing. 4:44 If our app crashes, the song won't be playing anymore. 4:50 And we shouldn't restart our service because then we'd have a started service 4:54 with no music playing. 4:58 Our service can now be successfully started, but 5:00 we still need to stop our service when its job is done. 5:03 This service is used for playback of a single song. 5:07 And when that song is done playing we can safely stop our service. 5:11 At the top of onStartCommand, let's add an OnCompletionListener to our media player, 5:16 mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener. 5:23 And inside the onCompletionMethod, let's call stopSelf with no parameters. 5:31 Remember, calling stopSelf with no parameters stops the service immediately, 5:38 regardless of whether it's still working or not. 5:44 Every time we tap the play button, it will start our service, 5:47 and onStartCommand will be called. 5:51 But since we only care about one song and one media player, 5:54 as soon as that song is finished playing, we just want to stop our service, 5:58 regardless of how many times it was started. 6:03 All right, now let's test the app 6:05 We can PLAY, and PAUSE music just like before, but 6:14 if we hit PLAY again and then leave the app, the music keeps playing. 6:19 Great job. 6:27 And if we look over to the log, 6:29 [MUSIC] 6:30 We can see the call to onUnbind, but not the call to onDestroy, 6:34 which means our service is no longer bound. 6:39 And since it wasn't destroyed, it must be started. 6:43 And if we wait for the end of the song, 6:47 we can see our service finally get destroyed just like we planned. 6:49 How cool is that? 6:54 You've just created a fully functioning music player that'll even 6:56 keep playing in the background. 6:59 You should be super proud of what you've accomplished, so go ahead and 7:01 take a minute to reflect on just how awesome you are. 7:05
You need to sign up for Treehouse in order to download course files.Sign up