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.

