1 00:00:05,300 --> 00:00:09,660 Alright so now what we want to do is start adding some listeners to our YouTube Player, 2 00:00:09,880 --> 00:00:12,830 so that we can get some feedback when various things happen. 3 00:00:12,920 --> 00:00:18,260 Now the YouTube Player can respond to a number of different events, things like a video playing, pausing, 4 00:00:18,260 --> 00:00:24,860 or being stopped, and can also notify us when the ads that appear at the start of many YouTube videos, start to play. 5 00:00:24,860 --> 00:00:30,380 Now Google have separated these into two different types of events: events that are associated with the playing 6 00:00:30,380 --> 00:00:34,710 of a video, and those that represent a change in the state of the video. 7 00:00:35,060 --> 00:00:38,850 Now this'll make more sense when you see the two listeners that we're going to create. 8 00:00:38,960 --> 00:00:41,620 So I'm going to go ahead with the code and talk about it afterwards, 9 00:00:41,660 --> 00:00:48,090 but firstly what we want to do is create a new playbackEventListener, to handle the playback events. 10 00:00:48,180 --> 00:00:52,850 So what I'm going to do is put that after the onInitializationFailure function. 11 00:00:52,870 --> 00:00:54,230 Down here I'm going to put private val 12 00:00:56,870 --> 00:01:08,350 playback event listener equals object colon YouTubePlayer.Playback 13 00:01:08,360 --> 00:01:12,450 EventListener, and I'm going to add a code block. 14 00:01:12,470 --> 00:01:15,000 Now the playbackEventListener is an interface, 15 00:01:15,170 --> 00:01:18,480 so we have to implement all the methods defined by that interface, 16 00:01:18,530 --> 00:01:22,940 and that's why we've actually got this error over here at the moment, that "object is not abstract and doesn't 17 00:01:22,940 --> 00:01:29,030 implement the abstract member for onSeek". As always Android Studio can automatically create a stub for each 18 00:01:29,030 --> 00:01:30,990 of the functions that we have to implement. 19 00:01:31,240 --> 00:01:36,830 So I'm going to make sure my cursor is inside the code block and do a control I, and I'm going to select all the 20 00:01:36,830 --> 00:01:39,000 methods and click on OK. 21 00:01:39,690 --> 00:01:45,380 And you can see now that we've done that, the error that was an object is now disappeared. Now so that we can 22 00:01:45,380 --> 00:01:51,940 see these methods being called, what I'm going to do is add a Toast message to the onPlaying and onPaused methods. 23 00:01:52,070 --> 00:01:57,080 We're not going to be using the onSeek and onBuffered functions, but we will have to delete the call to TODO, 24 00:01:57,200 --> 00:01:59,980 otherwise our app's going to crash when those functions get called. 25 00:02:00,190 --> 00:02:04,880 So let's go ahead and do that, so we're going to delete this one here, onSeek, delete that, 26 00:02:04,910 --> 00:02:09,820 and also onBuffering, we'll delete, and also onStopped, we'll delete. 27 00:02:10,169 --> 00:02:15,650 Well that leaves the two here, the first one in onPlaying, we will use that, and I'm going to make a Toast message, 28 00:02:15,650 --> 00:02:20,170 so Toast.makeText parentheses, pass 29 00:02:20,180 --> 00:02:24,410 this as the context. But we're going to do something slightly different, we're going to put at, and notice that 30 00:02:24,490 --> 00:02:27,280 there's an option there, this, and then this at YoutubeActivity. 31 00:02:27,290 --> 00:02:29,130 So I'm going to select that second option, 32 00:02:29,430 --> 00:02:35,240 comma double quotes, "Good video is playing OK", and 33 00:02:35,530 --> 00:02:41,250 then Toast.LENGTH_SHORT and new parentheses dot show. 34 00:02:41,630 --> 00:02:48,080 So that's the first one for onPlaying, and let's replace the onPaused with the same code but just change 35 00:02:48,080 --> 00:02:51,850 the text a little bit. Instead of putting "Good video is was playing OK", 36 00:02:51,890 --> 00:02:54,990 we'll put "Video has paused". 37 00:02:55,670 --> 00:02:59,990 So what we've got here is just a listener, like we've attached to buttons for example. 38 00:02:59,990 --> 00:03:04,910 Now I've declared it this way because there's quite a lot of code, and it would look very messy if we added 39 00:03:04,940 --> 00:03:07,830 all this code to the function calls that set the listeners. 40 00:03:08,090 --> 00:03:14,180 So this listener provides the YouTubePlayer with functions that it'll call when the various events happen. 41 00:03:14,330 --> 00:03:19,880 And when a video starts playing for example, it'll call the onPlaying function, and onPaused if we 42 00:03:19,880 --> 00:03:21,720 pause the video, and so on. 43 00:03:21,830 --> 00:03:26,390 So it's really up to you as to what you want to do with these functions. They're not required for the player 44 00:03:26,390 --> 00:03:32,780 to play videos, but this could be an app, perhaps, providing a company's training course for example. 45 00:03:32,780 --> 00:03:37,610 And in that case you could record the fact that the user has watched a video and how far they are through it, 46 00:03:37,910 --> 00:03:42,370 and maybe record it on their employee training plan by adding code in the onStop method. 47 00:03:42,710 --> 00:03:46,940 There's another event that we'll look at next that you could use to record that they'd actually watched 48 00:03:46,940 --> 00:03:48,530 the entire video. 49 00:03:48,530 --> 00:03:55,500 Now the YouTube Player's API is tracking the playback of the video, and giving us the ability to process events when they happen. 50 00:03:55,760 --> 00:04:01,660 So that's the playbackEventListener. So let's actually add the StateChangeListener and see what that does now: 51 00:04:02,390 --> 00:04:16,790 private val playerStateChangeListener equals object colon. This time it's going to be YouTubePlayer.Player 52 00:04:18,120 --> 00:04:22,730 as PlayerStateChangeListener, and now the code block, 53 00:04:23,260 --> 00:04:26,740 and we're going to use control I, making sure your cursor's inside the code block. 54 00:04:26,990 --> 00:04:33,190 We're going to implement all the functions, which then stops the error from appearing now. And we're 55 00:04:33,190 --> 00:04:33,200 going 56 00:04:33,200 --> 00:04:37,230 to actually add some Toast messages to three of them, just so you can see when they're called. 57 00:04:37,370 --> 00:04:39,620 So onAdStarted, let's start with that one, 58 00:04:42,440 --> 00:04:47,840 and I'll paste the old Toast message in, leaving the 'this' at YoutubeActivity, and I'm going to change the 59 00:04:47,840 --> 00:04:58,990 text though for that to be "Click Ad now, make the video creator rich!". OK ,and I'll just take a copy of that. 60 00:04:59,050 --> 00:05:03,550 Now onLoading, we won't bother with that so I'll just delete the TODO in there for that. 61 00:05:03,740 --> 00:05:06,000 onVideoStarted, let's do something for that one. 62 00:05:06,000 --> 00:05:08,660 I'm going to replace that with the Toaster.makeText, 63 00:05:08,920 --> 00:05:13,330 but in terms of the actual text that we're going to display on the screen and the Toast message, we'll 64 00:05:13,330 --> 00:05:19,370 just make it "Video has started". OK so that leaves a few more, so we've still got 65 00:05:19,940 --> 00:05:23,290 onLoaded here, onLoaded we'll delete for now, 66 00:05:23,470 --> 00:05:29,830 so it's got no TODO, onVideoEnded, that's a good spot for another one so let's change the code for that. I'm going to 67 00:05:29,830 --> 00:05:37,450 change the text for that, and the text for the onVideoEnded will be "Congratulations, 68 00:05:41,420 --> 00:05:45,230 "Congratulations! You've completed another video". 69 00:05:46,540 --> 00:05:50,890 OK, we've got one error. Let's delete the code on our error as well. 70 00:05:50,890 --> 00:05:53,680 Now to get a better idea on what these functions are all about, 71 00:05:53,680 --> 00:05:59,050 let's switch back to the Google documentation page of my browser, and I really do recommend that you 72 00:05:59,050 --> 00:06:00,320 actually do this. 73 00:06:00,370 --> 00:06:05,050 Check out the documentation to find out more about the functions you use, because that's how you really 74 00:06:05,050 --> 00:06:06,630 get the hang of what's going on. 75 00:06:06,910 --> 00:06:11,440 And you'll also find out about other things you can do, like that error dialogue that we saw when we looked 76 00:06:11,440 --> 00:06:17,290 at the documentation for the initialization results. Now on the left hand side here, is a table, a sort 77 00:06:17,290 --> 00:06:21,600 of a table of contents for YouTubePlayer, and there's the PlaybackEventListener. 78 00:06:21,820 --> 00:06:26,500 And there it is there, so I'm going to click on that now, PlaybackEventListener, and once I've clicked that, that gives us a 79 00:06:26,500 --> 00:06:29,530 bit of an overview of what the various functions do. 80 00:06:29,710 --> 00:06:32,770 And you probably could have guessed most of this from the names of the functions, 81 00:06:32,770 --> 00:06:37,840 but it's interesting that the onStop method in the PlaybackEventListener's also called then. 82 00:06:38,050 --> 00:06:43,150 So that implies we should get both functions called when the video plays all the way to the end. 83 00:06:43,150 --> 00:06:48,670 Now it's subtle things like this that you'll find out when you read the documentation. Method names and parameters 84 00:06:48,670 --> 00:06:52,330 are generally well chosen and will give you a good idea of what they do, 85 00:06:52,420 --> 00:06:54,020 but you'll only get the full picture 86 00:06:54,100 --> 00:06:58,890 by doing research on line, and the documentation's a great place to start with that. 87 00:06:59,110 --> 00:07:04,030 So after reading that, what I'm going to do is add a Toast message to the onStopped method as well, so 88 00:07:04,030 --> 00:07:05,240 that we can see if we're right 89 00:07:05,260 --> 00:07:14,150 and both methods get called. So back to the onStopped method, and let's paste in some code there, and we'll put "Video has stopped" 90 00:07:14,150 --> 00:07:14,690 there as well. 91 00:07:18,310 --> 00:07:21,880 Alright so we've now set up the listeners that'll respond to the various events, 92 00:07:22,130 --> 00:07:25,160 but at this point we haven't yet told the player to call them. 93 00:07:25,280 --> 00:07:28,410 In fact, Android Studio is showing our two variables in grey, as 94 00:07:28,430 --> 00:07:31,220 you can see here, and also the one further up, 95 00:07:32,160 --> 00:07:34,170 to indicate that they're not actually used anywhere. 96 00:07:34,680 --> 00:07:40,110 So what we need to do is, in the onInitializationSuccess function, we just call set functions 97 00:07:40,110 --> 00:07:44,590 and tell the player where to find the functions you'll need to call back when the events happen. 98 00:07:44,610 --> 00:07:49,560 So we're going to do that in the onInitializationSuccess as I mentioned, and where we want to put this 99 00:07:49,560 --> 00:07:52,150 is before the if not wasRestored code. 100 00:07:52,380 --> 00:08:02,040 So in here we're going to put youTubePlayer question mark dot setPlayerStateChangeListener parentheses, and 101 00:08:02,220 --> 00:08:07,920 that's going to be playerStateChangeListener, then youTubePlayer again, 102 00:08:09,060 --> 00:08:14,980 Question mark dot set, this time it's playbackEventListener parentheses, and 103 00:08:15,240 --> 00:08:18,460 it's going to be playbackEventListener. 104 00:08:18,780 --> 00:08:23,670 So that tells the player again where to find the functions that it'll need to call back when those events 105 00:08:23,670 --> 00:08:25,920 are triggered, or actually, when they actually happen. 106 00:08:25,940 --> 00:08:32,010 Now using anonymous classes inside those calls to setPlayerStateChangeListener and setPlayback 107 00:08:32,010 --> 00:08:37,830 EventListener, would have made the code very messy, which is why we declared variables for them instead. 108 00:08:37,830 --> 00:08:42,169 Alright, so let's actually try running the app and seeing our Toast messages appearing: 109 00:08:46,080 --> 00:08:49,710 Initialized successfully, and Video has stopped, as you can see. 110 00:08:49,920 --> 00:08:54,980 Now when I come over here and tap on the play icon, we got a message, as you can see, a Toast message to say 111 00:08:54,980 --> 00:08:59,020 that the 'Video has played', 'Good video is playing OK', appeared as well. 112 00:08:59,140 --> 00:09:04,480 I'm just going to pause for a minute now, and you can see it says 'Video has paused', and if I start it again, 113 00:09:04,710 --> 00:09:07,410 'Good video is playing OK' again, so we've got that message. 114 00:09:07,590 --> 00:09:09,730 Likewise when I pause, we've got 'Video has paused' again. 115 00:09:10,110 --> 00:09:16,960 And if I actually also go forward a little bit, you can see that we've got that message again, and we can play it again, 116 00:09:20,380 --> 00:09:25,190 'Good video is playing OK' as you can see, so it's actually working quite nicely for us. 117 00:09:25,190 --> 00:09:29,770 The other thing I'll do though now, is skip forward to a few seconds from the end, just so you can see what 118 00:09:29,770 --> 00:09:31,410 happens when the video finishes. 119 00:09:31,750 --> 00:09:39,340 So we got to about the 4:16, play, 'Congratulations you've completed another video'. 120 00:09:39,340 --> 00:09:41,750 You saw that appear, and then 'Video has stopped' also. 121 00:09:41,950 --> 00:09:47,090 So we do get both messages as you can see. The onVideoEnded function of the playerStateChangeListener 122 00:09:47,090 --> 00:09:51,680 displays it's Toast, and then we got the Toast from the onStopped function or the playbackEventListener. 123 00:09:51,950 --> 00:09:57,160 Alright so that's how you use the YouTubePlayer API to play videos in your own apps. 124 00:09:57,190 --> 00:10:02,230 Now we haven't had to write a great deal of code to play the videos, because we used Google's YouTube 125 00:10:02,280 --> 00:10:06,110 API to take care of all the technical details for us. 126 00:10:06,130 --> 00:10:11,920 Now we have covered some important concepts though, including how to add an external library to our code, and also 127 00:10:11,920 --> 00:10:18,450 how to write callback functions that external code calls, when it needs to notify our apps of important events. 128 00:10:18,460 --> 00:10:24,040 Now we've seen callbacks earlier, because a button click event also calls a callback function in our 129 00:10:24,040 --> 00:10:28,450 code to let us respond to the button click, and we're going to be using them a lot in the course, so you'll 130 00:10:28,450 --> 00:10:34,330 get plenty of examples of both callbacks and interfaces. And we'll try to explain them differently each time. 131 00:10:34,500 --> 00:10:36,350 If they don't make sense now they soon will. 132 00:10:36,580 --> 00:10:39,820 Alright so in the next video, we need to make a couple of improvements to the app. 133 00:10:39,850 --> 00:10:41,240 So I'll see you in the next video.