1
00:00:05,190 --> 00:00:10,040
In the previous video, we got the app running on Android versions earlier than Marshmallow, which is API

2
00:00:10,050 --> 00:00:12,480
23. With API 23,

3
00:00:12,570 --> 00:00:17,850
Google changed the way that permissions work, and we looked at that briefly in the top 10 Downloader app.

4
00:00:18,690 --> 00:00:25,350
So I'm going to run the app again, but this time I've loaded the API 27 emulator that I set up in an earlier video in this

5
00:00:25,410 --> 00:00:29,610
section of the course, the one that we've also entered some contact details into.

6
00:00:30,270 --> 00:00:31,590
So this time when I run the app,

7
00:00:41,500 --> 00:00:47,840
so the app starts as per normal, but when I click on the floating action button we actually get an error

8
00:00:47,840 --> 00:00:48,130
here:

9
00:00:48,150 --> 00:00:52,190
Content Provider Example has stopped. And if we come and have a look at our logcat, we can

10
00:00:55,050 --> 00:01:02,100
see that we've got an exception. I'll just go back up and look at it. Now we can see it here, the error, Permission Denial.

11
00:01:02,820 --> 00:01:07,600
Basically it goes on to say the Permission Denial was for opening provider com.android.providers

12
00:01:07,620 --> 00:01:11,170
dot contacts.ContactsProvider2.

13
00:01:11,370 --> 00:01:17,430
The bottom line here is with API 23 and above, it's not enough to just request the permissions we need

14
00:01:17,430 --> 00:01:18,650
in the manifest.

15
00:01:18,690 --> 00:01:25,180
We also need to write some code to request the permissions from the user when the app runs.

16
00:01:25,220 --> 00:01:34,620
So let's check the Google documentation here. So there's a guide which is pretty useful about Permissions, Android

17
00:01:34,630 --> 00:01:36,690
Permissions. I'm just going to paste in the link there.

18
00:01:40,880 --> 00:01:47,170
Now as it turns out, this documentation has been updated since we looked at the top 10 app, and the earlier link now

19
00:01:47,230 --> 00:01:52,360
redirects to here. So I'm going to start with this Permissions Overview at the top of the page. But do have

20
00:01:52,360 --> 00:01:53,260
a read through this guide

21
00:01:53,260 --> 00:01:57,310
once you've finished this section, to make sure you understand how everything works.

22
00:01:57,490 --> 00:02:02,140
We already know that we have to specify the permission in the manifest, regardless of the version of

23
00:02:02,250 --> 00:02:02,670
Android.

24
00:02:02,830 --> 00:02:04,070
And we've already done that step

25
00:02:04,270 --> 00:02:08,070
when we added the user's Permission tag in the Android manifest.xml file.

26
00:02:08,320 --> 00:02:13,540
But another important thing to note is that, in that first paragraph, is that the system might grant

27
00:02:13,540 --> 00:02:19,110
the permission automatically.

28
00:02:19,220 --> 00:02:24,650
So that's what happened in our top 10 app, because the Internet permission we needed is classed as a normal

29
00:02:24,650 --> 00:02:25,720
permission.

30
00:02:25,730 --> 00:02:30,040
So what that means is we didn't have to do anything else to be granted permission to access the Internet.

31
00:02:30,350 --> 00:02:34,360
But accessing the user's contacts is classed as a dangerous permission,

32
00:02:34,550 --> 00:02:38,070
though, so Android needs to ask the user to approve that permission.

33
00:02:38,120 --> 00:02:41,800
Now we didn't really see that when we ran our app on the Lollipop emulator.

34
00:02:42,050 --> 00:02:47,840
That's because the method that Android Studio uses to install apps on the device, bypasses the checks

35
00:02:47,840 --> 00:02:51,320
that you see when you install an app from the Google Play Store.

36
00:02:51,350 --> 00:02:56,420
Now earlier in the course, we enabled USB debugging on our phones, and you should have seen a dialogue

37
00:02:56,450 --> 00:03:00,270
pop up asking for confirmation that looks something like this:

38
00:03:00,470 --> 00:03:06,800
Now notice that it does say that enabling USB debugging can install apps on your device without notification.

