1
00:00:05,320 --> 00:00:05,590
Alright,

2
00:00:05,590 --> 00:00:10,600
so we're looking at permissions on Marshmallow and above. The app won't have been granted permission when

3
00:00:10,600 --> 00:00:14,390
it was installed and we have to request permission when the app runs.

4
00:00:14,410 --> 00:00:16,860
So we added a call to check selfPermission in our code,

5
00:00:16,880 --> 00:00:22,570
in the last video, to find out if we have the required permission or not. If the permission hasn't been granted,

6
00:00:22,950 --> 00:00:27,180
and it won't have been the first time the app runs, then we'll get PERMISSION_DENIED 

7
00:00:27,430 --> 00:00:29,100
when we call checkSelfPermission.

8
00:00:29,230 --> 00:00:34,870
So that means we have to request the permission in our code. Now this should be fairly straightforward,

9
00:00:35,320 --> 00:00:41,080
except that the users can deny the permission, and they can also tick a box so that they won't be asked

10
00:00:41,080 --> 00:00:42,080
again.

11
00:00:42,100 --> 00:00:46,990
So the flow chart that I'm putting on the screen now shows the options and the various states that our

12
00:00:46,990 --> 00:00:48,730
code has to handle.

13
00:00:48,850 --> 00:00:54,730
So when we check the permission by calling the checkSelfPermission method, we'll automatically be granted the

14
00:00:54,820 --> 00:00:55,710
permission

15
00:00:55,800 --> 00:01:03,250
on devices running API 22 or earlier. So that bit's easy and there's nothing more we need to do. On

16
00:01:03,250 --> 00:01:04,700
API 23 and above

17
00:01:04,700 --> 00:01:08,350
though, we have to request permission from the user.

18
00:01:08,710 --> 00:01:10,660
Now that's still quite straightforward.

19
00:01:10,660 --> 00:01:16,420
If the user grants the permission, then we can proceed and everything's fine, but the user may decide

20
00:01:16,420 --> 00:01:17,710
to deny the permission.

21
00:01:17,800 --> 00:01:24,670
So let's have a look at what they'll see the first time they're asked to grant the permission. Now if the user allows

22
00:01:24,670 --> 00:01:26,780
the permission, then that's fine,

23
00:01:26,950 --> 00:01:32,650
but if they choose to deny it, we have to decide what we're going to do and how we're going to deal with

24
00:01:32,650 --> 00:01:33,940
the situation.

25
00:01:34,030 --> 00:01:39,010
In some apps you could just disable the particular functionality that requires their permission.

26
00:01:39,490 --> 00:01:40,180
In our app

27
00:01:40,230 --> 00:01:42,190
though, that's not really an option.

28
00:01:42,220 --> 00:01:45,130
All the app does is access the contacts records,

29
00:01:45,130 --> 00:01:49,050
and without the necessary permission to do that it's a bit of a pointless app.

30
00:01:49,120 --> 00:01:54,460
It gets slightly more complicated because the next time the app is launched, after the permission has

31
00:01:54,460 --> 00:01:58,050
been denied, the dialogue offers another choice.

32
00:01:58,210 --> 00:02:02,230
So this time there's a box to tick not to be asked again.

33
00:02:02,400 --> 00:02:08,180
So when the user ticks that box, the only option provided is to then deny the permission.

34
00:02:08,220 --> 00:02:13,530
Now that can be a bit confusing to us as developers, and the documentation doesn't make it very clear

35
00:02:13,530 --> 00:02:14,580
unfortunately.

36
00:02:14,850 --> 00:02:19,610
But when they choose to allow the permission then they won't be asked again.

37
00:02:19,810 --> 00:02:25,080
That's automatic once you've allowed the permission, then it remains allowed unless you go into settings

38
00:02:25,080 --> 00:02:31,680
to change it, and we'll have a look at that later. If the user ticks that box and denies the permission,

39
00:02:31,680 --> 00:02:34,200
they won't be asked to allow it again.

40
00:02:34,320 --> 00:02:38,430
So our app just won't get the permission and we have to cater for that in our code.

41
00:02:38,580 --> 00:02:43,320
And once again, some apps could just disable the particular functionality that needs the permission,

42
00:02:43,800 --> 00:02:47,020
but our contacts app becomes useless without it.

