1 00:00:04,990 --> 00:00:06,920 OK, so moving on now. 2 00:00:06,920 --> 00:00:10,370 Now, we won't be able to run the finished app on our current emulator. 3 00:00:10,370 --> 00:00:13,450 That's because it needs Google's Youtube Player to be installed, 4 00:00:13,450 --> 00:00:18,250 but we are testing failure conditions here, so we can test the failure on our emulator. 5 00:00:18,250 --> 00:00:22,480 But there's one more thing we should do first, and that's to request Internet permissions, just like 6 00:00:22,480 --> 00:00:24,580 we did for the top 10 downloader app. 7 00:00:24,580 --> 00:00:28,150 So I'm going to make a quick change to the manifest file so that we can actually do that. 8 00:00:28,150 --> 00:00:34,210 So we're going to make sure that we're in Android view, select the Manifest's folder, double click on AndroidManifest, 9 00:00:34,210 --> 00:00:39,530 and what we want to do is add the Internet permission, and I'm going to do that just after the manifest's 10 00:00:39,530 --> 00:00:47,620 line before the application part. So I'm going to put the user's permission tag, the name equals, and I'm going 11 00:00:47,620 --> 00:00:51,600 to just type in enough characters, INTE, until Internet comes up. 12 00:00:51,600 --> 00:00:56,590 So I'm going to select that and press enter, making sure that it's specified exactly like that, 13 00:00:56,590 --> 00:01:00,910 and that's why, as I've mentioned before, it's usually a good idea to select it from the the drop-down list rather 14 00:01:00,910 --> 00:01:04,750 than typing it in, because if you type that in any way wrong, it won't work. 15 00:01:04,750 --> 00:01:08,650 And again these permissions are case sensitive so it's best to choose them from the list as I've mentioned, rather 16 00:01:08,650 --> 00:01:09,820 than typing them in. 17 00:01:09,820 --> 00:01:14,770 Now the app's going to fail when we run it on the emulator, but not for the reason you might think. There's 18 00:01:14,770 --> 00:01:17,470 something else that's going to cause it to crash and it's pretty cool. 19 00:01:17,470 --> 00:01:21,490 So let's see what it is. Now we were messing around with Gradle earlier, 20 00:01:21,490 --> 00:01:27,760 so we want to rebuild the project from the build menu, build, rebuild project. OK we're going to 21 00:01:27,760 --> 00:01:30,940 come up here and select run, we'll run it once. 22 00:01:30,940 --> 00:01:35,440 Well actually what I did was, I selected, or left the YouTube Player signing report selected, 23 00:01:35,440 --> 00:01:37,990 that's the last Gradle build task that we selected, 24 00:01:37,990 --> 00:01:40,810 so that's the reason that's come up, which isn't what we want to do here. 25 00:01:40,810 --> 00:01:45,640 So I'm going to just come up here, and I'll select YouTubeActivity from this list here, and now I'm going 26 00:01:45,640 --> 00:01:52,860 to click on run again, and I'm going to actually run this on my Nexus 5 emulator with API 26 that we've 27 00:01:52,860 --> 00:02:01,810 previously installed. Then we're going to run that, and we're going to find that it'll crash. 28 00:02:01,810 --> 00:02:08,490 OK, you can see Youtube Player has stopped and we've got a crash here, and we can open up our logcat. We 29 00:02:08,490 --> 00:02:11,650 could've just left it in the run there to have a look in the run tab, 30 00:02:11,650 --> 00:02:16,620 "An operation is not implemented", so it's a kotlin.NotImplemented error that we've actually got. 31 00:02:16,620 --> 00:02:22,280 And if you click on the error line over here, the link in blue, that actually takes us to line 38, which 32 00:02:22,280 --> 00:02:29,620 in the onInitializationSuccess method, and that's of course the function that we haven't yet implemented. 33 00:02:29,620 --> 00:02:35,050 Now we've used a TODO comment before, so that we didn't forget to add a safe call operator in the top 10 34 00:02:35,050 --> 00:02:40,210 downloader app, but I don't think I've mentioned that TODO comments are automatically tracked, and appear 35 00:02:40,210 --> 00:02:45,300 in the TODO pane at the bottom of the window down here. So that's very useful, 36 00:02:45,300 --> 00:02:50,550 you can click on an entry in there and go straight to the code that relates to the TODO. 37 00:02:50,550 --> 00:02:55,820 So definitely make use of that so you don't forget to come back to something that you intended to do later. 38 00:02:55,820 --> 00:02:59,760 But I'll close that now, but the thing is though here, this isn't a comment, 39 00:02:59,760 --> 00:03:04,650 it's actually a function call. So Kotlin provides this in it's standard library, 40 00:03:04,650 --> 00:03:07,500 and think of it like a TODO comment with attitude. 41 00:03:07,500 --> 00:03:13,200 So it doesn't just appear in the TODO entries, it actually throws an exception if we forget to do it. 42 00:03:13,200 --> 00:03:19,470 So definitely make use of those, they're really very handy and will remind you to update your code or change 43 00:03:19,470 --> 00:03:21,750 your code, if you haven't got around to doing that yet. 44 00:03:21,750 --> 00:03:25,950 In other words there's no chance that you're going to forget to implement this callback, because of actually 45 00:03:25,950 --> 00:03:30,990 the fact that it's crashing. So, what I'm going to do now is comment that line out. 46 00:03:30,990 --> 00:03:34,850 Now it still appears when I've done that in the TODO list, 47 00:03:34,850 --> 00:03:40,320 you can see down there, but I won't get an exception thrown now because that code won't be executed anymore. 48 00:03:40,320 --> 00:03:46,070 Alright, so let's actually try again. Now this time I have to be careful which emulator I use. 49 00:03:46,070 --> 00:03:50,780 Now we want the app to fail, so that we can see what happens when you run it on a device that doesn't 50 00:03:50,780 --> 00:03:52,250 have YouTube installed. 51 00:03:52,250 --> 00:03:58,730 But unfortunately YouTube can't be uninstalled from the emulators that include it. Now at the time I'm recording 52 00:03:58,730 --> 00:04:06,290 this, all the API 26 emulators include YouTube. Now some of the API 24 emulators also include it now. 53 00:04:06,290 --> 00:04:11,390 So what I did was, I created an API 17 emulator using a Nexus 4. 54 00:04:11,390 --> 00:04:17,450 Now if you want to get similar results to me then don't try it on an API 24 or 26 emulator, because 55 00:04:17,450 --> 00:04:22,560 most likely they'll probably include YouTube. So let's try running the app. 56 00:04:22,560 --> 00:04:35,120 So I'm going to run it. This time I'm going to select my Nexus 4 API 17, and we should find we get an error. 57 00:04:35,120 --> 00:04:42,010 And we'll just fast forward this bit so we see it quicker. Alright that's better now, 58 00:04:42,010 --> 00:04:44,620 and you can see the error that we've actually got here. 59 00:04:44,620 --> 00:04:47,980 So it doesn't work because YouTube isn't installed on this emulator. 60 00:04:47,980 --> 00:04:53,320 But now we can see some of the error dialogues that Google have provided as part of this API. 61 00:04:53,320 --> 00:04:57,220 And again we're getting the error message "This app won't run without the YouTube app which is missing 62 00:04:57,220 --> 00:04:59,140 from your device". 63 00:04:59,140 --> 00:05:04,090 Now on a physical device. tapping the Get YouTube App link will take you to the Play Store, 64 00:05:04,090 --> 00:05:09,220 but because the Google Play Services also aren't installed on the emulator, that doesn't work and we just 65 00:05:09,220 --> 00:05:13,610 get a message in the middle of the widget saying "An error occurred while initialising the YouTube Player" after 66 00:05:13,610 --> 00:05:18,960 we try as you can see on the screen there. Now on a tablet with an old version of YouTube Player installed, 67 00:05:18,960 --> 00:05:21,700 you'll get a dialogue that looks something like this: 68 00:05:21,700 --> 00:05:26,590 and you can see the difference there is that the message is updating as opposed to installing this time. 69 00:05:26,590 --> 00:05:30,090 Now after tapping the update YouTube App link, 70 00:05:30,090 --> 00:05:35,100 that'll take you to the Google Play Store, and you see a screen similar to this. Now I 71 00:05:35,100 --> 00:05:40,870 disabled the Google YouTube App on that device, but the update message takes precedence over the Disabled message, 72 00:05:40,870 --> 00:05:45,080 so I can't show you how the Disabled dialogue would take you into the Settings, so that you can enable 73 00:05:45,080 --> 00:05:49,510 YouTube if you disabled it. We'll see that later. Alright, but over all that's pretty cool, 74 00:05:49,510 --> 00:05:53,980 and instead of just displaying an error message, we are actually taking advantage of Google's error 75 00:05:53,980 --> 00:05:58,810 dialogue, to help the user sort out some of the problems for themselves. And we'll see how to automatically 76 00:05:58,810 --> 00:06:03,910 take the user into the settings for our apps when we look at permissions in more detail later. 77 00:06:03,910 --> 00:06:07,420 Alright so we've created the code to cope with failure. 78 00:06:07,420 --> 00:06:12,210 Now let's have a look at what we need to do if initialization was successful, by adding code to the 79 00:06:12,210 --> 00:06:14,560 onInitializationSuccess function. 80 00:06:14,560 --> 00:06:21,760 Now I'm going to go ahead and change the parameter names because p0, p1 and p2 really aren't very informative. 81 00:06:21,760 --> 00:06:25,090 I'm going to rename them to match the documentation we're looking at. 82 00:06:25,090 --> 00:06:29,560 Alright, so rather than going directly to the documentation this time I'm going to search for it, because 83 00:06:29,560 --> 00:06:32,590 that's probably what you'll end up doing when you start experimenting. 84 00:06:32,590 --> 00:06:42,890 So if I switch to a browser, and if I actually do a search here for youtube player, then oninitialization 85 00:06:42,890 --> 00:06:49,810 success, all one word, and generally it's a good idea to include the name of the class and not just the 86 00:06:49,810 --> 00:06:51,760 function when you're searching. 87 00:06:51,760 --> 00:06:55,670 And that's because there's probably hundreds of different classes that have some sort of initialization 88 00:06:55,670 --> 00:06:56,950 success function. 89 00:06:56,950 --> 00:07:01,980 And as you can see we've got quite a few results back, but I generally look at the URL which Google show 90 00:07:01,980 --> 00:07:08,020 just below the title of each result, and the official Google documentation is that developers.google.com. 91 00:07:08,020 --> 00:07:11,570 So that would be the link that I would normally check out first. 92 00:07:11,570 --> 00:07:17,680 Now by being fairly specific in the search, we get the Google documentation as the first result. 93 00:07:17,680 --> 00:07:22,750 So I didn't have to do too much thinking about what to search for either. We're working with the YouTube Player, 94 00:07:22,750 --> 00:07:25,750 and we're interested in the onInitializationSuccess function, 95 00:07:25,750 --> 00:07:30,310 so I just used those two terms as you saw when searching. Now the result was the reference doc for the 96 00:07:30,310 --> 00:07:32,860 interface that defines these two functions, 97 00:07:32,860 --> 00:07:35,740 so let's see what they have to say about the success method. 98 00:07:35,740 --> 00:07:39,280 So we've got this onInitializationSuccess method here, 99 00:07:39,280 --> 00:07:43,930 and if you go down towards the bottom of the page, you can see more details about this. 100 00:07:43,930 --> 00:07:47,080 These are the three parameters that are actually expected. 101 00:07:47,080 --> 00:07:52,150 Now the provider is an object that implements the YouTube Player.Provider interface, which our You 102 00:07:52,150 --> 00:07:57,550 TubePlayerView widget does. So that parameter will contain a reference to our Player widget. 103 00:07:57,550 --> 00:08:02,440 But don't take my word for it. You can log the class name of objects that you get as parameters, to see 104 00:08:02,440 --> 00:08:05,590 what you're really getting, and I'll show you how to do that in a minute. 105 00:08:05,590 --> 00:08:11,560 Now the second parameter is a YouTube Player that we can use to control playback such as pausing or 106 00:08:11,560 --> 00:08:12,960 stopping the video. 107 00:08:12,960 --> 00:08:18,700 Now we're not going to do that, but we will monitor the Player and provide some feedback on what it's doing. 108 00:08:18,700 --> 00:08:25,780 And that brings us to this third parameter: was restored. Now if that's true then we shouldn't start a new video, and 109 00:08:25,780 --> 00:08:29,530 that's because the Player will continue with the one that it was already playing. 110 00:08:29,530 --> 00:08:31,660 Alright, so back to the code. 111 00:08:31,660 --> 00:08:38,980 Now I want to add some logging, so let's add a tag to this class, just below the class definition I'm going to do a private 112 00:08:38,980 --> 00:08:44,680 val TAG equals, then we'll call it YoutubeActivity. 113 00:08:44,680 --> 00:08:48,580 Now we can rename those parameters and log the types of the first two. 114 00:08:48,580 --> 00:08:49,920 So let's go ahead and do that. 115 00:08:49,920 --> 00:08:57,940 So go to our onInitializationSuccess, we'll change p0 here to provider. We'll change the second one, 116 00:08:57,940 --> 00:09:07,560 p1, we'll call that youTubePlayer, and for the third one I'll just start that on the new line, instead of P2, 117 00:09:07,560 --> 00:09:14,060 we'll call this one wasRestored. Alright I'm going to delete that TODO now, because we're actually implementing 118 00:09:14,060 --> 00:09:21,100 that now, and in terms of the code, let's start by logging the types of the first two parameters. 119 00:09:21,100 --> 00:09:22,920 So Log.d 120 00:09:22,920 --> 00:09:33,980 TAG double quotes onInitializationSuccess colon provider is, now we'll add a dollar sign, 121 00:09:33,980 --> 00:09:41,480 Left to right curly braces, provider question mark dot javaClass. 122 00:09:41,480 --> 00:09:49,250 Then on the next line, we'll do a Log.d TAG, and then this second argument will be the same. Actually let's just 123 00:09:49,250 --> 00:09:56,580 copy that entire line, the rest of the line there, like so, and 124 00:09:56,580 --> 00:10:04,470 this time it's going to be onInitializationSuccess youTubePlayer, player is, and it's going to be youTube 125 00:10:04,470 --> 00:10:10,240 Player, youTubePlayer dot, sorry question mark dot javaClass. 126 00:10:10,240 --> 00:10:16,710 And thirdly let's add a Toast message here, so Toast.makeText parentheses, 127 00:10:16,710 --> 00:10:22,860 this, is the context, and the text we want to display will be "Initialized 128 00:10:22,860 --> 00:10:33,290 Youtube Player successfully", that's going to be Toast, Toast. 129 00:10:33,290 --> 00:10:39,250 LENGTH_SHORT this time, parentheses dot show. 130 00:10:39,250 --> 00:10:43,130 And then lastly what we're going to do is put if parentheses, 131 00:10:43,130 --> 00:10:51,900 not wasRestored, then we're going to do a youTubePlayer question mark dot cueVideo. 132 00:10:51,900 --> 00:10:58,720 Then we're going to, in there, we're going to type YOUTUBE_VIDEO_ID. Alright so I've used our normal logging, 133 00:10:58,720 --> 00:11:04,300 and whenever you get an object that's a parameter, you can use this dot javaClass as you can see me using on lines 134 00:11:04,300 --> 00:11:10,080 41 and 42, to find out what kind of object it is. And we'll display a Toast message so that the user knows 135 00:11:10,080 --> 00:11:15,220 that everything's going well so far, and then show the video using the ID we got earlier. 136 00:11:15,220 --> 00:11:21,250 Now as we saw in the documentation, we only want to play a new video if the player isn't resuming playback of 137 00:11:21,250 --> 00:11:26,620 an existing one, so the code check on line 45 checks that wasRestored is false 138 00:11:26,620 --> 00:11:33,570 first. Now to play the video, we call the cueVideo function and provide it with the ID of a video, 139 00:11:33,570 --> 00:11:37,760 and I've used the ID that we copied from the URL from the YouTube site in the previous video. 140 00:11:37,760 --> 00:11:39,840 Now there's a bit more we could do in here, 141 00:11:39,840 --> 00:11:44,680 and in the next video we'll start adding some code to monitor the various events that happen when the 142 00:11:44,680 --> 00:11:49,720 video starts playing. But let's actually see it running first, just before we end the video. 143 00:11:49,720 --> 00:11:52,500 So I'm going to run this time, on the Nexus 5 emulator, so 144 00:11:52,500 --> 00:11:58,860 what I'll do is, I'll just close down this old emulator, and then I'm going to run it. 145 00:11:58,860 --> 00:12:05,740 Then I'm going to select my Nexus 5X API 26, remembering that this particular build includes the YouTube 146 00:12:05,740 --> 00:12:15,620 apps, so our apps should run this time, and we'll just give the emulator time to start up, and then our app should automatically start. 147 00:12:15,620 --> 00:12:20,220 I can see our message there, initialized YouTube successfully. There's my video, and 148 00:12:20,220 --> 00:12:26,210 let's just try that again because we might have had an issue because it was starting the device when I started 149 00:12:26,210 --> 00:12:33,760 the app, so go back and try it again. We're initialized as you can see at the bottom, so that was working fine. 150 00:12:33,760 --> 00:12:40,720 And again I can actually run the, start the video, and you see that is actually working fine, and I can 151 00:12:40,720 --> 00:12:46,540 pause the video as you can see there, pause, and I can resume it and it starts in the same place. 152 00:12:46,540 --> 00:12:48,120 So that's working nicely. 153 00:12:48,120 --> 00:12:52,570 Now if you can't run these emulators on your computer for whatever reason, then connect your Android device 154 00:12:52,570 --> 00:12:55,840 up and test your app on a physical Android device. 155 00:12:55,840 --> 00:13:01,200 Alright so let's finish the video here. In the next video, now that we've got the app running and the 156 00:13:01,200 --> 00:13:03,070 Toast message is working OK, 157 00:13:03,070 --> 00:13:07,960 let's actually have a go at adding some listeners to the YouTube Player, just so we can get some feedback 158 00:13:07,960 --> 00:13:11,180 when various things happen. So I'll see you in the next video.