1
00:00:05,200 --> 00:00:09,390
In the last video we found out more about what this ContentResolver is.

2
00:00:09,430 --> 00:00:13,570
So back to our code now. We're going to use this applications ContentResolver.

3
00:00:13,810 --> 00:00:19,110
As I said there's just a single instance of the ContentResolver, and it's responsible for resolving

4
00:00:19,200 --> 00:00:26,120
all requests for content by directing the requests to the appropriate Content Provider. Now in our code down

5
00:00:26,130 --> 00:00:33,630
here on line 25 where we call contentResolver.query, the ContentResolver extracts the Authority

6
00:00:33,690 --> 00:00:39,900
from the URI and uses that to decide which Content Provider it should send the query request

7
00:00:39,900 --> 00:00:40,670
to.

8
00:00:40,980 --> 00:00:47,660
It then gets a cursor back from that Content Provider and returns the cursor to our calling code.

9
00:00:47,660 --> 00:00:51,840
Alright so we're going to write a bit more code now and we're going to store the contacts in a list.

10
00:00:51,920 --> 00:00:52,880
So let's start by doing that.

11
00:00:52,870 --> 00:00:59,500
So below the line now where we've retrieved our cursor, we're going to add some more code. So what we're going to do

12
00:00:59,500 --> 00:01:08,010
first is add a new line and then we're going to put val contacts is equal to ArrayList. And then we're going to

13
00:01:08,010 --> 00:01:12,090
use the diamond operate with string, so that's the type string we're getting back,

14
00:01:12,150 --> 00:01:15,710
or at least what's going to be in the ArrayList and parentheses on the end.

15
00:01:15,960 --> 00:01:16,880
And just a note there.

16
00:01:16,920 --> 00:01:23,460
That's basically going to be "create a list to hold our contacts".

17
00:01:23,600 --> 00:01:24,270
Alright.

18
00:01:24,270 --> 00:01:30,640
Then on the next line we do cursor question-mark dot use, left and right

19
00:01:30,680 --> 00:01:36,050
curly braces. And we'll just put a note here,

20
00:01:36,510 --> 00:01:37,050
"loop through

21
00:01:43,280 --> 00:01:50,900
the cursor". OK, so within the block itself, this time we're going to use while parentheses. We're going to use it this time

22
00:01:50,900 --> 00:01:56,470
correctly, so it.moveToNext closing parentheses.

23
00:01:56,670 --> 00:02:03,070
Open a code block again, then we do a contacts, which is our ArrayList dot add parentheses.

24
00:02:03,320 --> 00:02:13,230
it.getString. Then in parentheses again we're going to put it.getColumnIndex parentheses again,

25
00:02:13,460 --> 00:02:20,480
ContactsContract.Contacts. Then it's going to be dot DISPLAY_NAME_PRIMARY,

26
00:02:20,530 --> 00:02:25,670
then we've got three closing right parentheses at the end of the line.

27
00:02:25,670 --> 00:02:30,830
Alright so we're storing the contacts in a list which I've called contacts, and we're adding each contact to the list

28
00:02:31,190 --> 00:02:34,060
and we'll use the list shortly as the data for an adapter.

29
00:02:34,310 --> 00:02:37,010
Now we can't guarantee that we'll get any data back.

30
00:02:37,220 --> 00:02:40,420
So we're using the safe call operator before the use function

31
00:02:40,490 --> 00:02:41,890
with a question-mark.

32
00:02:41,900 --> 00:02:47,510
Now the call to use and the while loop use the same approach that we've used in our earlier example.

33
00:02:47,870 --> 00:02:51,040
Using a cursor is the same, even though we're now getting the data back

34
00:02:51,050 --> 00:02:54,290
via a ContentResolver and ContentProvider.

35
00:02:54,770 --> 00:02:59,840
So the last thing we need to do now in this code to read the data, is to create an adapter for the

36
00:02:59,840 --> 00:03:00,660
ListView.

37
00:03:00,800 --> 00:03:02,180
So let's go ahead and do that.

38
00:03:02,200 --> 00:03:05,090
I'm going to put that immediately below the line we've just finished typing.

39
00:03:05,180 --> 00:03:14,120
So we're going to type val adapter is equal to, we're going to type ArrayAdapter, then a diamond operator, string

40
00:03:14,120 --> 00:03:17,570
in the middle of that, so type string. Then parentheses