43
00:02:47,280 --> 00:02:54,240
So going back to the flowchart, we can see that the situations where permission is granted are easy to

44
00:02:54,240 --> 00:03:00,660
deal with. We'll leave the situations where permission is denied for now, and we'll come back to that once

45
00:03:00,660 --> 00:03:01,750
we've got the app working.

46
00:03:03,480 --> 00:03:09,290
Alright so let's go back to our code now, and the Android framework provides methods to handle requesting

47
00:03:09,290 --> 00:03:11,820
the permission from the user at runtime.

48
00:03:11,840 --> 00:03:17,550
So the first thing we have to do is check the value we got back from calling checkSelfPermission.

49
00:03:17,690 --> 00:03:23,600
So I'm going to add the code and then we'll go through it. So down here after the log, after the hasReadContact

50
00:03:23,600 --> 00:03:24,440
Permission, our

51
00:03:24,810 --> 00:03:26,480
variables, our variable line.

52
00:03:26,570 --> 00:03:33,230
We could add the code if parentheses hasReadContactPermission,

53
00:03:33,230 --> 00:03:44,570
if that's equal to PackageManager.PERMISSION_GRANTED, then we'll open a code block. And there we're going to put log

54
00:03:44,570 --> 00:03:56,580
dot d parentheses TAG comma and we'll just indicate in the message onCreate colon permission granted. And we're going to put

55
00:03:56,840 --> 00:04:00,160
readGranted is equal to true.

56
00:04:00,170 --> 00:04:04,120
However I'm also going to put a comment here TODO

57
00:04:04,790 --> 00:04:09,100
don't do this!! else,

58
00:04:09,300 --> 00:04:13,140
open up a code block Log.d parentheses

59
00:04:13,150 --> 00:04:17,350
TAG comma in double quotes onCreate colon,

60
00:04:17,829 --> 00:04:22,870
and that's requesting permission, because obviously we got denied.

61
00:04:23,240 --> 00:04:25,230
And that's going to be Activity

62
00:04:25,700 --> 00:04:29,410
Compat.requestPermissions

63
00:04:30,020 --> 00:04:30,840
parentheses

64
00:04:30,860 --> 00:04:36,330
this comma space arrayOf parentheses.

65
00:04:36,680 --> 00:04:41,230
Then it's going to be READ_CONTACTS, then a closing right parentheses comma,

66
00:04:41,840 --> 00:04:43,770
then REQUEST underscore

67
00:04:43,790 --> 00:04:44,440
CODE underscore READ

68
00:04:44,450 --> 00:04:46,330
underscore CONTACTS

69
00:04:46,630 --> 00:04:48,520
then closing right parentheses.

70
00:04:48,890 --> 00:04:54,750
And also take this opportunity to log when the onCreate method finishes. So let's add a log call

71
00:04:54,780 --> 00:05:03,730
down there; Log.d parentheses TAG comma onCreate colon ends.

72
00:05:04,270 --> 00:05:09,190
OK, so looking at the code starting on line 32.

73
00:05:09,290 --> 00:05:11,960
So if the result we got back from calling check

74
00:05:11,970 --> 00:05:17,360
SelfPermission was PERMISSION_GRANTED, then we have the permission we need and we can carry on.

75
00:05:17,570 --> 00:05:19,620
We'll need to know that we have the READ

76
00:05:19,620 --> 00:05:25,400
underscore CONTACTS permission later, before we try to access the contacts when the floating action

77
00:05:25,400 --> 00:05:26,500
button's clicked.

78
00:05:26,650 --> 00:05:30,710
So we're storing true in the readGranted field on line 34.

79
00:05:30,710 --> 00:05:34,840
Now we could just call the checkSelfPermission method every time we need to know if the permission's

80
00:05:34,850 --> 00:05:35,450
granted.

81
00:05:35,630 --> 00:05:37,480
But for now I'm going to store the result.

82
00:05:37,490 --> 00:05:41,100
That's a common thing to do but it's often a bad idea.

83
00:05:41,270 --> 00:05:44,020
So I'm going to demonstrate the problems it can cause us later.

84
00:05:44,330 --> 00:05:49,100
So following on from the code though, if the permission wasn't granted, the else codebook is executed starting

85
00:05:49,100 --> 00:05:50,370
on line 36.

86
00:05:50,410 --> 00:05:56,270
So at that point we need to request the permission, and we can do that by using the compat form of