39
00:03:07,070 --> 00:03:12,770
The emulators have USB debugging turned on by default, and that automatically accepts the permissions

40
00:03:12,770 --> 00:03:16,300
that you'd normally have to accept when installing a new app.

41
00:03:16,310 --> 00:03:21,080
So although we didn't see it when running our apps from Android Studio, you'd normally have to accept

42
00:03:21,080 --> 00:03:24,750
the permission that the app requested when you install it.

43
00:03:25,340 --> 00:03:27,380
And that's how it worked before Marshmallow.

44
00:03:27,560 --> 00:03:32,460
But when Google released Marshmallow they changed the way that permissions work.

45
00:03:32,540 --> 00:03:37,650
So let's go back to that web page now, just to see what this all means for Marshmallow and above.

46
00:03:37,850 --> 00:03:42,110
So we can get a good description of the change by scrolling down to the Requests prompts for dangerous

47
00:03:42,110 --> 00:03:43,090
permissions section,

48
00:03:43,100 --> 00:03:44,950
to this section here.

49
00:03:45,620 --> 00:03:51,080
So that confirms what we found in the top 10 app: Only dangerous permissions require user agreement.

50
00:03:51,080 --> 00:03:55,900
Now the next subsection there describes the differences from the user's perspective.

51
00:03:58,330 --> 00:04:04,300
If the device is running Android 6.0 API Level 23 or higher, users grant permission to apps while the

52
00:04:04,300 --> 00:04:05,110
app is running,

53
00:04:05,260 --> 00:04:06,970
not when they install the app.

54
00:04:07,180 --> 00:04:11,920
There's also an important comment there about the target SDK version.

55
00:04:11,980 --> 00:04:16,050
The target SDK version has to be 23 or higher for this behavior.

56
00:04:16,209 --> 00:04:21,670
If you target a lower version, then your app will have the earlier behavior regardless of the device that

57
00:04:21,670 --> 00:04:22,530
it's running on.

58
00:04:22,630 --> 00:04:25,980
The user will be prompted to grant access when they install the app.

59
00:04:26,260 --> 00:04:31,750
It also states that you can't always rely on having a permission. The user may grant it, but then deny

60
00:04:31,750 --> 00:04:32,710
it again later.

61
00:04:33,010 --> 00:04:37,960
And if you think about it that obviously has implications for us as developers, because we now have to

62
00:04:37,960 --> 00:04:43,000
write our apps so that they can handle the situation where a permission is no longer granted.

63
00:04:43,150 --> 00:04:48,670
Now for some apps that may involve us disabling some functionality. An example could be a photo

64
00:04:48,700 --> 00:04:54,360
processing app that allows the user to share the modified photo with their contacts.

65
00:04:54,550 --> 00:04:59,620
If the user revokes the apps permission to access their contacts, then the app would be unable to share

66
00:04:59,620 --> 00:05:00,420
the photo.

67
00:05:00,700 --> 00:05:05,260
So in that case we shouldn't even display that option at all. The app would still be able to perform its photo

68
00:05:05,260 --> 00:05:11,260
manipulation functions but would be unable to share the result. Now in the case of our simple contacts

69
00:05:11,260 --> 00:05:11,680
app,

70
00:05:11,860 --> 00:05:17,500
if the user doesn't grant access to the contacts database, then the entire app will become useless because

71
00:05:18,010 --> 00:05:19,120
that's all it does.

72
00:05:19,360 --> 00:05:26,840
So the next section, if we scroll down a little bit more, talks about Install, Install-time requests. And by the way I didn't scroll down,

73
00:05:26,890 --> 00:05:31,670
but that other information that I was talking about related to Android 6.0 and higher is on that page there - you

74
00:05:31,670 --> 00:05:36,250
can see it talks more about not relying on always having the permission. But scrolling down further now

75
00:05:36,260 --> 00:05:40,650
we're talking about the Install-time requests Android 5.1.1 and below.

76
00:05:40,940 --> 00:05:46,190
That's describing the behavior on earlier versions of Android, and that also applies if your target is