41
00:03:17,930 --> 00:03:31,750
this comma R.layout.content_detail comma then R.id.name comma then contacts being our

42
00:03:31,750 --> 00:03:35,340
ArrayList. Then next we're going to do contact

43
00:03:35,420 --> 00:03:47,660
underscore names.adapter equals adapter. Now by the way if you are asked to select the import for contact 

44
00:03:47,660 --> 00:03:54,390
underscore names, choose a synthetic import, and that's Kotlin X dot android.synthetic.main.content underscore

45
00:03:54,400 --> 00:03:56,900
main dot star.

46
00:03:57,110 --> 00:04:00,170
And you can see in my case there, because I've got auto-imports on,

47
00:04:00,170 --> 00:04:06,720
it's found that, well processed that automatically for us. Alright, so moving on. And by the way we've seen this code before

48
00:04:07,110 --> 00:04:10,530
in the top 10 downloader app for the ArrayAdapter.

49
00:04:10,760 --> 00:04:13,390
Alright so at this point the code's completed, almost.

50
00:04:13,680 --> 00:04:16,070
What we still need to deal with though is permissions.

51
00:04:16,250 --> 00:04:19,560
So Google changed the way permissions work with Android Marshmallow.

52
00:04:19,769 --> 00:04:24,930
So I want to spend a bit of time discussing that. Now we should really finish off what we're doing with

53
00:04:24,930 --> 00:04:27,760
these ContentResolvers and ContentProviders first, though.

54
00:04:28,050 --> 00:04:30,680
So what I'm going to do is run this on an Android lollipop,

55
00:04:30,720 --> 00:04:34,010
the API 21 emulator, so that we can see it working.

56
00:04:34,110 --> 00:04:37,810
But then in the next video we're going to spend some time looking at permissions.

57
00:04:37,920 --> 00:04:42,930
Whichever version of Android we use, we still need to request the permissions in the Android manifest

58
00:04:42,930 --> 00:04:44,370
at least, for the app.

59
00:04:44,380 --> 00:04:46,050
So let's go ahead and do that.

60
00:04:46,140 --> 00:04:53,140
So we're going to open the project on the left, we're going to open up manifest.

61
00:04:53,260 --> 00:04:56,920
So the permission we want here is READ_CONTACTS, so let's go ahead and do that.

62
00:04:56,920 --> 00:05:03,490
So we're going to come down here above the application tag and we'll create, or we'll add rather, a user's

63
00:05:03,580 --> 00:05:05,330
permission tag here.

64
00:05:05,640 --> 00:05:10,870
You can see that Android Studio is helpfully helping, or filling that in for us. And the one we want,

65
00:05:10,870 --> 00:05:16,390
as I mentioned, is READ_CONTACTS, so I'm just specifying that and pressing enter

66
00:05:16,420 --> 00:05:21,150
so there's no chance of me accidentally mistyping that. So I'm going to close off the tag there, so

67
00:05:21,160 --> 00:05:26,980
we've got the permission now set up for reading contacts defined in our Android Mainfest file.

68
00:05:27,370 --> 00:05:32,240
So once we've done this now the app should work on any version of Android before API 23.

69
00:05:32,590 --> 00:05:36,320
So let's run it on the API 21 device that we set up a few videos ago.

70
00:05:39,490 --> 00:05:42,560
So this is the one here that I set up, API 21 Contacts, so let's run that.

71
00:05:59,100 --> 00:06:03,140
Alright, so once the app is running, which it is now, we should be able to tap the floating action button

72
00:06:03,470 --> 00:06:05,760
and see the contacts displayed in the ListView.

73
00:06:05,800 --> 00:06:10,290
And just remember to choose the emulator that you've added the contacts to in the earlier video,

74
00:06:10,440 --> 00:06:13,960
otherwise of course you won't be able, or you won't have any contact records to display.

75
00:06:14,170 --> 00:06:20,450
So I'm going to click on the floating action button, and you can see we've got two records showing there. Now if we had enough

76
00:06:20,450 --> 00:06:25,000
records we could scroll through them, as you've seen us do with a ListView in earlier apps.

77
00:06:25,100 --> 00:06:26,750
In fact now we know that it's working,

78
00:06:26,780 --> 00:06:31,490
you could run it on your phone and you'll see all your contacts appear in the list.

