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.

