1 00:00:04,730 --> 00:00:06,859 In the last video, we looked at how to 2 00:00:06,859 --> 00:00:10,160 use the Android AsyncTask class to run 3 00:00:10,160 --> 00:00:12,289 code in a background thread, so that we 4 00:00:12,289 --> 00:00:14,089 didn't cause our app to block while 5 00:00:14,089 --> 00:00:16,070 waiting for a long-running process, such 6 00:00:16,070 --> 00:00:17,779 as downloading data from the Internet. 7 00:00:17,779 --> 00:00:19,279 Now one thing that I didn't 8 00:00:19,279 --> 00:00:20,720 mention about that doInBackground 9 00:00:20,720 --> 00:00:24,020 method, was the var arg modifier in the 10 00:00:24,020 --> 00:00:26,899 parameter list. Now, variable length 11 00:00:26,899 --> 00:00:28,820 argument lists allow you to provide 12 00:00:28,820 --> 00:00:31,550 several values for the parameter. Now all 13 00:00:31,550 --> 00:00:33,170 the arguments you provide must be of the 14 00:00:33,170 --> 00:00:35,420 same type, so they must all be strings 15 00:00:35,420 --> 00:00:37,280 in this particular case, but we could 16 00:00:37,280 --> 00:00:39,110 pass in several URLs and have them 17 00:00:39,110 --> 00:00:41,270 downloaded one after the other, if we 18 00:00:41,270 --> 00:00:42,140 wanted to do so. 19 00:00:42,140 --> 00:00:43,550 Now we're not actually going to do 20 00:00:43,550 --> 00:00:45,260 that, but the option's there if you need 21 00:00:45,260 --> 00:00:47,030 it. So we're only going to use a single 22 00:00:47,030 --> 00:00:49,280 string value when we get the doin 23 00:00:49,280 --> 00:00:50,930 Background method to do our downloading, 24 00:00:50,930 --> 00:00:52,940 but you can pass multiple parameters 25 00:00:52,940 --> 00:00:55,400 to it if you want to. Now because it's 26 00:00:55,400 --> 00:00:59,030 specified as var arg - and this is here, 27 00:00:59,030 --> 00:01:00,290 you can see on line 30, is what I'm 28 00:01:00,290 --> 00:01:03,530 talking about. The p0 parameter is 29 00:01:03,530 --> 00:01:06,979 accessed as a string array inside the 30 00:01:06,979 --> 00:01:09,139 function. So the first item in the array 31 00:01:09,139 --> 00:01:11,840 is p0,with 0 in square brackets, and 32 00:01:11,840 --> 00:01:13,819 that's the value we included in the 33 00:01:13,819 --> 00:01:15,649 logcat, which is effectively the first 34 00:01:15,649 --> 00:01:18,170 parameter. Now if several URLs were 35 00:01:18,170 --> 00:01:20,569 provided when calling the execute method, 36 00:01:20,569 --> 00:01:23,270 we can access them as p0 square 37 00:01:23,270 --> 00:01:26,030 brackets 1, p0 square brackets 2 and so 38 00:01:26,030 --> 00:01:28,039 on. So what I mean by that is, we can we 39 00:01:28,039 --> 00:01:33,920 can access them to something like p0[1], p0[2], 40 00:01:33,920 --> 00:01:38,899 so on and so forth. Now p0 is an awful 41 00:01:38,899 --> 00:01:40,399 name for a parameter, so I'm going to 42 00:01:40,399 --> 00:01:42,709 rename that to URL which makes a lot 43 00:01:42,709 --> 00:01:46,069 more sense. Now Android Studio will 44 00:01:46,069 --> 00:01:48,049 rename all occurrences for us, when we 45 00:01:48,049 --> 00:01:50,079 right-click and choose Refactor Rename. 46 00:01:50,079 --> 00:01:52,849 So I'm gonna go ahead and do that; select 47 00:01:52,849 --> 00:01:55,369 Refactor then Rename, and I'm 48 00:01:55,369 --> 00:01:58,090 going to call that URL and press Enter. 49 00:01:58,090 --> 00:02:00,469 And you can see, conveniently it's also 50 00:02:00,469 --> 00:02:03,079 changed the reference to what was p0 on 51 00:02:03,079 --> 00:02:06,409 line 31. Now hopefully the code generator 52 00:02:06,409 --> 00:02:08,300 will use a better name in future. The 53 00:02:08,300 --> 00:02:09,889 more usual args would have been better 54 00:02:09,889 --> 00:02:13,069 than p0. Now we saw how to start the 55 00:02:13,069 --> 00:02:14,599 background task, which just involves 56 00:02:14,599 --> 00:02:17,030 creating an instance of our Download 57 00:02:17,030 --> 00:02:18,440 Data class and calling 58 00:02:18,440 --> 00:02:20,900 it's execute method, with any arguments 59 00:02:20,900 --> 00:02:23,210 that it needs. When the AsyncTask 60 00:02:23,210 --> 00:02:26,060 class's execute method's called, it takes 61 00:02:26,060 --> 00:02:27,380 care of setting up all the 62 00:02:27,380 --> 00:02:29,330 multi-threading, and then runs doin 63 00:02:29,330 --> 00:02:31,970 Background on a separate thread, passing 64 00:02:31,970 --> 00:02:33,650 it whatever arguments we gave to the 65 00:02:33,650 --> 00:02:35,900 execute method. Now when the task 66 00:02:35,900 --> 00:02:38,420 completes, the AsyncTask gets the 67 00:02:38,420 --> 00:02:40,250 return value from the other thread, and 68 00:02:40,250 --> 00:02:42,980 then calls the onPostExecute method 69 00:02:42,980 --> 00:02:45,800 with the return value. So with that said, 70 00:02:45,800 --> 00:02:47,390 now let's get our background thread to 71 00:02:47,390 --> 00:02:49,760 do something a little bit more useful. So 72 00:02:49,760 --> 00:02:51,050 we're going to make some changes to the 73 00:02:51,050 --> 00:02:52,460 code now, and I'm just going to close the 74 00:02:52,460 --> 00:02:54,230 logcat for now to make a bit more, I'll 75 00:02:54,230 --> 00:02:55,420 give it a bit more screen real estate. 76 00:02:55,420 --> 00:02:58,070 So we're going to leave the first log 77 00:02:58,070 --> 00:03:01,280 there - the log message. We're going to 78 00:03:01,280 --> 00:03:04,730 come up here and type in val space RSS 79 00:03:04,730 --> 00:03:09,790 Feed is equal to download XML 80 00:03:09,790 --> 00:03:13,220 parenthesis url square brackets with a 81 00:03:13,220 --> 00:03:16,850 zero in the middle. And then on the next 82 00:03:16,850 --> 00:03:19,570 line, I'm going to type if parentheses 83 00:03:19,570 --> 00:03:27,530 rssFeed dot is empty, then open a code 84 00:03:27,530 --> 00:03:34,040 block. We're gonna type Log.e tag, and in 85 00:03:34,040 --> 00:03:38,720 parentheses, doInBackground : 86 00:03:38,720 --> 00:03:41,989 space error downloading, to let us know 87 00:03:41,989 --> 00:03:43,520 there was a problem, and obviously, that's 88 00:03:43,520 --> 00:03:45,620 closing off the code block. Then 89 00:03:45,620 --> 00:03:46,880 on the last line, instead of returning 90 00:03:46,880 --> 00:03:48,860 doInBackground completed as a string, 91 00:03:48,860 --> 00:03:53,510 we're going to return the rssFeed. So when 92 00:03:53,510 --> 00:03:55,700 you use a vararg parameter, the actual 93 00:03:55,700 --> 00:03:57,680 values get passed into the method as an 94 00:03:57,680 --> 00:03:59,209 array - an array of strings, in this 95 00:03:59,209 --> 00:04:01,340 particular case. And because we're only 96 00:04:01,340 --> 00:04:02,959 going to call this method with a single 97 00:04:02,959 --> 00:04:04,610 parameter, we won't actually bother 98 00:04:04,610 --> 00:04:06,380 writing code to get more than one string. 99 00:04:06,380 --> 00:04:08,209 The one we're interested in will be the 100 00:04:08,209 --> 00:04:10,100 first one in the array, and that's this 101 00:04:10,100 --> 00:04:12,200 url[0] which you can see me referencing, 102 00:04:12,200 --> 00:04:15,019 which we've talked about previously. Now 103 00:04:15,019 --> 00:04:16,100 of course, we haven't written the 104 00:04:16,100 --> 00:04:18,709 download XML method yet, but that'll take 105 00:04:18,709 --> 00:04:21,649 care of downloading the feed, and it'll 106 00:04:21,649 --> 00:04:23,600 return a string containing the XML when 107 00:04:23,600 --> 00:04:25,610 it's finished. Now if anything goes wrong 108 00:04:25,610 --> 00:04:27,979 it's going to return an empty string, so 109 00:04:27,979 --> 00:04:29,390 that we can check to see if the return 110 00:04:29,390 --> 00:04:31,800 value is empty, and log an error if 111 00:04:31,800 --> 00:04:35,009 is. Now normally we'd use Log.d for 112 00:04:35,009 --> 00:04:37,470 writing a debug information to the log, 113 00:04:37,470 --> 00:04:40,199 but this will actually be an error. Now 114 00:04:40,199 --> 00:04:42,150 log.d entries shouldn't appear in the 115 00:04:42,150 --> 00:04:44,220 logcat when we release the production 116 00:04:44,220 --> 00:04:46,139 version of our apps. The build process 117 00:04:46,139 --> 00:04:48,690 removes them from the code. But in this 118 00:04:48,690 --> 00:04:50,129 particular case, we'd really want 119 00:04:50,129 --> 00:04:52,050 this message to remain, so I'm using 120 00:04:52,050 --> 00:04:55,229 log.e instead of Log.d to log 121 00:04:55,229 --> 00:04:57,270 this message as an error, rather than a 122 00:04:57,270 --> 00:04:59,729 debug level. And of course, I'm referring to 123 00:04:59,729 --> 00:05:03,659 the entry on line 34. Alright, so all 124 00:05:03,659 --> 00:05:05,969 the code we put in doInBackground will 125 00:05:05,969 --> 00:05:07,949 run asynchronously on a background 126 00:05:07,949 --> 00:05:10,199 thread, and that also includes any 127 00:05:10,199 --> 00:05:12,449 methods that it calls. So that means 128 00:05:12,449 --> 00:05:15,300 download XML will also be running on the 129 00:05:15,300 --> 00:05:16,139 background thread. 130 00:05:16,139 --> 00:05:18,479 Now when the download XML function 131 00:05:18,479 --> 00:05:21,060 returns, we'll either have the XML in the 132 00:05:21,060 --> 00:05:23,699 rssFeed string, in which case we'll just 133 00:05:23,699 --> 00:05:26,250 return it, or if we've got an empty string, in 134 00:05:26,250 --> 00:05:27,840 which case, we're going to log an error 135 00:05:27,840 --> 00:05:31,110 before returning. Now the download XML 136 00:05:31,110 --> 00:05:32,879 function will take a fairly typical 137 00:05:32,879 --> 00:05:35,159 approach. That's pretty well common when 138 00:05:35,159 --> 00:05:36,419 you're reading from a stream of data, 139 00:05:36,419 --> 00:05:39,330 such as data over the internet or data 140 00:05:39,330 --> 00:05:41,550 stored in a file on disk. So we're going 141 00:05:41,550 --> 00:05:44,190 to start by opening a http connection, 142 00:05:44,190 --> 00:05:46,590 which we use to access the stream of 143 00:05:46,590 --> 00:05:49,020 data coming over the internet from a URL. 144 00:05:49,020 --> 00:05:51,509 Now the connection provides an input 145 00:05:51,509 --> 00:05:53,490 stream, so we're going to be using an 146 00:05:53,490 --> 00:05:56,130 input stream reader to read the data 147 00:05:56,130 --> 00:05:58,289 from it. Now whenever you're dealing with 148 00:05:58,289 --> 00:05:59,940 a stream that's coming from a slow 149 00:05:59,940 --> 00:06:02,460 device, such as a disk drive or an 150 00:06:02,460 --> 00:06:04,529 internet connection, it's actually a good 151 00:06:04,529 --> 00:06:07,469 idea to use a buffered reader. Now a 152 00:06:07,469 --> 00:06:09,680 buffered reader, as the name suggests, 153 00:06:09,680 --> 00:06:11,819 buffers the data coming in from the 154 00:06:11,819 --> 00:06:13,889 stream. So instead of repeatedly 155 00:06:13,889 --> 00:06:16,110 accessing the hard drive or network, a 156 00:06:16,110 --> 00:06:18,479 block of data is read into a buffer in 157 00:06:18,479 --> 00:06:20,879 memory, and our program can read from the 158 00:06:20,879 --> 00:06:23,099 buffer. So that's the recommended way to 159 00:06:23,099 --> 00:06:25,710 read data from an input stream, so our 160 00:06:25,710 --> 00:06:28,050 app will use a buffered reader. I'm 161 00:06:28,050 --> 00:06:29,610 going to type the code for that inside 162 00:06:29,610 --> 00:06:31,919 the DownloadData class, and then we'll 163 00:06:31,919 --> 00:06:34,009 actually discuss the actual reading. 164 00:06:34,009 --> 00:06:36,539 Now I've already horrified any Java 165 00:06:36,539 --> 00:06:38,759 developers taking this course, so now I'm 166 00:06:38,759 --> 00:06:40,589 going to turn the tables, and I'm going 167 00:06:40,589 --> 00:06:42,570 to horrify any Kotlin developers in the 168 00:06:42,570 --> 00:06:44,669 course. Now don't worry, this next bit of 169 00:06:44,669 --> 00:06:45,220 code is only 170 00:06:45,220 --> 00:06:47,590 temporary, and we're gonna be rewriting it 171 00:06:47,590 --> 00:06:50,710 into more idiomatic Kotlin shortly. The 172 00:06:50,710 --> 00:06:52,630 entire block of code that I'm about to 173 00:06:52,630 --> 00:06:54,790 type in, in the rest of this video, can be 174 00:06:54,790 --> 00:06:56,650 written in just a few lines as we'll see, 175 00:06:56,650 --> 00:06:59,020 but it is much easier to understand if 176 00:06:59,020 --> 00:07:01,900 we use and see the long version first. So 177 00:07:01,900 --> 00:07:04,210 let's go ahead and do that. So I'm gonna 178 00:07:04,210 --> 00:07:08,370 start with the new function; private fun 179 00:07:08,370 --> 00:07:11,650 downloadXML, and as an argument, it's 180 00:07:11,650 --> 00:07:14,920 gonna be urlPath colon string 181 00:07:14,920 --> 00:07:19,600 question mark colon string, and then 182 00:07:19,600 --> 00:07:21,480 we'll use the left and right curly braces. 183 00:07:21,480 --> 00:07:23,590 And we're going to start by typing val 184 00:07:23,590 --> 00:07:31,060 xmlResult equals string builder. I'm 185 00:07:31,060 --> 00:07:34,750 gonna do a try, then within the try I'm gonna 186 00:07:34,750 --> 00:07:41,440 type val url equals URL urlPath val 187 00:07:41,440 --> 00:07:46,290 connection colon HttpURLConnection. 188 00:07:46,290 --> 00:07:48,480 Make sure you actually type here, the 189 00:07:48,480 --> 00:07:51,940 HttpURLConnection. In the past, students 190 00:07:51,940 --> 00:07:54,400 have actually typed Https, which is an 191 00:07:54,400 --> 00:07:55,750 entirely separate thing. So make sure you 192 00:07:55,750 --> 00:07:57,880 choose the correct one. So that's equal 193 00:07:57,880 --> 00:08:01,720 to url.openConnection 194 00:08:01,720 --> 00:08:06,280 parentheses, then space as HttpURL 195 00:08:06,280 --> 00:08:11,140 Connection, and again, not Https. Next, on 196 00:08:11,140 --> 00:08:13,690 the next line, val response is equal 197 00:08:13,690 --> 00:08:18,780 to connection.responseCode Log.d 198 00:08:18,780 --> 00:08:21,820 TAG and double quotes after the comma, 199 00:08:21,820 --> 00:08:28,690 downloadXML : The response code was, and 200 00:08:28,690 --> 00:08:32,289 dollar response. On the next line, we're 201 00:08:32,289 --> 00:08:33,940 going to type - actually we'll leave a space there 202 00:08:33,940 --> 00:08:36,700 - on the line after that, val inputStream 203 00:08:36,700 --> 00:08:42,179 is equal to connection.inputStream. 204 00:08:42,179 --> 00:08:47,200 Then val inputStreamReader equals 205 00:08:47,200 --> 00:08:54,190 InputStreamReader inputStream, and val 206 00:08:54,190 --> 00:08:58,830 reader is equal to BufferedReader 207 00:08:58,830 --> 00:09:02,350 parentheses inputStreamReader - oops, 208 00:09:02,350 --> 00:09:05,080 parentheses there - then InputStream 209 00:09:05,080 --> 00:09:09,100 Reader. Alright, so starting off on line 210 00:09:09,100 --> 00:09:11,470 forty-six, I'm just using a String 211 00:09:11,470 --> 00:09:12,760 Builder, because we're going to be 212 00:09:12,760 --> 00:09:14,680 appending to the string a lot as we read 213 00:09:14,680 --> 00:09:17,650 characters from the inputStream. Now a 214 00:09:17,650 --> 00:09:19,390 StringBuilder is more efficient than 215 00:09:19,390 --> 00:09:21,670 just concatenating strings, and you'll 216 00:09:21,670 --> 00:09:23,560 see how that works in a minute. So the 217 00:09:23,560 --> 00:09:25,570 next thing you may find strange is the 218 00:09:25,570 --> 00:09:28,060 try block. When dealing with data from an 219 00:09:28,060 --> 00:09:30,040 external source, which basically means 220 00:09:30,040 --> 00:09:31,510 anything that isn't the computer's 221 00:09:31,510 --> 00:09:33,490 memory, there are actually a lot of 222 00:09:33,490 --> 00:09:35,980 things that can go wrong. The device may 223 00:09:35,980 --> 00:09:37,990 not be connected to the Internet, or the 224 00:09:37,990 --> 00:09:39,280 connection may drop while you're 225 00:09:39,280 --> 00:09:41,680 downloading data. It's possible that the 226 00:09:41,680 --> 00:09:43,300 Apple website might be down, which 227 00:09:43,300 --> 00:09:45,460 is rare, but you can't count on any 228 00:09:45,460 --> 00:09:47,470 websites being available 100% of the 229 00:09:47,470 --> 00:09:50,650 time. And it's also possible that the URL 230 00:09:50,650 --> 00:09:52,960 passed into the method isn't valid, which 231 00:09:52,960 --> 00:09:54,220 would prevent the connections from being 232 00:09:54,220 --> 00:09:57,040 made in the first place. So a try block 233 00:09:57,040 --> 00:09:59,290 is a way to wrap up a section of code, 234 00:09:59,290 --> 00:10:01,510 and catch any exceptions that occur 235 00:10:01,510 --> 00:10:04,180 while it's executing. Now the first 236 00:10:04,180 --> 00:10:05,800 exception that would be thrown in that 237 00:10:05,800 --> 00:10:08,560 code, is when we create a URL from the 238 00:10:08,560 --> 00:10:10,870 string that was passed in to download 239 00:10:10,870 --> 00:10:13,360 XML. There's no guarantee that our 240 00:10:13,360 --> 00:10:14,920 download XML method will be given a 241 00:10:14,920 --> 00:10:18,100 valid URL, in the URL path parameter, and 242 00:10:18,100 --> 00:10:20,740 if the method isn't valid, a malformed 243 00:10:20,740 --> 00:10:23,380 URL exception will be thrown. Now 244 00:10:23,380 --> 00:10:25,600 the way we deal with the exception is to 245 00:10:25,600 --> 00:10:29,110 catch it using a catch block. So what 246 00:10:29,110 --> 00:10:30,580 I'm going to do is, just move up here a 247 00:10:30,580 --> 00:10:33,910 little bit more, and after the right 248 00:10:33,910 --> 00:10:36,280 curly brace which closes off the try 249 00:10:36,280 --> 00:10:38,400 block, we're going to need to type catch 250 00:10:38,400 --> 00:10:42,490 parentheses e : and MalformedURL 251 00:10:42,490 --> 00:10:44,550 Exception, and select that from the list. 252 00:10:44,550 --> 00:10:47,140 You'll open a code block, and then type 253 00:10:47,140 --> 00:10:51,120 Log.e parentheses TAG comma space 254 00:10:51,120 --> 00:10:59,410 downloadXML. So invalid URL dollar left 255 00:10:59,410 --> 00:11:03,340 and right curly braces, e.message. Now 256 00:11:03,340 --> 00:11:05,680 I've used Log.e again there, 257 00:11:05,680 --> 00:11:07,600 rather than log.d, because this is an 258 00:11:07,600 --> 00:11:10,720 error and not just debug information. And 259 00:11:10,720 --> 00:11:11,720 you'll see that 260 00:11:11,720 --> 00:11:13,579 entry behind being logged to logcat, 261 00:11:13,579 --> 00:11:15,620 when we come to run the program because, 262 00:11:15,620 --> 00:11:17,480 at the moment, we're calling the Async, 263 00:11:17,480 --> 00:11:20,329 the AsyncTask's execute method with a 264 00:11:20,329 --> 00:11:23,240 very invalid URL - the string URL goes 265 00:11:23,240 --> 00:11:26,209 here. Now the next exception that we may 266 00:11:26,209 --> 00:11:28,310 get - that's an i/o exception. 267 00:11:28,310 --> 00:11:30,680 Now the first place we make an exception 268 00:11:30,680 --> 00:11:35,180 is on this line here, line 51, when we try 269 00:11:35,180 --> 00:11:37,399 to open the connection. In fact, an i/o 270 00:11:37,399 --> 00:11:38,870 exception can be thrown 271 00:11:38,870 --> 00:11:40,730 whenever code performs an input or 272 00:11:40,730 --> 00:11:42,860 output operation, such as reading or 273 00:11:42,860 --> 00:11:45,019 writing to a disk file or, like here, 274 00:11:45,019 --> 00:11:46,579 accessing the Internet. 275 00:11:46,579 --> 00:11:50,029 Now although we have a valid URL - URL if 276 00:11:50,029 --> 00:11:52,399 the code hasn't got that far - it may not 277 00:11:52,399 --> 00:11:54,410 be possible to open the connection if 278 00:11:54,410 --> 00:11:55,970 there's a problem with our internet 279 00:11:55,970 --> 00:11:58,100 connection. Now it's also possible that 280 00:11:58,100 --> 00:12:00,560 the URL may refer to a server that 281 00:12:00,560 --> 00:12:02,569 doesn't exist. Now, for example, if we 282 00:12:02,569 --> 00:12:05,899 spelt to Apple incorrectly as appl. So 283 00:12:05,899 --> 00:12:07,100 we're going to add another catch block 284 00:12:07,100 --> 00:12:09,350 here, under the first one, to catch IO 285 00:12:09,350 --> 00:12:11,000 exceptions. So go ahead and do that. 286 00:12:11,000 --> 00:12:15,519 So after the closing curly brace, catch 287 00:12:15,519 --> 00:12:21,410 parentheses e : IOException, and 288 00:12:21,410 --> 00:12:24,319 then closing parentheses and then open 289 00:12:24,319 --> 00:12:26,509 the code block. Log.E because it's 290 00:12:26,509 --> 00:12:28,850 an error again, TAG in parentheses comma 291 00:12:28,850 --> 00:12:31,579 space, then double quotes. Then it's gonna 292 00:12:31,579 --> 00:12:33,980 be downloadXML : 293 00:12:33,980 --> 00:12:41,389 IO Exception reading data : 294 00:12:41,389 --> 00:12:42,949 then dollar, then left and right curly 295 00:12:42,949 --> 00:12:46,759 braces, e.message again. So as you 296 00:12:46,759 --> 00:12:48,199 can see, you can have multiple catch 297 00:12:48,199 --> 00:12:50,000 blocks and when an exception's 298 00:12:50,000 --> 00:12:52,129 thrown, Kotlin will go through them in 299 00:12:52,129 --> 00:12:54,470 order, until it finds the first one that 300 00:12:54,470 --> 00:12:56,379 matches the exception that was thrown. 301 00:12:56,379 --> 00:12:59,180 Now the order that you catch the 302 00:12:59,180 --> 00:13:01,879 exceptions is important, because in our 303 00:13:01,879 --> 00:13:04,459 code here, a MalformedURLException is 304 00:13:04,459 --> 00:13:07,129 a subclass of IOException. Now we 305 00:13:07,129 --> 00:13:08,420 can check that if we hold down the 306 00:13:08,420 --> 00:13:10,939 command key, and click on the Malformed 307 00:13:10,939 --> 00:13:12,980 URLException, and on a PC running 308 00:13:12,980 --> 00:13:14,089 Windows or Linux that will be the 309 00:13:14,089 --> 00:13:16,610 Ctrl key. So we come down there - go to 310 00:13:16,610 --> 00:13:21,199 to Malformed Exception and click, and 311 00:13:21,199 --> 00:13:22,370 we can jump to the source for the 312 00:13:22,370 --> 00:13:24,439 exception class, as you can see here, and 313 00:13:24,439 --> 00:13:26,000 we can see that it extends 314 00:13:26,000 --> 00:13:28,100 IOException. So MalformedURL 315 00:13:28,100 --> 00:13:30,230 Exception on line ten, extends IO 316 00:13:30,230 --> 00:13:30,890 Exception. 317 00:13:30,890 --> 00:13:33,200 So if we'd caught these exceptions the 318 00:13:33,200 --> 00:13:35,360 other way round, we'd actually never see 319 00:13:35,360 --> 00:13:37,880 the message invalid URL - we'd just get IO 320 00:13:37,880 --> 00:13:39,950 exception reading data, which would make 321 00:13:39,950 --> 00:13:41,900 finding the cause of the problem a lot 322 00:13:41,900 --> 00:13:43,940 harder. Alright, so let's just close 323 00:13:43,940 --> 00:13:45,500 that file down again - that class file down 324 00:13:45,500 --> 00:13:47,600 again. Go back to where we were. Mow 325 00:13:47,600 --> 00:13:49,700 that's actually even more important, if 326 00:13:49,700 --> 00:13:51,740 you add another catch block to deal with 327 00:13:51,740 --> 00:13:54,200 all other exceptions. So I'm gonna come down 328 00:13:54,200 --> 00:13:56,600 here and do that. Add another catch on 329 00:13:56,600 --> 00:14:01,250 the next line, e : Exception, another 330 00:14:01,250 --> 00:14:02,690 code block again. It's gonna be Log.e 331 00:14:02,690 --> 00:14:06,290 parentheses TAG comma space double 332 00:14:06,290 --> 00:14:10,430 quote, Unknown error : 333 00:14:10,430 --> 00:14:12,500 dollar sign, left and curly braces, 334 00:14:12,500 --> 00:14:16,280 e.message. So if we put this last 335 00:14:16,280 --> 00:14:18,530 catch block first, then that would be the 336 00:14:18,530 --> 00:14:20,720 only one executed because all of our 337 00:14:20,720 --> 00:14:22,460 other exceptions are, ultimately, a 338 00:14:22,460 --> 00:14:25,880 subclass of exception. Alright, so let's 339 00:14:25,880 --> 00:14:28,190 end the video here now. In the next video, 340 00:14:28,190 --> 00:14:30,680 we'll start talking more about the Http 341 00:14:30,680 --> 00:14:32,660 connection, and how the server sends back 342 00:14:32,660 --> 00:14:35,090 a response code. So I'll see you in the next 343 00:14:35,090 --> 00:14:37,300 video.