87
00:05:56,270 --> 00:05:59,520
request permissions and you can say that code on line 37.

88
00:05:59,570 --> 00:06:05,420
Once again there's also a method built into the framework, but that'll only work on API 23 and above.

89
00:06:05,960 --> 00:06:11,780
Earlier devices don't know about this new security model, so they have to use the compatibility versions

90
00:06:11,780 --> 00:06:16,120
of those methods from the android.support.v4.app package.

91
00:06:16,220 --> 00:06:21,040
If you're targeting API 23 and above, the code will be almost the same, but you can leave off the

92
00:06:21,040 --> 00:06:26,440
ContextCompat and ActivityCompat class names when calling the methods.

93
00:06:26,510 --> 00:06:31,440
Now I say almost the same, because you don't have to pass this to the framework methods.

94
00:06:31,850 --> 00:06:37,640
The framework checkSelfPermission is called on the context, and request permissions is called on the

95
00:06:37,640 --> 00:06:38,600
activity,

96
00:06:38,600 --> 00:06:44,540
so there's no need to pass this to provide either the context or the activity. The compatible request

97
00:06:44,550 --> 00:06:47,050
permissions method does need to know the activity though,

98
00:06:47,220 --> 00:06:51,010
and that's why the first parameter is this, again on line 37.

99
00:06:51,290 --> 00:06:57,470
So next we provide an array containing the names of the permissions we were requesting.

100
00:06:57,470 --> 00:07:03,170
Now we only want to request a single permission, but it still has to be provided in a string array because

101
00:07:03,170 --> 00:07:04,950
that's the type of the parameter.

102
00:07:04,970 --> 00:07:07,970
You can check that by clicking on the method name and calling up the documentation,

103
00:07:11,210 --> 00:07:13,070
and you can see we've got permissions here;

104
00:07:13,130 --> 00:07:15,950
it's a string array. Now there's quite a lot of description here in

105
00:07:15,950 --> 00:07:20,400
this documentation, so it's well worth a read to understand how it all works.

106
00:07:20,420 --> 00:07:25,520
You may want to read it after we've got this app working though, because we'll be writing the onRequest

107
00:07:25,520 --> 00:07:31,180
PermissionsResult callback method next, and it may make more sense once you've seen that working code.

108
00:07:31,190 --> 00:07:35,830
Also I suggest you read through the guide that I called up in my browser in the last video.

109
00:07:36,080 --> 00:07:41,930
Now the documentation itself can be a bit confusing, and has resulted in some overly complex code on

110
00:07:41,930 --> 00:07:42,810
the Internet.

111
00:07:42,830 --> 00:07:48,170
Earlier versions of the documentation gave the impression that the app had to call requestPermissions

112
00:07:48,260 --> 00:07:49,660
every time it runs,

113
00:07:49,790 --> 00:07:52,200
which isn't the case as we'll see. 

114
00:07:52,220 --> 00:07:54,040
Once you've seen how we're going to write the code for this app,

115
00:07:54,260 --> 00:07:58,910
read through the documentation and it should all make more sense than trying to work from the documents

116
00:07:58,910 --> 00:08:00,330
alone.

117
00:08:00,390 --> 00:08:02,930
OK so the final parameter to requestPermissions

118
00:08:02,950 --> 00:08:07,850
is a result code and I've used a constant that I created earlier. Go back to our code,

119
00:08:07,850 --> 00:08:08,880
this one here.

120
00:08:09,420 --> 00:08:14,150
So the reason for that constant is because when you call the requestPermissions method you don't get

121
00:08:14,150 --> 00:08:14,730
the result

122
00:08:14,730 --> 00:08:21,080
back straight away. The system pops up a dialog, or the dialog, that we saw in the slides earlier, to ask

123
00:08:21,080 --> 00:08:22,970
the user to grant the permissions.

124
00:08:23,190 --> 00:08:29,190
Now if our onCreate method waited for the user to either grant or deny the request,

125
00:08:29,250 --> 00:08:34,590
then our app would be blocking and that's almost always never a good idea with an Android application.

126
00:08:34,679 --> 00:08:38,929
Now we discussed that when we were looking at async tasks in the top 10 Downloader and Flickrbrowser

127
00:08:38,929 --> 00:08:44,090
apps. It's not a good idea for our apps to block the UI thread and prevent the users from answering their

