1
00:00:05,520 --> 00:00:08,910
OK so we're gonna start with the basics with this application,

2
00:00:08,910 --> 00:00:14,220
and the first thing we need to do before parsing the json data is to download it.

3
00:00:14,220 --> 00:00:20,370
So I'm going to leave the user interface until later. To start with we'll download the data using an asynchronous

4
00:00:20,370 --> 00:00:24,930
task, which is similar to what we did in the top 10 downloader app.

5
00:00:24,930 --> 00:00:32,390
So let's start now, and we're going to come over here to our package name, we'll right click over here,

6
00:00:32,390 --> 00:00:42,210
select new, Kotlin Class, and we're going to call this one GetRawData. To save a bit of time I'm going to choose

7
00:00:42,210 --> 00:00:50,390
Class there in the drop down. We'll close down the log cat for now. So to start with we're going to extend the async

8
00:00:50,390 --> 00:00:56,270
class, so that GetRawData can perform it's downloading on a separate background thread.

9
00:00:56,270 --> 00:00:59,900
And again this is exactly the same as we did in the top 10 downloader app,

10
00:00:59,900 --> 00:01:01,550
and once again we're providing a string,

11
00:01:01,550 --> 00:01:05,540
or we're going to provide a string which will be the URL to download from,

12
00:01:05,540 --> 00:01:08,020
and we'll get back a string containing our data.

13
00:01:08,020 --> 00:01:16,080
So let's go ahead and do that. So I'm going to put a space colon space, and it's going to be an async task, and we want a

14
00:01:16,080 --> 00:01:19,250
diamond operator so left and right, less than and greater than

15
00:01:19,250 --> 00:01:26,420
signs there, then we're going to do a string, void, string, again you've seen that in the top 10 downloaders app, then

16
00:01:26,420 --> 00:01:31,610
add parentheses on the end there. Now we've got an error, but before implementing the required methods,

17
00:01:31,610 --> 00:01:36,590
I'm going to create an enum to hold a list of download statuses.

18
00:01:36,590 --> 00:01:42,640
Now we saw this also in the previous app, when the Google YouTube player, to find an enum to hold the result

19
00:01:42,640 --> 00:01:47,030
codes that we could get back if anything went wrong when playing the videos.

20
00:01:47,030 --> 00:01:53,000
So here we want a way to tell the calling processes whether the download succeeded or what the state

21
00:01:53,000 --> 00:01:56,270
of the download is. So I'm going to use an enum for that.

22
00:01:56,270 --> 00:02:01,130
Now I have covered enums in the Kotlin tutorial section too, so refer to that section if you're

23
00:02:01,130 --> 00:02:05,840
not sure what enums are. So I'll put this definition above the class here,

24
00:02:05,840 --> 00:02:15,510
the class definition, so that's enum, class, then DownloadStatus,

25
00:02:15,510 --> 00:02:20,540
then we put our left and right curly brace there. Then within there we put

26
00:02:20,540 --> 00:02:26,240
OK comma space, IDLE comma space NOT_INITIALIZED,

27
00:02:26,240 --> 00:02:37,740
comma space FAILED_OR_EMPTY comma space PERMISSIONS_ERROR comma space,

28
00:02:37,740 --> 00:02:42,590
and the last one, ERROR. So the download status enums got

29
00:02:42,590 --> 00:02:47,150
all the states that this class is going to be in, in other words all the possibilities.

30
00:02:47,150 --> 00:02:50,040
So OK means that we've got some valid data.

31
00:02:50,040 --> 00:02:55,310
IDLE means that it's not processing anything, NOT-INITIALIZED means that we haven't got a valid URL

32
00:02:55,310 --> 00:02:56,330
to download.

33
00:02:56,330 --> 00:03:01,010
It's an error condition, because we won't be able to set it until a download's been attempted. Now 

34
00:03:01,010 --> 00:03:06,920
FAILED_OR_EMPTY means that we either failed to download anything or the data came back empty.

35
00:03:06,920 --> 00:03:11,330
And the last two errors there, PERMISSIONS_ERROR and ERROR, indicate errors either with the permissions

36
00:03:11,330 --> 00:03:14,430
or with some other error that we haven't identified.

37
00:03:14,430 --> 00:03:19,340
Now you can obviously go into more detail and create more statuses if you really wanted to, but that

38
00:03:19,340 --> 00:03:21,290
will work for our purposes here.

39
00:03:21,290 --> 00:03:25,190
So the next thing I want to do is add a log tag for our debuggings. So let's do that, this time within the

40
00:03:25,190 --> 00:03:34,700
class, private val TAG equals double quotes GetRawData.

41
00:03:34,700 --> 00:03:45,680
Then on the next line we're going to do a private var downloadStatus equals DownloadStatus.IDLE, and you

42
00:03:45,680 --> 00:03:51,800
can see that I've also declared a variable to hold the download status, and we've initialized that to IDLE 

43
00:03:51,800 --> 00:03:57,380
because our class instance won't be doing anything when it's first created. Now we've got an error because

