1 00:00:04,830 --> 00:00:07,440 In the previous video, we copied the code 2 00:00:07,440 --> 00:00:09,930 from a blank project to add a Snackbar 3 00:00:09,930 --> 00:00:11,880 to our app. In this video, we're going to 4 00:00:11,880 --> 00:00:14,250 look at Snackbars in more detail, and 5 00:00:14,250 --> 00:00:16,500 see how we can make our app a little bit 6 00:00:16,500 --> 00:00:19,500 easier to use. Snackbars were introduced 7 00:00:19,500 --> 00:00:22,020 with Material Design, and are intended as 8 00:00:22,020 --> 00:00:24,390 an alternative to the Toast messages. 9 00:00:24,390 --> 00:00:26,040 Now both Snackbars and Toast 10 00:00:26,040 --> 00:00:28,320 messages can be used to notify the user 11 00:00:28,320 --> 00:00:31,349 of something, in an unobtrusive way. The 12 00:00:31,349 --> 00:00:33,450 user gets to see the message, but the 13 00:00:33,450 --> 00:00:34,950 messages don't interrupt their flow, 14 00:00:34,950 --> 00:00:37,500 and that's unlike a dialogue that has to 15 00:00:37,500 --> 00:00:39,899 be dismissed before you can continue. In 16 00:00:39,899 --> 00:00:41,579 the case of Toast messages and Snack 17 00:00:41,579 --> 00:00:44,039 bars, they appear on the screen, but 18 00:00:44,039 --> 00:00:45,929 shouldn't get in the way and thus can be 19 00:00:45,929 --> 00:00:48,300 ignored. Snackbars are a lot more 20 00:00:48,300 --> 00:00:50,640 versatile than Toast messages. One 21 00:00:50,640 --> 00:00:52,890 problem, actually, with a Toast message is 22 00:00:52,890 --> 00:00:55,500 that they may be easy to miss. There are 23 00:00:55,500 --> 00:00:57,210 only two options for how long a Toast 24 00:00:57,210 --> 00:00:58,859 can stay on the screen; LENGTH 25 00:00:58,859 --> 00:01:00,899 _SHORT and LENGTH 26 00:01:00,899 --> 00:01:03,420 _LONG. Once the specified period has 27 00:01:03,420 --> 00:01:05,519 expired, then the Toast message will 28 00:01:05,519 --> 00:01:07,430 automatically disappear from the screen. 29 00:01:07,430 --> 00:01:09,840 Now in the case of Snackbars, we've got 30 00:01:09,840 --> 00:01:11,580 another value we can use; LENGTH 31 00:01:11,580 --> 00:01:13,860 _INDEFINITE. So what I'm going 32 00:01:13,860 --> 00:01:15,990 to do is change the code, in our 33 00:01:15,990 --> 00:01:17,910 Floating Action Button's onClick method, 34 00:01:17,910 --> 00:01:19,140 and then we're going to have a look at 35 00:01:19,140 --> 00:01:20,760 what this LENGTH_INDEFINITE 36 00:01:20,760 --> 00:01:24,240 does. So I'm down here now - the code here 37 00:01:24,240 --> 00:01:25,950 on line 62. 38 00:01:25,950 --> 00:01:29,340 I'm going to change that to LENGTH_ 39 00:01:29,340 --> 00:01:31,200 INDEFINITE. Now I can bring up the 40 00:01:31,200 --> 00:01:33,210 documentation for our LENGTH_INDEFINITE to 41 00:01:33,210 --> 00:01:34,860 take a look at that. And you've seen this 42 00:01:34,860 --> 00:01:36,630 before with Ctrl_Alt. I can go and 43 00:01:36,630 --> 00:01:39,390 have a check, I can click and select the 44 00:01:39,390 --> 00:01:41,400 source code and we can see the comments 45 00:01:41,400 --> 00:01:43,950 above there, talking about what it is - how it 46 00:01:43,950 --> 00:01:46,340 shows the Snackbar, unsurprisingly, 47 00:01:46,340 --> 00:01:49,350 indefinitely. And basically, the Snackbar 48 00:01:49,350 --> 00:01:51,390 will be displayed, from the time that 49 00:01:51,390 --> 00:01:53,340 it's shown until either it's dismissed, 50 00:01:53,340 --> 00:01:56,070 or another Snackbar is shown, which will 51 00:01:56,070 --> 00:01:58,410 then replace it. So in this case, that's 52 00:01:58,410 --> 00:01:59,940 very good. It's going to allow us to 53 00:01:59,940 --> 00:02:01,290 leave that message on the screen until 54 00:02:01,290 --> 00:02:03,300 the user dismisses it, or there's another 55 00:02:03,300 --> 00:02:05,880 Snackbar message shown. And you've 56 00:02:05,880 --> 00:02:07,320 probably worked this out by now, but 57 00:02:07,320 --> 00:02:09,690 notice that the comments - when we go into 58 00:02:09,690 --> 00:02:12,090 the source code - appear above the code 59 00:02:12,090 --> 00:02:13,890 they refer to. So make sure you do read 60 00:02:13,890 --> 00:02:15,750 the right comment. Otherwise, things can 61 00:02:15,750 --> 00:02:16,800 get confusing if you're looking down 62 00:02:16,800 --> 00:02:18,030 here, for example, 63 00:02:18,030 --> 00:02:19,560 and wandering Does that apply to LENGTH 64 00:02:19,560 --> 00:02:21,150 _INDEFINITE? which is not the case. 65 00:02:21,150 --> 00:02:22,680 Alright, so I'm going to close down 66 00:02:22,680 --> 00:02:25,800 that Snackbar.java code now. By the way, 67 00:02:25,800 --> 00:02:27,390 we could have got a similar result by 68 00:02:27,390 --> 00:02:29,490 just opening the documentation, and 69 00:02:29,490 --> 00:02:30,690 getting the information up that way, 70 00:02:30,690 --> 00:02:32,250 which you've seen in previous videos as 71 00:02:32,250 --> 00:02:35,040 well. Alright, so let's run the app, and 72 00:02:35,040 --> 00:02:36,240 see what happens now we've got this 73 00:02:36,240 --> 00:02:38,100 indefinite setting, LENGTH_ 74 00:02:38,100 --> 00:02:46,950 INDEFINITE set. Alright, so I'm gonna 75 00:02:46,950 --> 00:02:50,640 click on DENY here this time. This time 76 00:02:50,640 --> 00:02:52,290 now when I open, or click on 77 00:02:52,290 --> 00:02:54,900 the FAB, notice now that the Snackbar 78 00:02:54,900 --> 00:02:56,670 message doesn't disappear automatically. 79 00:02:56,670 --> 00:02:58,470 But if you do want to dismiss a Snack 80 00:02:58,470 --> 00:03:00,750 bar, just swipe it right and it'll 81 00:03:00,750 --> 00:03:02,010 vanish from the screen, and you can see me 82 00:03:02,010 --> 00:03:04,770 doing that now. So that's pretty cool, but 83 00:03:04,770 --> 00:03:07,500 they can get even better. So instead of 84 00:03:07,500 --> 00:03:09,720 just showing the user a message, I think 85 00:03:09,720 --> 00:03:11,430 it'd be nice if we could provide them 86 00:03:11,430 --> 00:03:13,770 with a way to grant the access at the 87 00:03:13,770 --> 00:03:16,230 same time rather, than just telling them 88 00:03:16,230 --> 00:03:19,230 that they need to grant that access. The 89 00:03:19,230 --> 00:03:21,390 good news here is that Snackbars can 90 00:03:21,390 --> 00:03:23,790 contain a clickable link. So as well as 91 00:03:23,790 --> 00:03:25,560 displaying the message, they can also 92 00:03:25,560 --> 00:03:28,140 behave like a button and allow us to 93 00:03:28,140 --> 00:03:30,330 provide some extra functionality. So to 94 00:03:30,330 --> 00:03:32,459 do that, going back to our code, what we need 95 00:03:32,459 --> 00:03:34,320 to do is add some code here, in the 96 00:03:34,320 --> 00:03:36,150 listener, and you can see we've currently 97 00:03:36,150 --> 00:03:38,430 got that set to null. So I'm just going 98 00:03:38,430 --> 00:03:40,769 to delete that, and enter a left curly 99 00:03:40,769 --> 00:03:42,120 brace, which adds the right one 100 00:03:42,120 --> 00:03:44,760 automatically. Press ENTER, and I'm going 101 00:03:44,760 --> 00:03:46,980 to type in some code now. So this would 102 00:03:46,980 --> 00:03:48,930 be the code that we executed, if the 103 00:03:48,930 --> 00:03:52,019 Snackbar button itself is tapped. So I'm 104 00:03:52,019 --> 00:03:53,790 going to just put a Toast message in 105 00:03:53,790 --> 00:03:57,570 there. So Toast.makeText parenthesis 106 00:03:57,570 --> 00:04:02,579 it.context comma, and I'm just 107 00:04:02,579 --> 00:04:04,070 going to put a message there; Snackbar 108 00:04:04,070 --> 00:04:08,370 action clicked comma. And it's going to be Toast 109 00:04:08,370 --> 00:04:11,820 dot LENGTH_SHORT and right 110 00:04:11,820 --> 00:04:15,600 parenthesis and dot show. Now I'm 111 00:04:15,600 --> 00:04:16,978 not suggesting that you should show a 112 00:04:16,978 --> 00:04:19,168 Toast message from a Snackbar here. I'm 113 00:04:19,168 --> 00:04:20,820 only doing that here so we can see the 114 00:04:20,820 --> 00:04:22,620 action being called. We'll actually do 115 00:04:22,620 --> 00:04:24,360 something more useful with the action, in 116 00:04:24,360 --> 00:04:24,990 a moment. 117 00:04:24,990 --> 00:04:26,520 So let's actually run this, though, just 118 00:04:26,520 --> 00:04:28,080 to see what it does - make sure that it 119 00:04:28,080 --> 00:04:34,090 works. 120 00:04:34,090 --> 00:04:37,880 So I can click on DENY, click on the 121 00:04:37,880 --> 00:04:41,210 Floating Action Button, and that stays 122 00:04:41,210 --> 00:04:42,800 there because we've using the LENGTH 123 00:04:42,800 --> 00:04:44,990 _INDEFINITE. And now if I click 124 00:04:44,990 --> 00:04:47,900 on the action button, you can see we've 125 00:04:47,900 --> 00:04:49,130 got our Toast message showing up on the 126 00:04:49,130 --> 00:04:50,720 screen there. So clearly, the action was 127 00:04:50,720 --> 00:04:53,510 invoked after we clicked it. Now I actually 128 00:04:53,510 --> 00:04:55,669 had a reason for showing you that, and 129 00:04:55,669 --> 00:04:56,960 the reason was that when we create a 130 00:04:56,960 --> 00:04:58,520 Toast message, we have to provide a 131 00:04:58,520 --> 00:05:02,690 Context to the makeText function. You 132 00:05:02,690 --> 00:05:05,090 can see that code there, on line 65. The 133 00:05:05,090 --> 00:05:07,310 onClick method gets passed a reference 134 00:05:07,310 --> 00:05:09,590 to the View that was clicked. But because 135 00:05:09,590 --> 00:05:11,990 we're using Kotlin rather than Java, and 136 00:05:11,990 --> 00:05:14,000 implementing the onClick method with a 137 00:05:14,000 --> 00:05:16,669 lambda, Kotlin allows us to admit the 138 00:05:16,669 --> 00:05:19,190 parameter declaration. So instead of us 139 00:05:19,190 --> 00:05:21,110 explicitly declaring the parameter, 140 00:05:21,110 --> 00:05:23,600 Kotlin does it for us, and uses the 141 00:05:23,600 --> 00:05:25,430 symbol it - you can see I've typed it. 142 00:05:25,430 --> 00:05:27,889 context there. So basically, that's why we 143 00:05:27,889 --> 00:05:30,139 can refer to it.context as an argument 144 00:05:30,139 --> 00:05:33,080 to makeText. Now the other thing that 145 00:05:33,080 --> 00:05:35,539 may not be obvious, is that a View has a 146 00:05:35,539 --> 00:05:37,610 Context, and that's the other thing I 147 00:05:37,610 --> 00:05:39,830 wanted to demonstrate by using a Toast 148 00:05:39,830 --> 00:05:41,600 message here. Sometimes you might 149 00:05:41,600 --> 00:05:43,669 struggle to get a Context easily - in an 150 00:05:43,669 --> 00:05:46,190 Adapter, for example. Now if you find you 151 00:05:46,190 --> 00:05:48,320 need one in a ClickListener, you can 152 00:05:48,320 --> 00:05:50,419 often use the Context of the view 153 00:05:50,419 --> 00:05:53,210 argument, just like we're doing here. And 154 00:05:53,210 --> 00:06:02,270 again, just to confirm - run it again. Click 155 00:06:02,270 --> 00:06:03,900 on Deny, 156 00:06:03,900 --> 00:06:05,010 and this time you can see over here, 157 00:06:05,010 --> 00:06:07,020 there's an Action - Action text is 158 00:06:07,020 --> 00:06:08,340 appearing on the right-hand side there. 159 00:06:08,340 --> 00:06:10,440 Now that text comes from the text 160 00:06:10,440 --> 00:06:12,330 specified in the setAction method, and 161 00:06:12,330 --> 00:06:15,450 when I tap it, you can see we 162 00:06:15,450 --> 00:06:17,220 get our Toast message showing on 163 00:06:17,220 --> 00:06:19,290 the screen there. Now one common error 164 00:06:19,290 --> 00:06:21,570 that that people often make, is to forget 165 00:06:21,570 --> 00:06:24,210 to call the dot show at the end of 166 00:06:24,210 --> 00:06:26,820 Toast.makeText, and that applies when 167 00:06:26,820 --> 00:06:28,770 displaying Snackbar and Toast messages. 168 00:06:28,770 --> 00:06:31,170 Now Android Studio does warn you if you 169 00:06:31,170 --> 00:06:33,030 do that, but if you don't see the Toast 170 00:06:33,030 --> 00:06:35,130 message, make sure you've got dot show at 171 00:06:35,130 --> 00:06:37,530 the end there, in parentheses, as I've got. So 172 00:06:37,530 --> 00:06:39,270 the code for displaying Snackbars and 173 00:06:39,270 --> 00:06:41,700 Toast messages look very similar. You 174 00:06:41,700 --> 00:06:43,710 make a Snackbar or a Toast and then 175 00:06:43,710 --> 00:06:45,780 call the show method. Now there's really 176 00:06:45,780 --> 00:06:47,940 not a great deal more to say about Snack 177 00:06:47,940 --> 00:06:50,220 bars. We can check the documentation by 178 00:06:50,220 --> 00:06:51,570 clicking on Snackbar, which I can do 179 00:06:51,570 --> 00:06:55,980 over here. And you can see it says that Snack 180 00:06:55,980 --> 00:06:58,260 bars provide lightweight feedback about 181 00:06:58,260 --> 00:07:00,360 an operation. They show a brief message 182 00:07:00,360 --> 00:07:02,610 at the bottom of the screen on mobile, 183 00:07:02,610 --> 00:07:05,280 and lower left on larger devices. Snack 184 00:07:05,280 --> 00:07:08,220 bars appear above all other elements on 185 00:07:08,220 --> 00:07:09,780 screen, and only one can be 186 00:07:09,780 --> 00:07:11,880 displayed at a time. And also, they 187 00:07:11,880 --> 00:07:13,620 automatically disappear after a timeout 188 00:07:13,620 --> 00:07:15,780 or after using interaction elsewhere on 189 00:07:15,780 --> 00:07:17,370 the screen, particularly after 190 00:07:17,370 --> 00:07:18,960 interactions that summon a new surface 191 00:07:18,960 --> 00:07:21,240 or activity. And as you saw, they can also 192 00:07:21,240 --> 00:07:23,580 be swiped off the screen. Now it's also 193 00:07:23,580 --> 00:07:26,250 possible to be called back when a Snack 194 00:07:26,250 --> 00:07:28,200 bar is shown or dismissed, if you need to 195 00:07:28,200 --> 00:07:30,450 check that. Alright, so we've got the 196 00:07:30,450 --> 00:07:32,880 ability to respond when a user clicks 197 00:07:32,880 --> 00:07:35,280 the Action link. What we can do, is 198 00:07:35,280 --> 00:07:37,920 present the user with the dialogue to 199 00:07:37,920 --> 00:07:40,350 grant access. And that's pretty easy - we 200 00:07:40,350 --> 00:07:41,940 just call the requestPermission method 201 00:07:41,940 --> 00:07:43,860 again - but what if they've permanently 202 00:07:43,860 --> 00:07:44,730 denied access. 203 00:07:44,730 --> 00:07:47,190 So in that case, calling request 204 00:07:47,190 --> 00:07:48,870 Permissions won't pop up the dialogue 205 00:07:48,870 --> 00:07:51,120 again. What we can do in that case, is 206 00:07:51,120 --> 00:07:53,400 take them into the Settings for our app, 207 00:07:53,400 --> 00:07:55,560 so that they can grant the access that 208 00:07:55,560 --> 00:07:58,290 we need. Now unfortunately, Google doesn't 209 00:07:58,290 --> 00:08:00,210 allow a way to go all the way into their 210 00:08:00,210 --> 00:08:02,340 permissions, but we can get them as far 211 00:08:02,340 --> 00:08:04,950 as our app's settings. So let's see how 212 00:08:04,950 --> 00:08:06,450 that's going to work before we write the 213 00:08:06,450 --> 00:08:08,400 code to do it. I'm going to switch over 214 00:08:08,400 --> 00:08:10,680 and show you a finished version of this 215 00:08:10,680 --> 00:08:13,260 app in my API 27 emulator, 216 00:08:13,260 --> 00:08:16,200 just so that we can see what's it's 217 00:08:16,200 --> 00:08:20,550 actually going to do. 218 00:08:20,550 --> 00:08:22,530 Okay, so I'm running the final version, as 219 00:08:22,530 --> 00:08:24,919 you can see on screen now, and we get the 220 00:08:24,919 --> 00:08:27,539 normal dialogue to grant access - and that's 221 00:08:27,539 --> 00:08:30,270 as we've already seen in our app. So I'm 222 00:08:30,270 --> 00:08:35,070 gonna click on Deny access, and now when 223 00:08:35,070 --> 00:08:37,289 I tap the Floating Action Button, we get 224 00:08:37,289 --> 00:08:38,610 a Snackbar and there's now an option 225 00:08:38,610 --> 00:08:41,370 here to grant access. So if I tap that 226 00:08:41,370 --> 00:08:44,670 Action, you notice that the pop-up came 227 00:08:44,670 --> 00:08:48,029 up again. And I can click on Allow, just 228 00:08:48,029 --> 00:08:49,920 to confirm that that does work, and we 229 00:08:49,920 --> 00:08:51,360 can now see our contacts when we run it. 230 00:08:51,360 --> 00:08:53,670 So that's a definite improvement - 231 00:08:53,670 --> 00:08:56,279 rather than just a message, the user can 232 00:08:56,279 --> 00:08:58,320 grant access when they attempt to use 233 00:08:58,320 --> 00:09:00,209 the functionality. As google 234 00:09:00,209 --> 00:09:01,529 explain in the documentation, that 235 00:09:01,529 --> 00:09:03,180 you'll be reading when we 236 00:09:03,180 --> 00:09:05,790 finish this app, users sometimes refuse 237 00:09:05,790 --> 00:09:08,610 access because they don't understand why 238 00:09:08,610 --> 00:09:11,010 it's being requested. When they come to 239 00:09:11,010 --> 00:09:12,600 use a feature that requires the access, 240 00:09:12,600 --> 00:09:14,820 they're much more likely to understand 241 00:09:14,820 --> 00:09:16,980 why they're being asked for it, and so 242 00:09:16,980 --> 00:09:19,320 therefore, more likely to grant it. But 243 00:09:19,320 --> 00:09:21,630 what happens if they refuse access, and 244 00:09:21,630 --> 00:09:24,240 tick the box not to be bothered again? So 245 00:09:24,240 --> 00:09:25,730 what I'm going to do now is go into 246 00:09:25,730 --> 00:09:32,930 settings for this app - let's go and do that. 247 00:09:32,930 --> 00:09:35,070 I'm gonna go into our Content Provider, 248 00:09:35,070 --> 00:09:38,790 into Permissions, and I click, and turn this off. 249 00:09:38,790 --> 00:09:41,459 So I'm going to revoke access, or revoke 250 00:09:41,459 --> 00:09:43,290 that permission, so that when we want to 251 00:09:43,290 --> 00:09:45,360 run it again now, we should find it'll 252 00:09:45,360 --> 00:09:50,339 ask us for permission again. So it's 253 00:09:50,339 --> 00:09:51,720 asking us for permission again, because 254 00:09:51,720 --> 00:09:53,700 we've revoked access. So this time I 255 00:09:53,700 --> 00:09:55,709 gonna click on the Don't ask again, and 256 00:09:55,709 --> 00:09:59,130 I'm going to click on Deny. Now that I've 257 00:09:59,130 --> 00:10:01,350 done that, when I'm gonna click on our Floating 258 00:10:01,350 --> 00:10:04,829 Action Button. So we get the Snackbar as 259 00:10:04,829 --> 00:10:07,860 before. This time, though, when I click 260 00:10:07,860 --> 00:10:11,040 over here on Grant Access, notice that 261 00:10:11,040 --> 00:10:12,720 it goes straight into the app Settings 262 00:10:12,720 --> 00:10:15,360 for our Content Provider Example app. And 263 00:10:15,360 --> 00:10:17,160 unfortunately, as I mentioned, this is as 264 00:10:17,160 --> 00:10:19,589 far as we can get. But the user only has to 265 00:10:19,589 --> 00:10:22,589 tap on the Permissions here, to get into 266 00:10:22,589 --> 00:10:26,399 and grant access. So that might change in 267 00:10:26,399 --> 00:10:28,170 the future as Google gets feedback from 268 00:10:28,170 --> 00:10:30,089 users, but at the moment, that's the best 269 00:10:30,089 --> 00:10:32,010 we can do. So with that said, now that 270 00:10:32,010 --> 00:10:33,360 we've enabled the permission again, 271 00:10:33,360 --> 00:10:34,110 does it 272 00:10:34,110 --> 00:10:38,310 work? I'll go back now, keep going back - 273 00:10:38,310 --> 00:10:40,980 we're back in our app, and you can see 274 00:10:40,980 --> 00:10:43,079 we're accessing the contacts again. So 275 00:10:43,079 --> 00:10:45,209 you can see that that clearly worked. So 276 00:10:45,209 --> 00:10:47,370 that's how our app, ultimately, is going 277 00:10:47,370 --> 00:10:49,200 to work, but obviously, at this point in 278 00:10:49,200 --> 00:10:50,940 time we haven't implemented that code. So 279 00:10:50,940 --> 00:10:52,709 let's stop the video here and in the 280 00:10:52,709 --> 00:10:54,570 next video, we'll actually go ahead and 281 00:10:54,570 --> 00:10:56,970 implement that functionality. So I'll see 282 00:10:56,970 --> 00:10:59,660 you in the next video.