128
00:08:44,090 --> 00:08:45,180
phones.

129
00:08:45,250 --> 00:08:51,110
So instead, the Android framework displays the dialog and the requestPermissions method returns immediately.

130
00:08:51,770 --> 00:08:54,540
To find out whether the permission was granted or denied,

131
00:08:54,680 --> 00:09:00,890
what we have to do is implement a callback method that will be called once the user has made the decision.

132
00:09:00,920 --> 00:09:02,350
So let's actually write that,

133
00:09:02,420 --> 00:09:05,200
and we'll put this straight after the onCreate method.

134
00:09:05,400 --> 00:09:06,340
So I'm going to come down here,

135
00:09:07,240 --> 00:09:11,500
and start it immediately below the onCreate method as I said.

136
00:09:11,500 --> 00:09:13,810
Now we can get Android Studio to generate the stub for us, so

137
00:09:13,810 --> 00:09:20,870
I'm going to do a control o here, then we'll do a search for onRequest - I'm just typing onRequestPermissionsResults.

138
00:09:21,010 --> 00:09:27,380
As soon as we find the one we want, press enter there, and add the stub. I'm going to type this code in and

139
00:09:27,550 --> 00:09:28,080
then talk about it.

140
00:09:28,080 --> 00:09:31,750
For now I'm going to delete that first line, that super call, and I'm going to add a log there,

141
00:09:31,840 --> 00:09:38,560
log entry, Log.d parentheses TAG comma double quotes onRequestPermissionsResult

142
00:09:41,150 --> 00:09:53,550
colon starts. Then we're going to do when parentheses requestCode code block. We're going to do REQUEST_CODE_READ

143
00:09:53,560 --> 00:09:56,540
underscore CONTACTS dash greater than sign,

144
00:09:56,760 --> 00:09:59,080
then a left and right curly brace.

145
00:09:59,370 --> 00:10:09,180
Then within there we're going to put readGranted equals if parentheses grantResults

146
00:10:09,720 --> 00:10:21,180
dot isNotEmpty, and grantResults, left and right square braces and then zero, so index 0 is equal to

147
00:10:21,750 --> 00:10:23,600
PackagerManager dot.

148
00:10:23,850 --> 00:10:26,950
PERMISSION_GRANTED, then right parentheses.

149
00:10:26,990 --> 00:10:28,520
Then open a code block there.

150
00:10:28,970 --> 00:10:36,440
So at this point, in terms of our code, we can note here that permission was granted but the error will go away

151
00:10:36,450 --> 00:10:39,700
shortly, so "permission was granted,

152
00:10:41,440 --> 00:10:50,570
Yay" and then "Do the contacts-related task we need to do."

153
00:10:51,860 --> 00:10:53,820
So we're just going to return true there.

154
00:10:54,360 --> 00:10:56,010
Otherwise we'll run else

155
00:10:56,570 --> 00:10:59,550
then the code block again;

156
00:10:59,580 --> 00:11:00,300
"permission denied",

157
00:11:00,350 --> 00:11:04,400
at this point we get to this part of the code, denied, "boo!!"

158
00:11:05,080 --> 00:11:14,660
So we want to "Disable the functionality that depends on this permission".

159
00:11:15,360 --> 00:11:16,950
and we'll just add a log entry there;

160
00:11:17,210 --> 00:11:22,930
Log.d parentheses onRequest, or sorry TAG comma double quotes onRequest

161
00:11:25,470 --> 00:11:34,030
Permission, PermissionsResult colon permission refused.

162
00:11:34,670 --> 00:11:37,820
OK, and what I should probably do there, I put a typo there,

163
00:11:38,760 --> 00:11:46,380
let's also put a log entry there above the true, so we can see whether the permissions were successful

164
00:11:46,380 --> 00:11:46,820
or not.

165
00:11:46,920 --> 00:11:53,610
So we'll put permission granted for that one, and here we're going to return false, so false.

166
00:11:53,670 --> 00:11:56,820
Then right down the bottom here, just before the end of the function,

167
00:11:56,830 --> 00:12:08,040
we're going to put Log.d parentheses TAG comma double quotes onRequestPermissionsResult. PermissionsResult colon 

168
00:12:08,130 --> 00:12:14,400
ends. Now I've lifted this code almost verbatim from a Google training document.