44
00:03:57,380 --> 00:04:01,550
we haven't implemented the required methods for an async task.

45
00:04:01,550 --> 00:04:07,190
So let's actually sort that out. Now we need to override the required async task functions,

46
00:04:07,190 --> 00:04:13,250
so we can do a command n, making sure you're within the class definition, or alt insert on a PC, and then

47
00:04:13,250 --> 00:04:18,890
select override methods. Alternatively command

48
00:04:18,890 --> 00:04:22,630
O on a Mac or control O, would get straight to here as well.

49
00:04:22,630 --> 00:04:27,290
So the ones we want here are doInBackground and we also want onPostExecute,

50
00:04:27,290 --> 00:04:32,190
so I'm going to select both of those, then click OK.

51
00:04:32,190 --> 00:04:36,500
The error's now disappeared as you can see. Now the doInBackground

52
00:04:36,500 --> 00:04:42,410
function's going to be pretty similar to the code in the top 10 downloader. There are minor differences, because

53
00:04:42,410 --> 00:04:47,810
we're going to set the download status, and I also want to introduce a catch block to trap any errors, but we'll

54
00:04:47,810 --> 00:04:49,070
come to that in a minute.

55
00:04:49,070 --> 00:04:59,780
So let's start some coding there, we'll delete TODO, and we're going to put if parentheses params, zero

56
00:04:59,780 --> 00:05:01,400
in square brackets,

57
00:05:01,400 --> 00:05:10,170
is equal to null, open a code block and there's going to be download status is equal to download status dot NOT

58
00:05:10,170 --> 00:05:17,420
INITIALIZED, return, then in double quotes No URL specified.

59
00:05:17,420 --> 00:05:21,940
So this first bit of code that I've added just checks that the URL we get isn't null.

60
00:05:21,940 --> 00:05:25,330
Now the function receives an array of strings or a string

61
00:05:25,330 --> 00:05:28,170
array, if you're more used to thinking of it that way.

62
00:05:28,170 --> 00:05:35,470
What's interesting here is the nullable type string question mark, up here.

63
00:05:35,470 --> 00:05:41,530
So this means that the individual elements of params can be null. Params itself however can't be null,

64
00:05:41,530 --> 00:05:46,090
and we can actually get Android Studio to verify that by changing our

65
00:05:46,090 --> 00:05:48,490
null check. So I could change that there to

66
00:05:48,490 --> 00:05:55,540
putting, if params is equal to null, and when I do that, if I hover over that, you can see 'Condition params is equal

67
00:05:55,540 --> 00:06:01,450
to null is always false'. So we can be sure we definitely get a non null array,

68
00:06:01,450 --> 00:06:04,660
but the individual elements it contains might be null.

69
00:06:04,660 --> 00:06:05,530
So that's what the type,

70
00:06:05,530 --> 00:06:10,410
that's why rather, the type is string question mark, and why we start off with a null check.

71
00:06:10,410 --> 00:06:15,090
So pay really careful attention to the code that Android Studio generates, and

72
00:06:15,090 --> 00:06:17,090
be aware that it can change.

73
00:06:17,090 --> 00:06:22,300
Google change things frequently, and if you generate the same function a week later, you might well get

74
00:06:22,300 --> 00:06:24,100
slightly different code.

75
00:06:24,100 --> 00:06:29,110
In fact if you review the top 10 downloader app, the parameter name was different when it generated the

76
00:06:29,110 --> 00:06:29,800
same function

77
00:06:29,800 --> 00:06:35,350
back then. Alright so I'm going to put that line back, I'm going to undo that, and that warning goes away,

78
00:06:35,350 --> 00:06:38,800
and not only that, it's now doing something useful.

79
00:06:38,800 --> 00:06:43,840
Alright so we checked that we've been given a URL and the function was called. We don't know if it's

80
00:06:43,840 --> 00:06:47,830
a valid URL yet, but we can at least check that we've got something.

81
00:06:47,830 --> 00:06:53,490
If not, if the first element of params is null, then we set the standard to NOT_INITIALIZED,

82
00:06:53,490 --> 00:06:56,650
return the text "No url specified".

83
00:06:56,650 --> 00:07:02,470
So let's now enclose the rest of the code and this function inside a try block, so that we can catch any exceptions

84
00:07:02,470 --> 00:07:04,990
that are raised while downloading.

85
00:07:04,990 --> 00:07:17,680
So I'll do that down here, try, then within that I'm going to put downloadStatus equals DownloadStatus.OK, return

86
00:07:17,680 --> 00:07:31,370
URL in uppercase, parentheses, params 0 in square brackets, closing parentheses dot readText. We

87
00:07:31,370 --> 00:07:38,960
need to accept that import, and again that code's very similar to the top 10 downloader function,

88
00:07:38,960 --> 00:07:44,510
once we reduced it to a single line. Now the import for URL doesn't always get added automatically

89
00:07:44,510 --> 00:07:46,250
and you saw that it didn't for me.