79
00:06:31,490 --> 00:06:33,650
Alright but at this point that's working fine,

80
00:06:33,650 --> 00:06:37,310
and that's how we can use data using a Content Provider.

81
00:06:37,760 --> 00:06:42,980
Now obviously this is a very basic application, but it does give you the concepts of a Content Provider and

82
00:06:42,980 --> 00:06:45,530
also using a Content Resolver.

83
00:06:45,530 --> 00:06:50,660
In this case we were able to access the contacts built into the phone, and as you can see if we go back to the

84
00:06:50,660 --> 00:06:51,110
code,

85
00:06:57,320 --> 00:07:03,450
the actual code to query the data is very similar to what we had when we accessed the database directly.

86
00:07:03,470 --> 00:07:09,920
So using a Content Provider doesn't really introduce any more complexity into our code, beyond having

87
00:07:09,920 --> 00:07:16,040
to obtain the content_uri from the ContentProvider class, so that we can pass that to

88
00:07:16,040 --> 00:07:22,460
the Content Resolver. We query the Content Resolver, and that passes the query onto the Content Provider.

89
00:07:22,850 --> 00:07:29,120
The Content Provider then fetches the data from its data source or, in the case of an update, writes the

90
00:07:29,120 --> 00:07:35,600
data to the data source and either returns a cursor to the Content Resolver or reports back how many

91
00:07:35,600 --> 00:07:36,960
records were updated.

92
00:07:37,040 --> 00:07:41,710
There's a direct mapping of methods from a Content Resolver to the Content Provider.

93
00:07:41,870 --> 00:07:47,180
For example, when we call the Resolver's query method, that has to call a query method in the Provider,

94
00:07:47,540 --> 00:07:53,330
and the same applies to Inserts and Updates. Every method we call in the resolver has a corresponding method

95
00:07:53,660 --> 00:07:59,600
that the Resolver calls in the Provider, and we'll see that all in more detail when we come to create our own

96
00:07:59,600 --> 00:08:00,740
Content Provider.

97
00:08:00,970 --> 00:08:05,930
And in the next app we'll do just that, and we'll look at creating our own Content Provider to provide

98
00:08:05,930 --> 00:08:08,240
access to our apps database.

99
00:08:08,240 --> 00:08:13,970
Now this is more complex than just using the database directly, but it does mean that other apps will

100
00:08:14,000 --> 00:08:20,160
also be able to access the data in the same way as we've just done with the phone's contacts data.

101
00:08:20,280 --> 00:08:25,280
And it also frees us from having to cater for things like the activity life-cycle. We're not accessing

102
00:08:25,280 --> 00:08:30,680
the database directly, and don't have to worry about opening and closing it. The Content Resolvers object's

103
00:08:30,680 --> 00:08:34,669
global, and doesn't get destroyed when our activity does.

104
00:08:34,669 --> 00:08:38,770
Of course we still have to program our activity to handle its life-cycle events.

105
00:08:38,809 --> 00:08:41,750
If I rotate the emulator the ListView's cleared.

106
00:08:42,020 --> 00:08:46,830
So going back to the emulator, so as you can see if I rotate the device

107
00:08:46,830 --> 00:08:51,950
the ListView is cleared, and we have to click on the fab button to bring the data back again.

108
00:08:52,280 --> 00:08:57,050
So that does result in the query getting executed again unsurprisingly, then we'll be seeing how a

109
00:08:57,050 --> 00:08:59,780
loader can be used to prevent that though.

110
00:08:59,780 --> 00:09:05,300
The point I want to make though about the life-cycle, is that we don't have to concern ourselves with coordinating

111
00:09:05,300 --> 00:09:12,320
the data access with the activity life-cycle. The Content Resolver and Content Provider handle that all for

112
00:09:12,320 --> 00:09:13,060
us.

113
00:09:13,370 --> 00:09:18,920
If we query the database using a CursorLoader, we also don't have to worry about creating background

114
00:09:18,920 --> 00:09:22,260
threads, and we'll be saying how to do that in the next section.

115
00:09:22,640 --> 00:09:27,170
But coming up in the next video we're going to look at the changes that Google made to permissions in API

116
00:09:27,170 --> 00:09:32,190
23, and how to get this app working with Android Marshmallow and above.

117
00:09:32,230 --> 00:09:33,160
See you in the next video.