169
00:12:14,420 --> 00:12:15,780
I just want to quickly bring that up on the screen,

170
00:12:22,300 --> 00:12:27,830
and if we scroll down, the section that we're looking for is Handle the permission, the permissions request

171
00:12:27,830 --> 00:12:35,730
response, this part of the code, this is the code here. Now you can see the code is very similar to what's showing in there; it's

172
00:12:35,740 --> 00:12:37,510
almost verbatim.

173
00:12:37,510 --> 00:12:42,060
Now we're going to be adding a bit more to it later, to deal with the permission being denied,

174
00:12:42,190 --> 00:12:45,070
but this will do for now just to get an idea of what's happening.

175
00:12:45,070 --> 00:12:51,010
Basically when Android calls this method for us, it'll pass in the response code that we provided when

176
00:12:51,010 --> 00:12:55,900
we called the requestPermissions method. And going back to our code,

177
00:12:55,970 --> 00:13:02,920
that's what the constant REQUEST_CODE_READ_CONTACTS is for. Now in a larger

178
00:13:02,930 --> 00:13:07,940
app, we may well be requesting several permissions; an app that records video, for example, would need to

179
00:13:07,940 --> 00:13:09,250
get access to the camera,

180
00:13:09,350 --> 00:13:14,990
the microphone and also the storage, so that it can save the video. By providing a unique response

181
00:13:14,990 --> 00:13:17,610
code when calling requestPermissions,

182
00:13:17,690 --> 00:13:21,940
we can tell which particular request we're getting the results back for. Now here

183
00:13:21,980 --> 00:13:23,480
there's only one request,

184
00:13:23,590 --> 00:13:27,420
and we don't need to switch statement to check which one the results apply to,

185
00:13:27,620 --> 00:13:32,310
but it is useful to see how to handle multiple requests from a single activity.

186
00:13:32,660 --> 00:13:34,470
Alright, so that's the request code,

187
00:13:34,490 --> 00:13:37,900
the first parameter. The next one is permissions -

188
00:13:38,020 --> 00:13:41,300
well, actually the next two arguments are both arrays. We've got permissions

189
00:13:41,360 --> 00:13:47,660
and we've also got grantResults as you can see. The first contains the permissions we have requested and the second

190
00:13:47,660 --> 00:13:50,210
contains the result for each permission.

191
00:13:50,270 --> 00:13:56,020
It's possible that the user could grant some permissions and deny others, if we'd requested several at once,

192
00:13:56,030 --> 00:14:00,320
so this allows us to check which ones were accepted and which were denied.

193
00:14:00,320 --> 00:14:05,810
Now again we've only requested a single permission - READ_CONTACTS - so we're only interested in

194
00:14:05,810 --> 00:14:08,110
the first item in the grantResults array,

195
00:14:08,360 --> 00:14:14,180
and you can see the code now for that on line 69. If that permission's granted, then we can set the Boolean

196
00:14:14,180 --> 00:14:15,960
field readGranted to true,

197
00:14:16,160 --> 00:14:19,970
so we know we do have the permission. We'll look at things we can do if

198
00:14:19,970 --> 00:14:21,730
a permission is denied, a bit later.

199
00:14:21,970 --> 00:14:28,070
For now though if the permission is denied, then readGranted will be false, and once again, we really shouldn't

200
00:14:28,070 --> 00:14:28,900
be doing that.

201
00:14:29,120 --> 00:14:35,600
As I mentioned, it may be an obvious thing to try to do. When you do it and get in a mess it's not immediately

202
00:14:35,600 --> 00:14:37,730
obvious what's causing the mess.

203
00:14:37,730 --> 00:14:42,150
And if you've done any web development work then you'll know exactly where I'm going with this.

204
00:14:42,200 --> 00:14:44,250
Don't try and save state.

205
00:14:44,300 --> 00:14:46,930
If that doesn't mean much to you don't worry - it'll soon become clear.

206
00:14:47,150 --> 00:14:51,440
So that should work and we've got some logging code now that'll let us see what's going on.

207
00:14:51,530 --> 00:14:56,690
I'll stop the video here, and in the next one we'll run the app and see what happens when the user accepts

208
00:14:56,690 --> 00:14:58,410
and denies the permission.

209
00:14:58,430 --> 00:14:59,360
So you in the next video.

