1 00:00:00,410 --> 00:00:04,820 We just got an ANR by trying to do our downloading in our service. 2 00:00:04,820 --> 00:00:08,240 But didn't we just say that services are an application component 3 00:00:08,240 --> 00:00:11,340 that can perform long running operations in the background? 4 00:00:11,340 --> 00:00:12,220 What gives? 5 00:00:13,260 --> 00:00:15,200 Well, by default, 6 00:00:15,200 --> 00:00:19,540 everything in an app runs on the main thread, including our service. 7 00:00:19,540 --> 00:00:23,790 So even if a service is performing long running operations in the background 8 00:00:23,790 --> 00:00:27,750 by default it will be doing those long running operations on the main thread. 9 00:00:28,760 --> 00:00:31,573 If we want our service to do work on a separate thread, 10 00:00:31,573 --> 00:00:34,273 we need to create that separate thread ourselves. 11 00:00:35,821 --> 00:00:37,740 Seems simple enough. 12 00:00:37,740 --> 00:00:41,410 Now let's make our download service do the downloading on a separate thread. 13 00:00:42,490 --> 00:00:47,480 Let's close the Android manifest and start with some planning. 14 00:00:47,480 --> 00:00:52,790 On the left is the code from when we created our own thread and main activity. 15 00:00:52,790 --> 00:00:58,060 We created, named, and started the thread in the on create method. 16 00:00:58,060 --> 00:01:03,600 Then, in the on click method of our button for each song we obtained and 17 00:01:03,600 --> 00:01:07,650 set a message and then sent that message using our handler. 18 00:01:09,300 --> 00:01:11,530 Now we need to replicate this in our service. 19 00:01:12,560 --> 00:01:17,800 Just like an activity, a service also has a life cycle and life cycle methods. 20 00:01:18,950 --> 00:01:22,000 And one of these methods is the good or onCreate method. 21 00:01:23,360 --> 00:01:27,810 So we'll create, name and start our thread, in the onCreate method. 22 00:01:29,490 --> 00:01:34,200 And since we've now replaced this message part with starting our service, 23 00:01:34,200 --> 00:01:35,840 we should now be obtaining and 24 00:01:35,840 --> 00:01:40,990 sending messages to our handler over here in the onStartCommand method. 25 00:01:42,090 --> 00:01:43,420 All right. 26 00:01:43,420 --> 00:01:47,603 Let's start and download service and remove the download song method. 27 00:01:53,628 --> 00:01:55,971 We'll now be using our download handler and 28 00:01:55,971 --> 00:01:58,700 it still has its download song method from before. 29 00:02:00,040 --> 00:02:02,570 Let's also remove the call to download the song. 30 00:02:05,450 --> 00:02:09,630 Then let's override our services on create method. 31 00:02:09,630 --> 00:02:13,620 Let's place our cursor above onStartCommand and 32 00:02:13,620 --> 00:02:17,420 use control O to override the onCreate method. 33 00:02:19,470 --> 00:02:21,680 And let's delete this call to super. 34 00:02:21,680 --> 00:02:22,360 We don't need it. 35 00:02:24,970 --> 00:02:30,100 Now we need to create, name and start our thread just like we did in our activity. 36 00:02:32,180 --> 00:02:36,870 Let's start by creating a new download thread at the top of the on create method. 37 00:02:38,340 --> 00:02:44,310 Download thread thread equals new download thread. 38 00:02:46,330 --> 00:02:50,136 Then on the next line, let's set the name of our thread. 39 00:02:50,136 --> 00:02:56,474 Thread.setName DownloadThread. 40 00:02:56,474 --> 00:03:02,584 And lastly let's start our thread, thread.start. 41 00:03:04,530 --> 00:03:08,490 Next up, we need to send a message to our thread 42 00:03:08,490 --> 00:03:10,770 each time on start command is called. 43 00:03:12,080 --> 00:03:15,680 Under where we declare a song, let's obtain a message, and 44 00:03:15,680 --> 00:03:17,476 set it to a new message variable. 45 00:03:17,476 --> 00:03:24,940 Message message equals message.obtain. 46 00:03:24,940 --> 00:03:27,878 Then let's attach our song variable to our message, 47 00:03:27,878 --> 00:03:33,390 message.obj equals song, 48 00:03:33,390 --> 00:03:38,700 and send the message using our handler, which we currently don't have access to. 49 00:03:39,750 --> 00:03:42,406 Let's quickly create a field for our download handler. 50 00:03:42,406 --> 00:03:48,443 private download handler 51 00:03:48,443 --> 00:03:53,240 mhandler, then let's give it a value at the bottom of on Create 52 00:03:55,950 --> 00:04:00,240 mhandler equals thread but mhandler. 53 00:04:01,350 --> 00:04:04,100 Lastly, back in on StartCommand, 54 00:04:04,100 --> 00:04:13,256 let's send our message, mHandler.sendMessage(message);, 55 00:04:13,256 --> 00:04:15,420 great work! 56 00:04:15,420 --> 00:04:18,560 Now that we're doing our download and a separate thread, 57 00:04:18,560 --> 00:04:23,070 again we shouldn't have any issues with the app being slow or 58 00:04:23,070 --> 00:04:26,310 not responding, but let's test it out just to be sure. 59 00:04:32,460 --> 00:04:36,453 Let's click the download button and 60 00:04:36,453 --> 00:04:41,744 yikes the app crashed If we look through the log. 61 00:04:46,808 --> 00:04:48,300 And filter by errors. 62 00:04:50,710 --> 00:04:55,180 It looks like we're getting a null pointer exception because we're trying to invoke 63 00:04:55,180 --> 00:05:03,050 the virtual method, send message on a null object reference. 64 00:05:05,060 --> 00:05:07,380 And if we click on the link to jump to the error 65 00:05:10,260 --> 00:05:13,280 it looks like that null object is our handler. 66 00:05:15,390 --> 00:05:18,950 Just like last time this is because our main thread 67 00:05:18,950 --> 00:05:21,260 is ahead of our download thread. 68 00:05:21,260 --> 00:05:25,447 The main thread has already finished the onCreate method and 69 00:05:25,447 --> 00:05:28,320 moved on to the onStartCommand method all 70 00:05:28,320 --> 00:05:33,014 before our download thread has even created our download handler. 71 00:05:35,417 --> 00:05:36,343 To fix this, 72 00:05:36,343 --> 00:05:41,920 let's make our main thread wait until the handler exists before we assign it. 73 00:05:43,360 --> 00:05:49,033 Up in the on create method above the assignment 74 00:05:49,033 --> 00:05:54,272 to mHandler,let's type while thread.m 75 00:05:54,272 --> 00:05:59,520 handler equals null and add our brackets. 76 00:06:00,960 --> 00:06:03,490 We shouldn't have to worry about a null handler any more. 77 00:06:05,130 --> 00:06:10,250 Using an empty while loop like this definitely isn't the best practice. 78 00:06:10,250 --> 00:06:12,830 But it's the best we can do with what we've learned so far. 79 00:06:14,110 --> 00:06:17,501 Now let's test the app again and hopefully everything will work. 80 00:06:20,947 --> 00:06:24,377 Also make sure you have the Android device monitor open so 81 00:06:24,377 --> 00:06:27,740 we can see what happens when we kill our app's process. 82 00:06:28,970 --> 00:06:34,200 And if we click the download button, it seems to be working. 83 00:06:35,650 --> 00:06:43,740 And if we wait ten seconds, We can see our downloads start coming in. 84 00:06:45,170 --> 00:06:46,540 Nice. 85 00:06:46,540 --> 00:06:50,260 Now let's switch to the Android device monitor and kill our apps process 86 00:06:55,420 --> 00:06:58,810 and if we check the log and scroll up a little bit, 87 00:07:01,430 --> 00:07:07,220 we can see a scheduling restart of crashed service and there's our service. 88 00:07:10,590 --> 00:07:13,370 It looks like it'll restart in 47 seconds. 89 00:07:17,720 --> 00:07:20,600 So let's wait for 47 seconds and see what happens. 90 00:07:24,790 --> 00:07:27,340 And look at that, our process came back. 91 00:07:29,660 --> 00:07:30,290 And check it out. 92 00:07:31,700 --> 00:07:33,190 Our downloads are happening again. 93 00:07:34,910 --> 00:07:35,770 What's going on here? 94 00:07:37,140 --> 00:07:39,280 Let's find out in the next video.