77
00:05:46,190 --> 00:05:51,480
SDK version is 22 or lower, regardless of the version of Android that the device is running.

78
00:05:51,620 --> 00:05:55,730
So in that case the permissions are requested when the app is installed.

79
00:05:55,730 --> 00:05:59,950
The user can either grant all permissions or decide not to install the app,

80
00:06:00,540 --> 00:06:01,560
and talks more about that as 

81
00:06:01,570 --> 00:06:04,180
we scroll down. If the permissions are granted,

82
00:06:04,460 --> 00:06:09,840
the only way to deny any of those permissions is to uninstall the app. So going back up the page now,

83
00:06:12,990 --> 00:06:16,440
just down here to the end of the Permission approval section,

84
00:06:16,870 --> 00:06:21,280
there's a link there to the protection levels - this link here. Now that lists the normal and dangerous

85
00:06:21,280 --> 00:06:26,440
permissions, and lets you check if you need to do more than just add an entry in the manifest for a specific

86
00:06:26,440 --> 00:06:30,620
permission or permissions that your apps need. Click on that and have a look,

87
00:06:31,210 --> 00:06:32,080
but I'll leave that for now.

88
00:06:32,080 --> 00:06:33,310
We'll go back to Android

89
00:06:33,340 --> 00:06:39,490
Studio, and let's now look at the code we need to check for those permissions, and then we'll consider what

90
00:06:39,490 --> 00:06:41,370
to do if they're not granted.

91
00:06:41,530 --> 00:06:46,630
But what I'm going to do first is start by adding a constant and a variable that we'll be using shortly.

92
00:06:46,960 --> 00:06:54,070
So I'm going to do that. I'm going to close down the logcat window, go up to the top of the file. So lay our constant below our TAG, so it's going

93
00:06:54,070 --> 00:06:55,390
to be private

94
00:06:55,400 --> 00:06:58,420
const Val. We'll call this one REQUEST, in

95
00:06:58,530 --> 00:07:06,410
uppercase, underscore CODE underscore READ underscore CONTACTS, and we'll assign the value of 1 to that, equals 1.

96
00:07:06,470 --> 00:07:08,500
And we're using that variable shortly.

97
00:07:08,670 --> 00:07:13,670
I'll also explain what it's for when we come to using it, but also in the class itself

98
00:07:13,720 --> 00:07:16,030
let's add a variable, and we're going to call it

99
00:07:16,070 --> 00:07:19,920
readGranted. So it's going to be private, private var

100
00:07:19,950 --> 00:07:21,100
and it's going to be read

101
00:07:21,110 --> 00:07:23,920
Granted equals false.

102
00:07:24,260 --> 00:07:26,570
Same deal, I'll talk about that shortly,

103
00:07:26,700 --> 00:07:31,480
and obviously in the case of the constant on line 14, you saw that I made it a top level value using the

104
00:07:31,480 --> 00:07:33,530
private const modifiers.

105
00:07:33,560 --> 00:07:38,320
Alright, so the first step now is to check to see if the app has already been granted the permission

106
00:07:38,320 --> 00:07:39,260
it needs.

107
00:07:39,450 --> 00:07:44,650
And we can do that by calling the checkSelfPermission method. So I'm going to add the code and then say a

108
00:07:44,650 --> 00:07:46,290
couple of things about it.

109
00:07:46,360 --> 00:07:48,750
So I want to put that code just immediately below this

110
00:07:48,760 --> 00:07:51,550
setSupportActionBar call.

111
00:07:51,860 --> 00:07:55,840
And it's going to be val hasReadContactPermission,

112
00:07:58,690 --> 00:08:03,520
and we'll set that equal to ContextCompat

113
00:08:03,740 --> 00:08:07,090
dot, and it's going to be check

114
00:08:07,110 --> 00:08:15,170
SelfPermission. In parentheses it's going to be this comma, and it's going to be Manifest. At this point here

115
00:08:15,190 --> 00:08:22,900
it's important to choose the android.Manifest package, this one down here and not the java.util one. So Manifest dot

116
00:08:23,050 --> 00:08:24,530
permission

117
00:08:25,210 --> 00:08:32,440
dot READ_CONTACT. And what I'm going to do is just put that on the next line. Actually I won't, it reads

