1 00:00:04,700 --> 00:00:06,529 We've now written a ContentProvider 2 00:00:06,529 --> 00:00:08,799 that allows us to query our database. 3 00:00:08,799 --> 00:00:10,820 There's still a bit more work needed 4 00:00:10,820 --> 00:00:12,590 before our ContentProvider's finished 5 00:00:12,590 --> 00:00:14,449 though. We need to be able to insert new 6 00:00:14,449 --> 00:00:17,420 rows, update existing data and delete 7 00:00:17,420 --> 00:00:19,730 rows as well. So going back to the App 8 00:00:19,730 --> 00:00:21,769 Provider class that I'm in on screen 9 00:00:21,769 --> 00:00:23,839 now, we've got stubs for these methods 10 00:00:23,839 --> 00:00:25,869 down the bottom; insert, update and delete. 11 00:00:25,869 --> 00:00:28,159 They were created for us, if you recall, 12 00:00:28,159 --> 00:00:30,050 by the Android Studio code generator 13 00:00:30,050 --> 00:00:32,540 when we implemented the abstract methods 14 00:00:32,540 --> 00:00:35,300 of the ContentProvider class. Before we 15 00:00:35,300 --> 00:00:36,739 write the code for those methods though, 16 00:00:36,739 --> 00:00:38,930 let's have a quick look at this getType 17 00:00:38,930 --> 00:00:40,280 function which we've got at the top here, 18 00:00:40,280 --> 00:00:42,769 above the query method starting on line 19 00:00:42,769 --> 00:00:45,829 62, because we also need to implement 20 00:00:45,829 --> 00:00:47,930 that. Now this function's used when 21 00:00:47,930 --> 00:00:50,300 something needs to know the MIME type of 22 00:00:50,300 --> 00:00:53,840 the data available at the URIs that 23 00:00:53,840 --> 00:00:56,480 our ContentProvider recognizes. Now we 24 00:00:56,480 --> 00:00:58,280 don't need this function to return 25 00:00:58,280 --> 00:01:00,620 anything for this app, and because we're 26 00:01:00,620 --> 00:01:02,690 not returning any recognized MIME types, 27 00:01:02,690 --> 00:01:05,269 the information returned won't be much 28 00:01:05,269 --> 00:01:08,720 use to any external apps either. But we 29 00:01:08,720 --> 00:01:10,880 have to implement it and because of that we 30 00:01:10,880 --> 00:01:13,310 may as well do it properly. So what's a 31 00:01:13,310 --> 00:01:14,360 MIME type? 32 00:01:14,360 --> 00:01:17,329 Well the Android documentation on mime 33 00:01:17,329 --> 00:01:20,119 types doesn't really say much at all, but 34 00:01:20,119 --> 00:01:22,610 if you search online for mime type you'll 35 00:01:22,610 --> 00:01:24,829 find a lot of information. Now there's a 36 00:01:24,829 --> 00:01:26,420 Wikipedia page which has got a good 37 00:01:26,420 --> 00:01:28,340 explanation. I'm just going to bring that up 38 00:01:28,340 --> 00:01:34,040 on the screen there now. This is a good 39 00:01:34,040 --> 00:01:35,810 page to visit. As well as a good 40 00:01:35,810 --> 00:01:37,280 explanation it's also got some examples 41 00:01:37,280 --> 00:01:41,180 of common MIME types shown, and you can 42 00:01:41,180 --> 00:01:42,290 see those when we scroll down a little bit 43 00:01:42,290 --> 00:01:43,820 further down here, under common examples. 44 00:01:43,820 --> 00:01:47,509 So they're basically - MIME types - there to 45 00:01:47,509 --> 00:01:49,610 let other systems know what kind of data 46 00:01:49,610 --> 00:01:51,979 that they can expect to get back from 47 00:01:51,979 --> 00:01:54,619 our ContentProvider. For example, if we 48 00:01:54,619 --> 00:01:57,229 created a ContentProvider that returned 49 00:01:57,229 --> 00:02:00,020 png images - ping images - then the CONTENT 50 00:02:00,020 --> 00:02:02,630 underscore ITEM_TYPE would 51 00:02:02,630 --> 00:02:06,469 be image/png. So the idea is, that a 52 00:02:06,469 --> 00:02:09,350 program can request the MIME type of our 53 00:02:09,350 --> 00:02:11,900 URIs and use it to work out what to 54 00:02:11,900 --> 00:02:14,150 do with the data returned. So if we 55 00:02:14,150 --> 00:02:16,489 returned a MIME type of image/png 56 00:02:16,489 --> 00:02:17,390 the 57 00:02:17,390 --> 00:02:19,190 program would know that it received a 58 00:02:19,190 --> 00:02:22,190 png image, so could then process it or do 59 00:02:22,190 --> 00:02:23,150 something else with it. 60 00:02:23,150 --> 00:02:24,950 Remember that Android has been designed 61 00:02:24,950 --> 00:02:27,260 to be very flexible, and a Content 62 00:02:27,260 --> 00:02:29,180 Provider can provide all sorts of 63 00:02:29,180 --> 00:02:31,520 content. For our app the URIs passed 64 00:02:31,520 --> 00:02:33,770 to our query function will result in a 65 00:02:33,770 --> 00:02:35,959 cursor being returned, so they're not 66 00:02:35,959 --> 00:02:37,820 really returning anything that fits a 67 00:02:37,820 --> 00:02:40,459 generally recognised MIME type. Now we 68 00:02:40,459 --> 00:02:42,890 could just return null, but frankly 69 00:02:42,890 --> 00:02:44,840 that's a little hazy. So let's have a 70 00:02:44,840 --> 00:02:47,630 look at the Android documentation for 71 00:02:47,630 --> 00:02:54,080 some more information here. And if we 72 00:02:54,080 --> 00:02:56,450 just do a bit of a search here for vnd, 73 00:02:56,450 --> 00:02:59,720 under getType here as you can see, it 74 00:02:59,720 --> 00:03:02,150 tells us here that the type should start 75 00:03:02,150 --> 00:03:05,630 vnd.android.cursor.item 76 00:03:05,630 --> 00:03:09,110 for a single record, and vnd.android 77 00:03:09,110 --> 00:03:12,290 dot cursor.dir for multiple items, such 78 00:03:12,290 --> 00:03:14,540 as a whole table. So I've used those 79 00:03:14,540 --> 00:03:17,420 values in our TasksContract class, and 80 00:03:17,420 --> 00:03:20,000 added our content Authority and a 81 00:03:20,000 --> 00:03:22,190 table name to the end. So these are 82 00:03:22,190 --> 00:03:24,799 custom MIME types and won't mean 83 00:03:24,799 --> 00:03:27,530 anything to any other app but ours. Now 84 00:03:27,530 --> 00:03:29,570 one way that these types may be used, is 85 00:03:29,570 --> 00:03:31,130 when displaying our data using 86 00:03:31,130 --> 00:03:33,410 intents. So our app could include an 87 00:03:33,410 --> 00:03:36,739 activity to display reports, and we could 88 00:03:36,739 --> 00:03:38,600 allow that activity to be launched by 89 00:03:38,600 --> 00:03:41,209 another app using an intent. So in that 90 00:03:41,209 --> 00:03:43,370 case, the other app would pass the 91 00:03:43,370 --> 00:03:45,500 appropriate content type to the intent, 92 00:03:45,500 --> 00:03:47,900 so we'd know whether it was asking us to 93 00:03:47,900 --> 00:03:50,120 display the entire table or just a 94 00:03:50,120 --> 00:03:52,579 specific row. Now it's probably not often 95 00:03:52,579 --> 00:03:53,930 that you'll implement something like 96 00:03:53,930 --> 00:03:56,530 that, so I suggest just using this next 97 00:03:56,530 --> 00:03:59,209 function as a template and not really 98 00:03:59,209 --> 00:04:01,190 worrying too much about it. So what I'm 99 00:04:01,190 --> 00:04:03,290 going to do is copy some code and paste 100 00:04:03,290 --> 00:04:05,959 it in there, and you'll be able to grab 101 00:04:05,959 --> 00:04:09,170 this code from the resources section of 102 00:04:09,170 --> 00:04:10,670 this video. So we'll go back to Android 103 00:04:10,670 --> 00:04:12,829 Studio and I'm going to paste it in, 104 00:04:12,829 --> 00:04:17,660 replacing the TODO for getType. I'm 105 00:04:17,660 --> 00:04:19,190 just going to make a bit of a space, a few 106 00:04:19,190 --> 00:04:20,470 spaces here, so it's a bit more readable. 107 00:04:20,470 --> 00:04:22,850 It's probably suffice, will suffice for 108 00:04:22,850 --> 00:04:25,160 now. So you can see here we're doing a 109 00:04:25,160 --> 00:04:27,200 very similar thing to the query method, 110 00:04:27,200 --> 00:04:30,400 using a uriMatcher to decide what URI 111 00:04:30,400 --> 00:04:32,889 has been passed, or we've been passed. We 112 00:04:32,889 --> 00:04:35,320 then return the appropriate MIME type. 113 00:04:35,320 --> 00:04:36,940 Now I'm going to comment out the code 114 00:04:36,940 --> 00:04:40,030 here for TIMINGS and for TASK_DURATIONS 115 00:04:40,030 --> 00:04:43,330 because we haven't written those yet. But 116 00:04:43,330 --> 00:04:45,130 in general don't worry about these MIME 117 00:04:45,130 --> 00:04:47,080 types at the moment. I've added this 118 00:04:47,080 --> 00:04:49,180 typical code rather than give the 119 00:04:49,180 --> 00:04:51,039 impression that it's okay to return null. 120 00:04:51,039 --> 00:04:53,860 However, our app won't be using these types. So 121 00:04:53,860 --> 00:04:55,180 that explains the reason for the other 122 00:04:55,180 --> 00:04:57,789 two constants in our TasksContract 123 00:04:57,789 --> 00:05:00,400 class. Alright, so now that everything 124 00:05:00,400 --> 00:05:02,050 in the TasksContract class has been 125 00:05:02,050 --> 00:05:05,410 explained, it's time for a challenge. So 126 00:05:05,410 --> 00:05:07,660 your challenge is to create a contact 127 00:05:07,660 --> 00:05:10,570 class for the Timings table. Now the 128 00:05:10,570 --> 00:05:12,520 Timings table will be called Timings with a 129 00:05:12,520 --> 00:05:14,560 capital T, and will have the columns that 130 00:05:14,560 --> 00:05:16,900 we saw in the database diagram at the 131 00:05:16,900 --> 00:05:19,120 start of this section. Now to save having 132 00:05:19,120 --> 00:05:21,970 to modify your code, it'll be helpful if 133 00:05:21,970 --> 00:05:23,620 you use the same names as me for the 134 00:05:23,620 --> 00:05:25,810 columns constants. So the names I'll be 135 00:05:25,810 --> 00:05:29,080 using are; ID, TIMING_TASK 136 00:05:29,080 --> 00:05:31,599 _ID, TIMING_START 137 00:05:31,599 --> 00:05:34,449 _TIME and TIMING 138 00:05:34,449 --> 00:05:36,610 _DURATION. Now just as a hint 139 00:05:36,610 --> 00:05:39,130 here, you can copy the TasksContract 140 00:05:39,130 --> 00:05:41,889 class and modify it to produce the new 141 00:05:41,889 --> 00:05:42,610 contract. 142 00:05:42,610 --> 00:05:44,770 Alright, so pause the video now and see 143 00:05:44,770 --> 00:05:46,389 if you can figure that out, and when you 144 00:05:46,389 --> 00:05:47,949 come back we'll go through it, step by 145 00:05:47,949 --> 00:05:50,990 step. Pause the video now. 146 00:05:50,990 --> 00:05:53,160 Alright so hopefully you went well with 147 00:05:53,160 --> 00:05:55,260 that challenge. What you'll find is that 148 00:05:55,260 --> 00:05:57,330 all the contract classes are pretty much 149 00:05:57,330 --> 00:06:00,420 the same. Once you've created one you can 150 00:06:00,420 --> 00:06:02,430 use it as a template for all others. So 151 00:06:02,430 --> 00:06:05,580 what I'm going to do is open up my code and 152 00:06:05,580 --> 00:06:08,070 go into the learnprogramming.academy 153 00:06:08,070 --> 00:06:10,020 dot tasktimer package, and I'm going 154 00:06:10,020 --> 00:06:12,840 to copy the TasksContract - control C, 155 00:06:12,840 --> 00:06:15,300 control V or command C and V on a Mac. 156 00:06:15,300 --> 00:06:18,840 That brings up the Copy object dialog 157 00:06:18,840 --> 00:06:20,810 and I'll change that to timings. So 158 00:06:20,810 --> 00:06:22,950 the name of the file will be Timings 159 00:06:22,950 --> 00:06:27,210 Contract. Alright so now that Android 160 00:06:27,210 --> 00:06:29,550 Studio's helpfully changed that name for 161 00:06:29,550 --> 00:06:31,560 us, here under the object, we just need to 162 00:06:31,560 --> 00:06:33,240 rename some of the other things in this 163 00:06:33,240 --> 00:06:36,000 file. So firstly for tasks, I'm going to 164 00:06:36,000 --> 00:06:37,920 change that to Timings's - the name of the 165 00:06:37,920 --> 00:06:40,050 table in our database. 166 00:06:40,050 --> 00:06:41,520 I'm going to take a copy of that because 167 00:06:41,520 --> 00:06:42,600 I'll be pasting that in a few other 168 00:06:42,600 --> 00:06:45,150 places. So the URI to access the, 169 00:06:45,150 --> 00:06:48,450 that should be Timings table, then down 170 00:06:48,450 --> 00:06:50,250 here it's going to be Timings fields 171 00:06:50,250 --> 00:06:53,190 instead of Tasks fields. Now in terms of 172 00:06:53,190 --> 00:06:56,640 the actual constants we've got ID, which 173 00:06:56,640 --> 00:06:58,620 is correct. We'll leave that as it is. The 174 00:06:58,620 --> 00:07:00,690 next one is TIMING_TASK_ID, 175 00:07:00,690 --> 00:07:04,470 so it's TIMING_TASK 176 00:07:04,470 --> 00:07:08,010 _ID. We're going to set that to 177 00:07:08,010 --> 00:07:12,840 the name TaskId. Alright so the next 178 00:07:12,840 --> 00:07:15,990 one is going to be TIMING_ 179 00:07:15,990 --> 00:07:19,560 START_TIME. I'm going to set 180 00:07:19,560 --> 00:07:22,710 that equal to StartTime, capital S 181 00:07:22,710 --> 00:07:25,650 capital T. And the last one will be 182 00:07:25,650 --> 00:07:28,710 TIMING DURATION, TIMING_ 183 00:07:28,710 --> 00:07:31,910 DURATION. I'm going to set that equal to 184 00:07:31,910 --> 00:07:35,940 Duration with a capital D. So contracts 185 00:07:35,940 --> 00:07:38,250 classes for different tables may have 186 00:07:38,250 --> 00:07:40,140 more or less columns, but apart from that 187 00:07:40,140 --> 00:07:43,110 they're very easy to create. Alright so 188 00:07:43,110 --> 00:07:44,190 now that we've actually done that and 189 00:07:44,190 --> 00:07:46,440 completed those changes, we can go back 190 00:07:46,440 --> 00:07:48,960 to our AppProvider class. We can now 191 00:07:48,960 --> 00:07:51,450 uncomment some code in that class. So 192 00:07:51,450 --> 00:07:53,070 firstly, I'm already here in the getType 193 00:07:53,070 --> 00:07:56,430 function, so I'm going to uncomment the 194 00:07:56,430 --> 00:07:58,110 code that we created but commented out, 195 00:07:58,110 --> 00:08:01,530 or that we pasted and commented out, and 196 00:08:01,530 --> 00:08:02,940 I'll uncomment that now because we've 197 00:08:02,940 --> 00:08:04,610 actually got the TimingsContract 198 00:08:04,610 --> 00:08:08,220 implemented. Then we'll go up to the 199 00:08:08,220 --> 00:08:11,880 buildUriMatcher function. We're 200 00:08:11,880 --> 00:08:14,040 going to uncomment the two lines 201 00:08:14,040 --> 00:08:16,560 relating to TimingsContract, and I'll 202 00:08:16,560 --> 00:08:18,000 comment out the next, uncomment the next 203 00:08:18,000 --> 00:08:20,940 line out as well. And then finally, go 204 00:08:20,940 --> 00:08:23,490 down to our query method, we've also got 205 00:08:23,490 --> 00:08:25,260 some comments in there that we can 206 00:08:25,260 --> 00:08:26,400 uncomment. So I'm just going to take a 207 00:08:26,400 --> 00:08:29,010 copy, or select rather, everything 208 00:08:29,010 --> 00:08:31,710 relating to TIMINGS, as well as the 209 00:08:31,710 --> 00:08:34,380 comment on the blank line after, and 210 00:08:34,380 --> 00:08:36,750 uncomment that all. So we're not sure what 211 00:08:36,750 --> 00:08:38,070 fields we're going to have in our 212 00:08:38,070 --> 00:08:40,469 database view, so we can't really create 213 00:08:40,469 --> 00:08:42,659 the DurationsContract class 214 00:08:42,659 --> 00:08:44,820 yet, but when we do it'll be just about 215 00:08:44,820 --> 00:08:47,250 the same process. There's one 216 00:08:47,250 --> 00:08:48,690 unimportant difference that I'll mention 217 00:08:48,690 --> 00:08:51,420 when we create it though. Alright so 218 00:08:51,420 --> 00:08:53,070 I'm going to stop the video here. In the 219 00:08:53,070 --> 00:08:54,390 next one we're going to work on the code 220 00:08:54,390 --> 00:08:56,460 for the insert, update and delete 221 00:08:56,460 --> 00:08:58,860 functions in this AppProvider class. 222 00:08:58,860 --> 00:09:02,600 So I'll see you in the next video.