1 00:00:04,830 --> 00:00:06,660 Alright so as I mentioned in the, 2 00:00:06,660 --> 00:00:08,280 towards the end of the previous video, 3 00:00:08,280 --> 00:00:10,710 we've currently got two rows and I've 4 00:00:10,710 --> 00:00:12,120 got them on the screen there. They've got 5 00:00:12,120 --> 00:00:14,490 a sort order of 2. So let's see how we 6 00:00:14,490 --> 00:00:16,650 can use the selection parameters to 7 00:00:16,650 --> 00:00:19,110 update several rows at once. So I'm going 8 00:00:19,110 --> 00:00:21,720 to go back to our code. Now once again, 9 00:00:21,720 --> 00:00:23,130 what I'll do is create a new function, 10 00:00:23,130 --> 00:00:25,110 and I'm going to put that above our test 11 00:00:25,110 --> 00:00:27,840 Update function just so that we can 12 00:00:27,840 --> 00:00:30,689 actually see what we're doing, and see 13 00:00:30,689 --> 00:00:32,040 some of the output as well. So we'll go 14 00:00:32,040 --> 00:00:35,870 back up. So I'm going to put that just below 15 00:00:35,870 --> 00:00:39,019 the onCreate method that we've got here, 16 00:00:39,019 --> 00:00:42,390 and I'll call this one testUpdateTwo because 17 00:00:42,390 --> 00:00:44,280 obviously we need a unique function name. 18 00:00:44,280 --> 00:00:46,109 Alright so what we're going to do here - the 19 00:00:46,109 --> 00:00:46,920 change we're going to make - we're going 20 00:00:46,920 --> 00:00:48,870 to change the Sort Order but we're going 21 00:00:48,870 --> 00:00:51,390 to change that for two entries. Actually 22 00:00:51,390 --> 00:00:52,739 we're going to change the description as well. 23 00:00:52,739 --> 00:00:54,570 So the entries I'm going to put in there, 24 00:00:54,570 --> 00:00:56,519 firstly there's the Sort Order, so TASK 25 00:00:56,519 --> 00:00:58,920 _SORT_ORDER. I'm going to set 26 00:00:58,920 --> 00:01:01,499 that to 99 - that's a number so no 27 00:01:01,499 --> 00:01:04,019 double quotes - and the description, we'll 28 00:01:04,019 --> 00:01:07,490 also change that to Completed for both. 29 00:01:07,490 --> 00:01:11,340 Alright next, outside of the apply code 30 00:01:11,340 --> 00:01:14,660 block, we need to add a val selection 31 00:01:14,660 --> 00:01:19,140 equals, it's going TasksContract dot 32 00:01:19,140 --> 00:01:23,150 Columns.TASK_SORT_ORDER 33 00:01:23,150 --> 00:01:26,670 and plus and double quotes a space 34 00:01:26,670 --> 00:01:29,670 equals 2 double quotes. That's going 35 00:01:29,670 --> 00:01:31,230 to be our selection criteria there, to 36 00:01:31,230 --> 00:01:33,300 choose which records, or which rows rather 37 00:01:33,300 --> 00:01:35,130 we want to update. I'm going to comment 38 00:01:35,130 --> 00:01:37,950 out the taskUri for the id 4, 39 00:01:37,950 --> 00:01:40,140 and what I'm going to do is change - and I'll 40 00:01:40,140 --> 00:01:41,280 just bring this up on the screen so we 41 00:01:41,280 --> 00:01:42,750 can see it a bit better - rowsAffected 42 00:01:42,750 --> 00:01:45,780 should now be contentResolver dot 43 00:01:45,780 --> 00:01:47,670 updates still. We're going to go back now 44 00:01:47,670 --> 00:01:49,860 instead of taskUri. We're 45 00:01:49,860 --> 00:01:51,540 going to call just our regular Tasks 46 00:01:51,540 --> 00:01:54,390 Contract.CONTENT_ 47 00:01:54,390 --> 00:01:56,220 URI. Then we're going to pass, and I'll put 48 00:01:56,220 --> 00:01:57,420 this on a separate line so it's easy 49 00:01:57,420 --> 00:01:58,020 to read, 50 00:01:58,020 --> 00:02:02,220 null and selection criteria. And actually I'll put 51 00:02:02,220 --> 00:02:04,440 values on the next line as well, and we 52 00:02:04,440 --> 00:02:06,210 can leave the TAG - logging tagging - as it 53 00:02:06,210 --> 00:02:08,848 is there on line 65 showing how many rows 54 00:02:08,848 --> 00:02:11,160 were affected. And obviously then, we need 55 00:02:11,160 --> 00:02:13,310 to go back up into our onCreate method, 56 00:02:13,310 --> 00:02:16,290 comment out the original testUpdate 57 00:02:16,290 --> 00:02:19,000 function - I said onCreate method 58 00:02:19,000 --> 00:02:21,240 but of course it's a function - and test 59 00:02:21,240 --> 00:02:26,730 UpdateTwo, we want to call that. Alright so 60 00:02:26,730 --> 00:02:30,490 we'll run this again, go back to our log 61 00:02:30,490 --> 00:02:34,240 cat, and you can see that I've made a 62 00:02:34,240 --> 00:02:36,040 critical error there, and this is 63 00:02:36,040 --> 00:02:38,170 something that you will almost certainly 64 00:02:38,170 --> 00:02:41,020 do in your career. And you can see what 65 00:02:41,020 --> 00:02:42,790 I've done is I haven't actually set the 66 00:02:42,790 --> 00:02:44,890 selection criteria, so consequently 67 00:02:44,890 --> 00:02:47,470 what's happened is, all the records in 68 00:02:47,470 --> 00:02:49,540 the table have been updated. You can see 69 00:02:49,540 --> 00:02:52,120 Sort order 99 is set for all four, and also 70 00:02:52,120 --> 00:02:54,130 the description has been set for all 71 00:02:54,130 --> 00:02:55,840 four. What I should've done, if we come back 72 00:02:55,840 --> 00:02:57,010 down here and have a look under test 73 00:02:57,010 --> 00:03:00,730 UpdateTwo, we defined the selection to be 74 00:03:00,730 --> 00:03:02,890 the SORT_ORDER, TASK_SORT_ORDER with a 75 00:03:02,890 --> 00:03:05,530 value of 2, but then I didn't use it in 76 00:03:05,530 --> 00:03:07,180 our contentResolver.update. So what 77 00:03:07,180 --> 00:03:08,920 I should have done is actually added 78 00:03:08,920 --> 00:03:10,720 that under the WHERE clause, effectively 79 00:03:10,720 --> 00:03:14,950 under this first argument, selection. But 80 00:03:14,950 --> 00:03:16,570 at this point in time I've now updated 81 00:03:16,570 --> 00:03:18,310 the database, so what I'm going to do is 82 00:03:18,310 --> 00:03:20,560 quickly pause the video. I'm going to go back 83 00:03:20,560 --> 00:03:22,450 to the state that the database was in 84 00:03:22,450 --> 00:03:25,150 prior to this call to the testUpdateTwo 85 00:03:25,150 --> 00:03:27,310 function, and then we'll continue. But a 86 00:03:27,310 --> 00:03:29,019 good lessen there, especially in 87 00:03:29,019 --> 00:03:31,420 situations like this, to really check and 88 00:03:31,420 --> 00:03:33,610 make sure that you put the changes in to 89 00:03:33,610 --> 00:03:34,959 avoid doing just what I did there, which 90 00:03:34,959 --> 00:03:37,000 was, of course, updating all records. So 91 00:03:37,000 --> 00:03:39,630 I'll be back shortly and we'll continue. 92 00:03:39,630 --> 00:03:43,030 Okay so I'm back now, and what I've done 93 00:03:43,030 --> 00:03:44,680 is I've restored it to the state now, 94 00:03:44,680 --> 00:03:46,810 where we're at just after we called the 95 00:03:46,810 --> 00:03:49,360 first update, the testUpdateTwo function. 96 00:03:49,360 --> 00:03:50,680 So you can see that at the moment we've 97 00:03:50,680 --> 00:03:52,390 got 4 records - number of rows returned 98 00:03:52,390 --> 00:03:55,299 4 - but also you can see that we've 99 00:03:55,299 --> 00:03:58,150 got our fourth record set to Name equals, 100 00:03:58,150 --> 00:04:00,640 Task names, Content Provider: Description: 101 00:04:00,640 --> 00:04:03,040 Record content providers video. So that's 102 00:04:03,040 --> 00:04:05,530 the status of the database just prior to 103 00:04:05,530 --> 00:04:08,769 us calling that second testUpdateTwo. 104 00:04:08,769 --> 00:04:10,090 So you can see now that I've got selection 105 00:04:10,090 --> 00:04:12,280 defined for the WHERE clause for the 106 00:04:12,280 --> 00:04:14,829 update - it's that argument - and then in 107 00:04:14,829 --> 00:04:16,209 terms of what we're going to execute up 108 00:04:16,209 --> 00:04:18,040 here in our onCreate function, it's 109 00:04:18,040 --> 00:04:21,250 about to execute testUpdateTwo. So let's 110 00:04:21,250 --> 00:04:23,020 give that another go now and just make 111 00:04:23,020 --> 00:04:25,030 sure that it actually works, or check 112 00:04:25,030 --> 00:04:28,780 that it works. 113 00:04:28,780 --> 00:04:30,490 Alright so that's a lot better this 114 00:04:30,490 --> 00:04:31,840 time now that I've added the selection 115 00:04:31,840 --> 00:04:34,180 criteria. You can see that firstly, that 116 00:04:34,180 --> 00:04:36,040 the log entries report, those two records 117 00:04:36,040 --> 00:04:38,590 are updated - number of records updated is 118 00:04:38,590 --> 00:04:41,050 equal to two - and we're going to also see, 119 00:04:41,050 --> 00:04:42,340 if you look down here, changes now to 120 00:04:42,340 --> 00:04:43,960 just the two entries down the bottom 121 00:04:43,960 --> 00:04:48,730 there; Sort order 99 set for the entries, 122 00:04:48,730 --> 00:04:50,740 that had prior to this, the Sort order of 123 00:04:50,740 --> 00:04:53,980 2, namely Tasks ID for Android N and 124 00:04:53,980 --> 00:04:56,920 also the newly created id 4, which was 125 00:04:56,920 --> 00:04:58,870 our Content Provider. So in other words, 126 00:04:58,870 --> 00:05:00,730 the bulk update updating more than one 127 00:05:00,730 --> 00:05:03,730 entry at a time has worked. Alright so 128 00:05:03,730 --> 00:05:06,460 that's how to use the selection, and 129 00:05:06,460 --> 00:05:09,580 we'll go back to our function again, by 130 00:05:09,580 --> 00:05:11,500 passing this selection which is 131 00:05:11,500 --> 00:05:12,880 effectively the WHERE clause on what 132 00:05:12,880 --> 00:05:15,370 records in this case, or what rows I 133 00:05:15,370 --> 00:05:17,410 should say, to update. But what is this fourth 134 00:05:17,410 --> 00:05:20,770 argument, this selectionArgs, used for? 135 00:05:20,770 --> 00:05:23,470 What's that all about? Well selectionArgs 136 00:05:23,470 --> 00:05:26,080 is a string array of values that are 137 00:05:26,080 --> 00:05:28,540 used in the selection criteria, and they're 138 00:05:28,540 --> 00:05:30,940 used to prevent SQL injection attacks. 139 00:05:30,940 --> 00:05:33,610 So a SQL injection attack is where an 140 00:05:33,610 --> 00:05:35,920 attacker causes specially crafted 141 00:05:35,920 --> 00:05:38,740 SQL statements to be executed against 142 00:05:38,740 --> 00:05:40,960 the database. Now if your code accepts 143 00:05:40,960 --> 00:05:43,660 selection criteria from user input, then 144 00:05:43,660 --> 00:05:45,370 the user could type in something quite 145 00:05:45,370 --> 00:05:48,670 dodgy. So as for example, the code 146 00:05:48,670 --> 00:05:50,590 that we've defined on line 60 there, if 147 00:05:50,590 --> 00:05:53,800 we'd got the value 2 in this case, from 148 00:05:53,800 --> 00:05:55,630 user input, then they could have entered 149 00:05:55,630 --> 00:05:57,100 something more than just 2. They could 150 00:05:57,100 --> 00:05:58,360 have entered something effectively like 151 00:05:58,360 --> 00:06:05,440 equals 2 semicolon drop table tasks. Now 152 00:06:05,440 --> 00:06:07,180 this won't work - we'd have to be a bit 153 00:06:07,180 --> 00:06:09,490 cleverer to fool the system - but it is 154 00:06:09,490 --> 00:06:11,770 possible to do. So let's actually run the 155 00:06:11,770 --> 00:06:14,080 app with that code, just to see what 156 00:06:14,080 --> 00:06:15,880 happens, and we should get an error 157 00:06:15,880 --> 00:06:20,430 message but let's just run that anyway. 158 00:06:20,430 --> 00:06:22,630 And what I should've done, I didn't quite 159 00:06:22,630 --> 00:06:24,730 change that properly. It should have been 160 00:06:24,730 --> 00:06:27,100 equals two, then I need to actually change 161 00:06:27,100 --> 00:06:30,700 that to put a right brace, a right 162 00:06:30,700 --> 00:06:32,620 parentheses. Let's just try running that 163 00:06:32,620 --> 00:06:38,850 again. 164 00:06:38,850 --> 00:06:40,990 This time we get an error. This is the 165 00:06:40,990 --> 00:06:42,820 error that I was trying to show you, and 166 00:06:42,820 --> 00:06:44,290 if we scroll over and take a look at the 167 00:06:44,290 --> 00:06:48,040 error, we get a syntax error as you can 168 00:06:48,040 --> 00:06:50,380 see there, trying to do it that way. But 169 00:06:50,380 --> 00:06:51,520 if we go back to what it was before, 170 00:06:51,520 --> 00:06:54,190 equals two, and we remove the parentheses, 171 00:06:54,190 --> 00:06:55,660 the right parentheses for some 172 00:06:55,660 --> 00:06:57,400 reason, that's clearly not going to work 173 00:06:57,400 --> 00:06:59,290 either. You saw what happened last time - 174 00:06:59,290 --> 00:07:02,470 we didn't get any output at all. So again, 175 00:07:02,470 --> 00:07:04,750 depending on how you try and do this, if 176 00:07:04,750 --> 00:07:06,910 you were setting what the user's actually 177 00:07:06,910 --> 00:07:08,590 typed in here, you may actually get a 178 00:07:08,590 --> 00:07:11,440 SQL exception pop up. The point here 179 00:07:11,440 --> 00:07:12,640 I'm trying to make here, is that 180 00:07:12,640 --> 00:07:14,860 Android Studio and the code that Android 181 00:07:14,860 --> 00:07:16,390 is developing, is getting a lot smarter 182 00:07:16,390 --> 00:07:19,030 at trying to figure out this code and 183 00:07:19,030 --> 00:07:20,410 trying to see whether someone's trying 184 00:07:20,410 --> 00:07:22,540 to do a SQL injection attack. 185 00:07:22,540 --> 00:07:24,760 Basically, what the point here is that a 186 00:07:24,760 --> 00:07:27,400 few years ago, removing the extra right 187 00:07:27,400 --> 00:07:29,950 parentheses that I did there would have 188 00:07:29,950 --> 00:07:33,040 been enough to have deleted the entire table 189 00:07:33,040 --> 00:07:34,360 from the database, but there's now 190 00:07:34,360 --> 00:07:35,950 prevention stopping that from happening 191 00:07:35,950 --> 00:07:38,200 these days, which is good. Basically 192 00:07:38,200 --> 00:07:39,850 database systems are getting wise to 193 00:07:39,850 --> 00:07:41,830 this sort of thing. So even if you did 194 00:07:41,830 --> 00:07:43,780 delete the extra right parentheses 195 00:07:43,780 --> 00:07:45,550 from the string, the tables won't be 196 00:07:45,550 --> 00:07:46,630 dropped and you saw when I ran this 197 00:07:46,630 --> 00:07:47,979 that they actually weren't dropped. 198 00:07:47,979 --> 00:07:49,720 SQLite won't execute multiple 199 00:07:49,720 --> 00:07:52,630 queries in a single call to a query. But 200 00:07:52,630 --> 00:07:55,090 even so, with that said, it is possible to 201 00:07:55,090 --> 00:07:56,200 come up with statements that are 202 00:07:56,200 --> 00:07:58,750 formatted so that something like a drop 203 00:07:58,750 --> 00:08:00,880 table command will be executed. So 204 00:08:00,880 --> 00:08:01,960 getting back to what we were talking about 205 00:08:01,960 --> 00:08:05,289 here, the selectionArgs parameter, the 206 00:08:05,289 --> 00:08:07,960 values provided in that selectionArgs 207 00:08:07,960 --> 00:08:10,750 parameter are sanitized to reduce the 208 00:08:10,750 --> 00:08:13,150 risk of SQL injection attacks, so it's 209 00:08:13,150 --> 00:08:15,370 definitely worth using them if your 210 00:08:15,370 --> 00:08:17,950 criteria uses values that a user has 211 00:08:17,950 --> 00:08:20,289 typed into your app. So all we have to do to 212 00:08:20,289 --> 00:08:22,720 use that parameter is to replace the 213 00:08:22,720 --> 00:08:24,640 values in the selection string with a 214 00:08:24,640 --> 00:08:26,919 question mark, and then put the actual 215 00:08:26,919 --> 00:08:30,430 values into another array. Then we can 216 00:08:30,430 --> 00:08:32,320 pass that array as the final parameter 217 00:08:32,320 --> 00:08:34,630 to that function. So let's actually have 218 00:08:34,630 --> 00:08:36,159 a look at how to do that, so if you're 219 00:08:36,159 --> 00:08:37,450 faced with that scenario you'll know 220 00:08:37,450 --> 00:08:40,809 what to do. So after selection, we're 221 00:08:40,809 --> 00:08:42,250 going to delete that so it's just set back to 222 00:08:42,250 --> 00:08:44,410 equal, but instead of two it's going to be 223 00:08:44,410 --> 00:08:48,430 equal question mark. Then on the next line 224 00:08:48,430 --> 00:08:50,310 it's going to be val 225 00:08:50,310 --> 00:08:55,800 selectionArgs is equal to arrayOf 226 00:08:55,800 --> 00:09:00,100 parentheses double quotes 99, rows 227 00:09:00,100 --> 00:09:01,420 affected we're going to leave, and I'm 228 00:09:01,420 --> 00:09:03,550 going to delete this, those two lines 229 00:09:03,550 --> 00:09:05,980 there, and selectionArgs, we're now going 230 00:09:05,980 --> 00:09:10,780 to pass selectionArgs. And just so we 231 00:09:10,780 --> 00:09:12,160 can see that it has been an update I'm 232 00:09:12,160 --> 00:09:14,950 going to change TASK_SORT_ORDER to 999. 233 00:09:14,950 --> 00:09:17,050 I'm going to change the TASK_DESCRIPTION 234 00:09:17,050 --> 00:09:19,930 to For deletion so we can actually see 235 00:09:19,930 --> 00:09:21,460 that this has actually worked. And 236 00:09:21,460 --> 00:09:23,260 obviously I'm not using 99 there because 237 00:09:23,260 --> 00:09:24,640 we've already updated that in a previous 238 00:09:24,640 --> 00:09:27,250 update call. Now we've only provided a 239 00:09:27,250 --> 00:09:29,980 single argument here for TASK_SORT_ORDER 240 00:09:29,980 --> 00:09:31,050 because that's our selection criteria, 241 00:09:31,050 --> 00:09:33,520 but it's still expecting an array, and 242 00:09:33,520 --> 00:09:36,790 notice also that the 99 is in double 243 00:09:36,790 --> 00:09:39,130 quotes in this case because we're adding it to 244 00:09:39,130 --> 00:09:41,500 an array. Now when the SQL statement's 245 00:09:41,500 --> 00:09:43,930 built up to perform the update, each of 246 00:09:43,930 --> 00:09:46,210 the values in args is used to replace 247 00:09:46,210 --> 00:09:47,980 the question marks in the selection. And 248 00:09:47,980 --> 00:09:50,230 they're replaced in order, and you have 249 00:09:50,230 --> 00:09:51,490 to make sure that there are the same 250 00:09:51,490 --> 00:09:53,380 number of args values as there are 251 00:09:53,380 --> 00:09:55,150 question marks. So when I run the app 252 00:09:55,150 --> 00:10:03,550 again now, number of rows updated equals 253 00:10:03,550 --> 00:10:05,470 2, and we've now got two entries down 254 00:10:05,470 --> 00:10:07,540 the bottom here; description is For 255 00:10:07,540 --> 00:10:09,880 deletion and the Sort order is 999 for 256 00:10:09,880 --> 00:10:11,770 both of them. So you've actually got a 257 00:10:11,770 --> 00:10:14,290 choice in how you specify a selection 258 00:10:14,290 --> 00:10:17,260 criteria when using the Content Provider. 259 00:10:17,260 --> 00:10:20,050 If all the values for the criteria come 260 00:10:20,050 --> 00:10:22,150 from inside your code, then it doesn't 261 00:10:22,150 --> 00:10:24,040 really matter which way or which 262 00:10:24,040 --> 00:10:26,140 approach, which method you use, but even 263 00:10:26,140 --> 00:10:28,180 so it is worth getting into the habit of 264 00:10:28,180 --> 00:10:30,490 using selectionArgs like we've actually 265 00:10:30,490 --> 00:10:32,320 used here. So I'd suggest you do that, 266 00:10:32,320 --> 00:10:34,810 again using that with a combination of 267 00:10:34,810 --> 00:10:37,080 the question marks for your selection. 268 00:10:37,080 --> 00:10:39,160 Alright so the last thing we now need to 269 00:10:39,160 --> 00:10:41,380 know how to do, or to test rather, is 270 00:10:41,380 --> 00:10:43,360 deletion, and as you'd expect this works 271 00:10:43,360 --> 00:10:45,970 very similarly to updating, except we 272 00:10:45,970 --> 00:10:47,710 don't have to specify the ContentValues. 273 00:10:47,710 --> 00:10:51,580 So I'm going to copy the testUpdate code. Let's 274 00:10:51,580 --> 00:10:55,090 just grab that. I'm going to put it up 275 00:10:55,090 --> 00:10:58,870 the top here and we'll call this one 276 00:10:58,870 --> 00:11:03,300 testDelete. 277 00:11:03,300 --> 00:11:06,730 So in terms of what we need to add, we don't 278 00:11:06,730 --> 00:11:08,860 need to pass a ContentValues object at 279 00:11:08,860 --> 00:11:10,480 all so I'm going to delete that. All we 280 00:11:10,480 --> 00:11:12,870 need to do is have a URI set to 281 00:11:12,870 --> 00:11:15,700 specify the ID we want to delete. In this 282 00:11:15,700 --> 00:11:17,470 case, this is for a single deletion or 283 00:11:17,470 --> 00:11:21,250 pass id 3; rows affected, the deletion 284 00:11:21,250 --> 00:11:23,260 call hasn't got ContentValues because 285 00:11:23,260 --> 00:11:25,420 we're deleting not updating, so I can 286 00:11:25,420 --> 00:11:28,900 delete that second argument. And obviously 287 00:11:28,900 --> 00:11:30,730 update now has changed to delete - 288 00:11:30,730 --> 00:11:33,070 we're calling the delete function from 289 00:11:33,070 --> 00:11:35,080 our Content Provider. Number of rows 290 00:11:35,080 --> 00:11:40,090 deleted is then our rows affected. So 291 00:11:40,090 --> 00:11:41,860 that's the testDelete. That's pretty 292 00:11:41,860 --> 00:11:43,450 straightforward. Then we just need to 293 00:11:43,450 --> 00:11:45,400 go to our onCreate in this case, and 294 00:11:45,400 --> 00:11:47,470 I'm going to comment out testUpdateTwo, 295 00:11:47,470 --> 00:11:49,810 and we're going to call our testDelete 296 00:11:49,810 --> 00:11:52,690 function that we just wrote. So run the 297 00:11:52,690 --> 00:11:58,510 app again and we'll check our log. Number 298 00:11:58,510 --> 00:12:01,210 of rows deleted equals one, and we've now 299 00:12:01,210 --> 00:12:02,620 only got three entries as you can see 300 00:12:02,620 --> 00:12:06,700 here; IDs 1, 2 and 4, and 301 00:12:06,700 --> 00:12:08,620 obviously we specified ID 3 and 302 00:12:08,620 --> 00:12:10,540 that got deleted. And you can see 303 00:12:10,540 --> 00:12:13,150 there, by the way, the deletion, there's our 304 00:12:13,150 --> 00:12:16,600 URI and it's got 3 as the ID passed 305 00:12:16,600 --> 00:12:18,550 on the end of it. Alright, so the Kotlin 306 00:12:18,550 --> 00:12:19,990 task basically got deleted there so 307 00:12:19,990 --> 00:12:21,850 that's working fine. Now we can also 308 00:12:21,850 --> 00:12:25,030 specify a URI without an ID, and instead 309 00:12:25,030 --> 00:12:27,400 use a selection to specify which row or 310 00:12:27,400 --> 00:12:29,800 rows to delete, just like when we updated 311 00:12:29,800 --> 00:12:31,930 several rows earlier in the video. So 312 00:12:31,930 --> 00:12:35,110 let's go and do that. So I'll come down here 313 00:12:35,110 --> 00:12:38,230 and I'll take a, and what I'll do is I'll 314 00:12:38,230 --> 00:12:40,390 take a copy of testUpdateTwo, because this 315 00:12:40,390 --> 00:12:42,660 has got some code there that we can use 316 00:12:42,660 --> 00:12:46,120 which will be quite handy, even though 317 00:12:46,120 --> 00:12:50,320 we'll need to delete some of it. So we'll 318 00:12:50,320 --> 00:12:53,170 call that test deletion two, testDelete 319 00:12:53,170 --> 00:12:57,220 Two will do. So firstly, we don't need a 320 00:12:57,220 --> 00:12:58,660 ContentValues object so I'm going to 321 00:12:58,660 --> 00:13:01,240 delete that. Our selection, we're going to 322 00:13:01,240 --> 00:13:03,460 start off with TasksContract.Columns. 323 00:13:03,460 --> 00:13:05,200 Let's try deleting something by Task 324 00:13:05,200 --> 00:13:09,640 description, so dot TASK_ 325 00:13:09,640 --> 00:13:12,130 DESCRIPTION, and we're going to leave it as 326 00:13:12,130 --> 00:13:14,350 plus, equals and then a 327 00:13:14,350 --> 00:13:16,330 question mark there. The selectionArgs 328 00:13:16,330 --> 00:13:19,570 this time, we going to, instead of 99, we're 329 00:13:19,570 --> 00:13:22,480 going to pass For deletion because if you 330 00:13:22,480 --> 00:13:25,720 remember we've currently got entries 331 00:13:25,720 --> 00:13:28,210 there For deletion. We've got that entry there. 332 00:13:28,210 --> 00:13:30,370 We've also got this one here, so IDs 2 333 00:13:30,370 --> 00:13:33,100 and 4 are currently set, or have the 334 00:13:33,100 --> 00:13:35,440 DESCRIPTION, TASK_DESCRIPTION set to 335 00:13:35,440 --> 00:13:37,600 For deletion. And then the rowsAffected 336 00:13:37,600 --> 00:13:39,760 line is going to be calling the delete 337 00:13:39,760 --> 00:13:42,310 and of the update, so I'm going to do 338 00:13:42,310 --> 00:13:45,520 that. So I'll change that to delete, so I'm going 339 00:13:45,520 --> 00:13:46,900 to leave that unchanged, CONTENT__URI. 340 00:13:46,900 --> 00:13:49,030 Then values, we haven't got that anymore 341 00:13:49,030 --> 00:13:51,430 so I'm going to delete that; selection 342 00:13:51,430 --> 00:13:53,470 and then selectionArgs are the two 343 00:13:53,470 --> 00:13:55,870 things that we've defined on line 58 and 344 00:13:55,870 --> 00:13:58,450 59, and we'll change this number of rows 345 00:13:58,450 --> 00:14:00,430 affected, updated rather, to Number of 346 00:14:00,430 --> 00:14:02,950 rows deleted. So that should be all we 347 00:14:02,950 --> 00:14:05,110 need to do, and we'll just go back up to 348 00:14:05,110 --> 00:14:09,310 onCreate, comment out testDelete, then 349 00:14:09,310 --> 00:14:11,980 we'll call our testDeleteTwo function. 350 00:14:11,980 --> 00:14:15,370 And let's try running that again to make 351 00:14:15,370 --> 00:14:20,020 sure it works. You can see here, Number of 352 00:14:20,020 --> 00:14:22,720 rows deleted equals 2, and looking at 353 00:14:22,720 --> 00:14:24,130 the number of entries in our database 354 00:14:24,130 --> 00:14:26,500 from our query, number of rows returned, 355 00:14:26,500 --> 00:14:28,630 rows in returned cursor equals 1. We've 356 00:14:28,630 --> 00:14:30,550 now just got the one entry which is ID 357 00:14:30,550 --> 00:14:33,190 1, which is our TaskTimer app creation 358 00:14:33,190 --> 00:14:34,690 with the description there - Sort order 359 00:14:34,690 --> 00:14:38,050 null ID 1. So that's our Content Provider 360 00:14:38,050 --> 00:14:40,090 now working - we've actually tested it. So 361 00:14:40,090 --> 00:14:41,830 in the next video, now that we've got a 362 00:14:41,830 --> 00:14:44,200 fully working Content Provider, we're 363 00:14:44,200 --> 00:14:45,430 going to start work on the user 364 00:14:45,430 --> 00:14:47,740 interface for this app. So I'll see you 365 00:14:47,740 --> 00:14:50,310 in the next video.