118
00:08:32,440 --> 00:08:32,789
alright.

119
00:08:32,799 --> 00:08:36,690
I just wanted to make sure there's enough space on the screen to see that, but we can see that.

120
00:08:36,740 --> 00:08:38,669
So we're checking to see whether we've got that permission and

121
00:08:38,679 --> 00:08:43,120
I'm just going to do a log entry here - Log.d parentheses TAG comma.

122
00:08:43,289 --> 00:08:48,060
Then in double quotes onCreate colon check

123
00:08:48,070 --> 00:08:48,600
SelfPermission

124
00:08:51,170 --> 00:08:55,660
returned $hasReadContactPermission.

125
00:08:56,760 --> 00:09:02,130
Now because the new security model was introduced in API 23 and we're targeting Android versions way

126
00:09:02,130 --> 00:09:08,580
back to API 17, we have to use the v4.support library to get access to the checkSelfPermission

127
00:09:08,580 --> 00:09:09,350
method.

128
00:09:09,360 --> 00:09:14,050
Now there is a checkSelfPermission method in the framework, but that would only work for Marshmallow

129
00:09:14,050 --> 00:09:14,980
and above.

130
00:09:15,060 --> 00:09:21,460
And both methods return the same result, but the ContextCompat method which we selected, first checks

131
00:09:21,460 --> 00:09:26,790
to see if it's running on Android prior to API 23. If it is it just a little success,

132
00:09:26,850 --> 00:09:31,170
and that's of course because the new security model doesn't apply before API 23.

133
00:09:31,170 --> 00:09:34,990
Now remember that we defined the permissions we needed in the manifest,

134
00:09:35,220 --> 00:09:40,320
so therefore we can use the constants defined in the manifest's class to specify which permission we're

135
00:09:40,320 --> 00:09:40,910
checking.

136
00:09:41,020 --> 00:09:46,350
Here it's the READ_CONTACTS permission. So having to type Manifest.permission.READ

137
00:09:46,350 --> 00:09:47,150
underscore CONTACTS

138
00:09:47,160 --> 00:09:49,010
everytime is a bit of a mouthful,

139
00:09:49,140 --> 00:09:54,810
so we can import the constant from android.Manifest.permission instead. Now Android Studio add the import

140
00:09:54,810 --> 00:09:55,570
for us,

141
00:09:55,740 --> 00:10:01,590
so first note that android.Manifest has been imported to give us access to the Manifest.permission 

142
00:10:01,590 --> 00:10:03,750
dot READ_CONTACTS field.

143
00:10:03,840 --> 00:10:10,010
So if we have a look in the import section, you can see here, android.Manifest. In my case, it's literally

144
00:10:10,010 --> 00:10:15,670
the first entry of the import section of the source code. The ordering of course isn't important,

145
00:10:15,890 --> 00:10:19,030
so it may well be appearing lower down for you.

146
00:10:19,550 --> 00:10:23,940
So if I go back and remove the Manifest.permission qualifier from the READ_CONTACTS field -

147
00:10:24,100 --> 00:10:25,760
I'll just make that READ_CONTACTS,

148
00:10:28,900 --> 00:10:33,230
and what I can do is just delete that if needed. You can see the old one's still there but it has actually added

149
00:10:33,230 --> 00:10:33,680
the new ones.

150
00:10:33,680 --> 00:10:35,900
I'm just going to delete the old one.

151
00:10:37,150 --> 00:10:41,600
But what it should do then, as you can see, it added the android.Manifest.permission.READ

152
00:10:41,600 --> 00:10:42,980
underscore CONTACTS.

153
00:10:43,220 --> 00:10:47,130
So therefore we can now get away with just putting READ_CONTACTS here.

154
00:10:47,180 --> 00:10:53,250
Let me just take this opportunity to check my preferences here. I'm going into Preferences, going into Editor,

155
00:10:53,930 --> 00:10:59,540
General, Auto import, and I've got Add unambiguous imports on the fly and Optimize imports on the fly

156
00:10:59,600 --> 00:11:00,990
which is what that uses.