90
00:07:46,250 --> 00:07:52,730
If it doesn't, you can just hold down alt enter, and choose Java dot net dot url, and you see again that I did that.

91
00:07:52,730 --> 00:07:56,600
Now there should only be one value passed in the params array.

92
00:07:56,600 --> 00:08:03,290
So we pick up the first one in params zero, this code here, to make sure that we're using elements zero.

93
00:08:03,290 --> 00:08:10,450
As I said, this may not be a valid URL but we're going to rely on the catch block to detect an invalid URL.

94
00:08:10,450 --> 00:08:16,940
Now we set the status to OK using the constant defined in our enum, which is a common approach.

95
00:08:16,940 --> 00:08:20,610
So in other words we assume everything's going to work fine, but then change the status,

96
00:08:20,610 --> 00:08:21,590
even exceptions,

97
00:08:21,590 --> 00:08:29,150
raised. Now the catch block I'm about to add's the same as we originally had in the top 10 downloader.

98
00:08:29,150 --> 00:08:38,659
So let's go ahead and do that and actually add it, so we're going to do a catch, parentheses e colon exception, then a 

99
00:08:38,659 --> 00:08:45,200
code block, and then we're going to put val

100
00:08:45,200 --> 00:08:49,880
errorMessage equals when, then in parentheses e.

101
00:08:49,880 --> 00:08:55,060
Then open a code block, then within that we're going to put is Malformed

102
00:08:55,060 --> 00:09:04,000
URLException, end of that we'll have arrow token and then a code block, then we're going to put downloadStatus is equal

103
00:09:04,000 --> 00:09:17,760
to DownloadStatus.NOT_INITIALIZED, then in double quotes on the next line, doInBackground colon Invalid 

104
00:09:17,760 --> 00:09:26,780
URL space dollar sign, left and right curly braces, e.message. And what we might do to save a bit of time

105
00:09:26,780 --> 00:09:30,380
here is we might copy and paste some of these.

106
00:09:30,380 --> 00:09:34,020
So I'm going to put is Malformed exception there. I'm going to copy that,

107
00:09:34,020 --> 00:09:36,990
because we've got a couple more we want to put, we want to try.

108
00:09:36,990 --> 00:09:46,280
Next one is going to be IO exception so let's do that one, so is IOException, and

109
00:09:46,280 --> 00:10:00,780
for that one we're going to put FAILED_OR_EMPTY, the status will be failed or empty, and we'll put for the text "IO Exception

110
00:10:00,780 --> 00:10:09,630
reading data" colon and then we'll put the e.message again, there again. The next one we want is security exceptions,

111
00:10:09,630 --> 00:10:11,790
so let's paste that as well.

112
00:10:11,790 --> 00:10:24,120
So is SecurityException, and for that one we're going to put permissions error, dot PERMISSIONS_ERROR, and for

113
00:10:24,120 --> 00:10:37,490
the actual text let's go with "Security exception Needs permission?", and

114
00:10:37,490 --> 00:10:44,150
and we'll leave that e.message in there for the specific error. Then we also need to do down here, after the last is, we need

115
00:10:44,150 --> 00:10:51,980
to add an else, so else code block, sorry arrow token and then block block, and the else is going to be downloadStatus is

116
00:10:51,980 --> 00:10:54,760
equal to DownloadStatus.ERROR.

117
00:10:54,760 --> 00:10:59,780
So that's that generic error that we haven't been able to identify actually what happened, and the

118
00:10:59,780 --> 00:11:10,490
text we're returning is "Unknown error" colon and then space dollar, left and right curly braces, e.message.

119
00:11:10,490 --> 00:11:15,400
Then moving down, down here now, outside of the val error message,

120
00:11:15,400 --> 00:11:25,520
we have a Log.e this time, because it is actually an error, Log.e TAG, error message, then we're going

121
00:11:25,520 --> 00:11:30,160
to return errorMessage.

122
00:11:30,160 --> 00:11:34,420
Alright so that's our function now and our try catch block.

123
00:11:34,420 --> 00:11:40,140
So basically what we're doing is we're checking for a malformed URL, and then any IO exceptions that

124
00:11:40,140 --> 00:11:43,450
actually are thrown, that's these two here.

125
00:11:43,450 --> 00:11:49,750
And there's also a check for security, or at a security exception, if we forget to request permission to access

126
00:11:49,750 --> 00:11:54,160
the Internet. Now if there was an exception, we'll get to the code after the catch blocks

127
00:11:54,160 --> 00:11:59,500
when we return the error message. So that's our doInBackground function completed.

128
00:11:59,500 --> 00:12:04,030
We made a few changes and some minor improvements, but it's really basically the same code as we

129
00:12:04,030 --> 00:12:06,400
used in the top 10 downloader.

130
00:12:06,400 --> 00:12:11,680
So I'll stop the video here, and in the next one we'll create the code for on post execute.

131
00:12:11,680 --> 00:12:12,660
So see you in the next video.