157
00:11:00,990 --> 00:11:02,270
So I'm not sure why that other

158
00:11:02,270 --> 00:11:07,070
grey entry appeared and appeared to sit there for a while but it should be automatic, and remove that

159
00:11:07,070 --> 00:11:07,910
automatically for me.

160
00:11:07,970 --> 00:11:09,900
But anyway, at this point we've actually succeeded now.

161
00:11:10,200 --> 00:11:15,440
We've got a the line making it a lot easier to read now, using just READ_CONTACTS rather than the qualifier

162
00:11:15,440 --> 00:11:17,360
that we had previously.

163
00:11:17,360 --> 00:11:20,970
So at this point though, looking at this import on line 3,

164
00:11:21,410 --> 00:11:24,520
that's the equivalent of what's called a static import in java.

165
00:11:24,890 --> 00:11:29,690
Now if you're not familiar with the static imports in Java, that's just a way to import the static members

166
00:11:29,690 --> 00:11:30,670
of a class,

167
00:11:30,680 --> 00:11:34,380
and these are usually constants and it saves having to fully qualify them.

168
00:11:34,500 --> 00:11:38,990
Kotlin doesn't have the static keyword, but importing the fully qualified value like

169
00:11:38,990 --> 00:11:45,410
this is the Kotlin equivalent. Importing like this can be useful, but use it sparingly. If you over

170
00:11:45,410 --> 00:11:45,730
do it

171
00:11:45,740 --> 00:11:49,110
you can make your code hard to understand and debug.

172
00:11:49,260 --> 00:11:52,950
Now to see what I mean, have a look at the code - coming down here again -

173
00:11:54,340 --> 00:12:01,770
from line 27 onwards. And if you look at that code from line 27 onwards, it's now not immediately obvious where READ

174
00:12:01,770 --> 00:12:07,730
underscore CONTACTS is coming from, and if it had also imported the ContactsContract constants, we'd have

175
00:12:07,730 --> 00:12:11,020
a lot of constants coming from different classes without being qualified.

176
00:12:11,240 --> 00:12:16,090
And that can make it hard to see what's going on and where all these constants are coming from.

177
00:12:16,100 --> 00:12:20,040
So I recommend not using this type of import for more than one class at a time.

178
00:12:20,060 --> 00:12:22,150
Alright so back to line 27.

179
00:12:22,190 --> 00:12:26,960
So we've passed a context, this here, as the first parameter,

180
00:12:27,350 --> 00:12:32,620
and we also passed a constant representing the permission we're interested in to the checkSelf

181
00:12:32,620 --> 00:12:33,740
Permission method.

182
00:12:33,760 --> 00:12:35,670
Now we'll get back an int result.

183
00:12:35,860 --> 00:12:39,500
So let's check the documentation to see what the return value is.

184
00:12:39,500 --> 00:12:42,890
So I'm going to click on the checkSelfPermission method and bring up the documentation,

185
00:12:47,490 --> 00:12:50,310
and you can see that these return values are fairly straightforward.

186
00:12:50,540 --> 00:12:55,970
We get one of the two constants returned; either PERMISSION_GRANTED if we already have the permission,

187
00:12:56,390 --> 00:12:58,030
or PERMISSION_DENIED

188
00:12:58,040 --> 00:13:04,300
if we don't. Now on Android versions before Marshmallow, we should always get PERMISSION_GRANTED as long as

189
00:13:04,310 --> 00:13:09,650
we specify the permission in the manifest. On Marshmallow and above, the permission won't have been

190
00:13:09,650 --> 00:13:11,420
granted when the app was installed,

191
00:13:11,540 --> 00:13:16,160
and that means that the first time we run this app, we'll get PERMISSION_DENIED and we'll

192
00:13:16,170 --> 00:13:18,710
have to request the permission from the user.

193
00:13:18,750 --> 00:13:22,760
This is where things get a bit interesting. Now it would be fairly straightforward except that

194
00:13:22,760 --> 00:13:27,730
users have an option to deny a permission, and you can tick a box so that they won't get asked again.

195
00:13:27,830 --> 00:13:31,370
I'm going to have a look at how that works and how to deal with it in the next video.

