1
00:00:04,600 --> 00:00:08,200
Welcome back. In the last video we discussed bugs in android

2
00:00:08,200 --> 00:00:09,560
and in our own code.

3
00:00:10,260 --> 00:00:12,760
There certainly have been bugs in the android framework,

4
00:00:13,160 --> 00:00:15,660
and sometimes Google is unable to fix them.

5
00:00:16,360 --> 00:00:20,260
The problem that google has is that they're not responsible for updating android

6
00:00:20,260 --> 00:00:21,160
on devices.

7
00:00:22,150 --> 00:00:24,450
They can update the Google Play side of things,

8
00:00:24,850 --> 00:00:27,850
and they can provide us with updates to the support libraries,

9
00:00:28,510 --> 00:00:32,310
but the individual manufacturers are responsible for the android version

10
00:00:32,310 --> 00:00:33,410
on their devices.

11
00:00:35,910 --> 00:00:38,510
If Google wants to maintain backwards compatibility,

12
00:00:38,870 --> 00:00:41,470
they have to be very careful about what they change.

13
00:00:42,020 --> 00:00:45,920
They may fix a bug in android, and break a whole lot of apps as a result.

14
00:00:46,720 --> 00:00:49,320
That means that sometimes bugs don't get fixed.

15
00:00:50,420 --> 00:00:52,420
Our app contains one such bug.

16
00:00:53,220 --> 00:00:55,580
It's been fixed in recent android versions,

17
00:00:55,980 --> 00:00:59,080
but there's still a problem on Jelly Bean and KitKat.

18
00:01:00,180 --> 00:01:04,580
The bug is in the DatePicker dialog, so let's start by seeing the problem.

19
00:01:05,480 --> 00:01:08,680
I'll run the app on an API 17 emulator.

20
00:01:15,180 --> 00:01:16,680
The reports work fine,

21
00:01:17,340 --> 00:01:19,340
and we've got a load of data displayed.

22
00:01:19,940 --> 00:01:22,940
To see the bug in action, open the logcat.

23
00:01:25,940 --> 00:01:29,540
To make it easier, enter date to filter,

24
00:01:30,040 --> 00:01:31,040
and then clear.

25
00:01:33,040 --> 00:01:35,240
When I use the calendar to pick a date,

26
00:01:35,640 --> 00:01:38,000
notice that we get a DatePicker style

27
00:01:39,700 --> 00:01:42,200
that will be familiar to users of Jelly Bean.

28
00:01:42,970 --> 00:01:45,270
It doesn't look as good as the more modern one,

29
00:01:45,570 --> 00:01:48,770
but it's functional and users won't be surprised to see it.

30
00:01:49,430 --> 00:01:51,130
The DatePicker does have a quirk.

31
00:01:51,830 --> 00:01:53,830
If you choose the month first,

32
00:01:54,330 --> 00:01:58,320
then wind the day past the end of the month past 30 or 31,

33
00:01:58,820 --> 00:02:00,820
then the month also increases.

34
00:02:01,320 --> 00:02:04,820
If you go the other way, back to 31 from 1,

35
00:02:05,370 --> 00:02:06,970
the month also goes backwards.

36
00:02:07,630 --> 00:02:10,229
That's not a bug. It's intended behavior.

37
00:02:10,630 --> 00:02:14,630
It's just a bit annoying if you choose the month before the day of the month.

38
00:02:15,230 --> 00:02:17,530
The modern date pick is a lot easier to use.

39
00:02:18,330 --> 00:02:22,690
Okay. I'll change the date to the 10th of May then tap done.

40
00:02:37,890 --> 00:02:41,890
We're now displaying records from the 5th to the 11th of May.

41
00:02:42,390 --> 00:02:46,590
That's fine. The emulator is new and is set to the USA locale,

42
00:02:46,590 --> 00:02:48,890
that means the week starts on a Sunday.

43
00:02:50,090 --> 00:02:54,990
The logcat entries are interesting, onDateSet's been called twice.

44
00:02:56,490 --> 00:03:00,890
Luckily we checked that the date had really changed in our onDateSet function.

45
00:03:01,290 --> 00:03:03,890
So the app doesn't re-query the database.

46
00:03:04,550 --> 00:03:08,350
Even if we hadn't, OnDateSet being called twice

47
00:03:08,350 --> 00:03:10,750
isn't the end of the world in our particular case.

48
00:03:11,300 --> 00:03:13,900
We're using the date to query a local database,

49
00:03:14,400 --> 00:03:15,900
and we're not performing an update.

50
00:03:16,800 --> 00:03:20,600
You can imagine situations where calling OnDateSet twice

51
00:03:20,600 --> 00:03:22,600
would be far from ideal though.

52
00:03:23,200 --> 00:03:25,560
If we were obtaining data from the internet,

53
00:03:25,560 --> 00:03:28,860
we could cause unnecessary data charges for our users,

54
00:03:29,460 --> 00:03:31,460
and it would also be slow.

55
00:03:32,260 --> 00:03:34,260
If we were updating the database,

56
00:03:34,460 --> 00:03:36,820
this could cause all sorts of problems.

57
00:03:37,420 --> 00:03:38,520
So this isn't good.

58
00:03:39,720 --> 00:03:41,920
In fact, it's slightly worse than that.

59
00:03:42,520 --> 00:03:46,520
What happens if I select a new date then change my mind.

60
00:03:47,320 --> 00:03:48,220
Let's have a look.

61
00:03:48,820 --> 00:03:51,920
I'll enter the comment cancelling date into the logcat

62
00:03:51,920 --> 00:03:53,920
to make it easier to see what's going on.

63
00:04:04,620 --> 00:04:08,620
It's been a while since we've entered the comment into the logcat. As a reminder,

64
00:04:08,620 --> 00:04:11,420
you just click at the end of the logcat entries

65
00:04:11,420 --> 00:04:15,020
and press enter to start a new line, type your text,

66
00:04:15,020 --> 00:04:16,220
then press enter again.

67
00:04:17,550 --> 00:04:21,250
All right. I'll tap the calendar icon in the app again

68
00:04:21,250 --> 00:04:23,750
and leave the month and day the same

69
00:04:23,750 --> 00:04:25,950
but choose 2020 for the year.

70
00:04:27,050 --> 00:04:28,850
Instead of tapping done,

71
00:04:28,850 --> 00:04:31,850
I'll use the back button to cancel a DatePicker.

72
00:04:35,350 --> 00:04:37,850
All our data seems to have vanished.

73
00:04:38,450 --> 00:04:41,450
We can see what's happened quite easily in the logcat.

74
00:04:41,650 --> 00:04:46,050
OnDateSet still got called with the date we tried to cancel.

75
00:04:46,820 --> 00:04:51,220
The logcat shows the date, and we got a new cursor with no records.

76
00:04:52,210 --> 00:04:54,710
Our users will have no idea what's happened.

77
00:04:55,410 --> 00:04:59,610
The bug in the DatePicker dialogue has gone from a minor inconvenience

78
00:04:59,910 --> 00:05:03,210
to a problem for our users, so we need to fix it.

79
00:05:04,210 --> 00:05:05,510
The fix is quite easy

80
00:05:05,760 --> 00:05:09,320
and googling for DatePicker calls OnDateSet twice

81
00:05:09,320 --> 00:05:11,320
produces lots of answers.

82
00:05:12,120 --> 00:05:14,320
The bug's been around for a long time.

83
00:05:14,980 --> 00:05:18,340
The solution, I like, can be found in google's issues tracker.

84
00:05:19,000 --> 00:05:21,200
The issue can be found here.

85
00:05:30,100 --> 00:05:32,900
Comment 18 contains the fix.

86
00:05:33,670 --> 00:05:37,370
We create our own subclass of DatePicker dialog

87
00:05:37,670 --> 00:05:40,570
but don't call the super OnStop method.

88
00:05:40,970 --> 00:05:44,330
It's DatePicker dialogue's OnStop method that has the bugs.

89
00:05:44,690 --> 00:05:48,390
And Wojtek Jarosz has done all the hard work for us.

90
00:05:48,390 --> 00:05:50,690
It's worth reading his comments carefully

91
00:05:50,990 --> 00:05:54,980
because there are implications when using an action bar with this solution.

92
00:05:55,640 --> 00:06:00,000
We're not using an action bar, we're using the app bar to host the toolbar

93
00:06:00,000 --> 00:06:02,600
so it's fine for us to use this solution here.

94
00:06:03,590 --> 00:06:07,490
Back in android studio create new

95
00:06:07,490 --> 00:06:08,490
java class.

96
00:06:11,150 --> 00:06:12,650
Yes, you heard right.

97
00:06:13,010 --> 00:06:15,110
The android framework's written in java,

98
00:06:15,110 --> 00:06:17,710
and this is a fix for a java class.

99
00:06:18,510 --> 00:06:22,170
There's no problem mixing java and Kotlin code in your projects.

100
00:06:22,170 --> 00:06:24,270
In fact, we've been doing it all along

101
00:06:24,270 --> 00:06:27,970
because all the libraries that our apps use have been written in java.

102
00:06:28,570 --> 00:06:32,370
I'll call the class UnbuggyDatePickerDialog,

103
00:06:36,070 --> 00:06:37,670
and I'll paste in the code.

104
00:06:38,370 --> 00:06:42,270
I want to include credits to Wojtek and a link to this issue.

105
00:06:42,270 --> 00:06:44,770
And I'm sure you won't want to watch me type it all.

106
00:06:54,170 --> 00:06:55,770
The class doesn't do much.

107
00:06:55,770 --> 00:06:58,370
It just overrides OnStop

108
00:06:58,370 --> 00:07:00,570
and fails to call the super method.

109
00:07:01,130 --> 00:07:04,730
That means the OnStop method of the original DatePicker dialog,

110
00:07:04,730 --> 00:07:08,030
which is the part that contains the bug doesn't get called.

111
00:07:08,800 --> 00:07:11,400
Before we change our code to use this fixed class,

112
00:07:11,650 --> 00:07:13,650
have a look at the imports at the top.

113
00:07:14,050 --> 00:07:17,950
DatePicker dialog is in the android.app package.

114
00:07:18,450 --> 00:07:21,050
In other words, it's part of the android framework.

115
00:07:21,950 --> 00:07:26,500
If Google had included DatePicker dialogue in the support libraries, instead

116
00:07:26,900 --> 00:07:29,560
they could have provided a fixed version of the libraries.

117
00:07:29,560 --> 00:07:31,860
That may help to explain one reason

118
00:07:31,860 --> 00:07:35,160
why they recommend using the support libraries wherever possible,

119
00:07:35,710 --> 00:07:38,810
and also why fragment and dialogue fragment

120
00:07:38,810 --> 00:07:40,810
have been deprecated in the framework.

121
00:07:41,310 --> 00:07:44,970
Okay. We need to change the OncReateDialog method

122
00:07:44,970 --> 00:07:48,270
in our DatePicker fragment to use this new class.

123
00:07:59,970 --> 00:08:00,870
That's it.

124
00:08:01,370 --> 00:08:05,470
Now we'll be calling the UnbuggyDatePicker and our code should work.

125
00:08:06,130 --> 00:08:09,530
Run the app on the API 17 emulator again,

126
00:08:10,030 --> 00:08:13,030
and clear the logcat before tapping the report icon.

127
00:08:22,020 --> 00:08:23,900
I'll repeat the previous test.

128
00:08:24,690 --> 00:08:29,090
First, use the calendar icon to choose the 10th of May and tap done.

129
00:08:38,090 --> 00:08:39,289
That looks better

130
00:08:39,690 --> 00:08:41,690
OnDateSet was only called once.

131
00:08:42,490 --> 00:08:45,790
We can see the data for the 5th to the 11th of May,

132
00:08:46,290 --> 00:08:48,650
which again is correct for the USA locale.

133
00:08:49,250 --> 00:08:50,250
How about cancelling?

134
00:08:50,910 --> 00:08:53,790
Once again, I'll change the year to 2020,

135
00:08:53,790 --> 00:08:55,290
and then use the back button.

136
00:08:56,790 --> 00:09:00,090
That works fine. There's nothing in the logcat,

137
00:09:00,090 --> 00:09:02,090
and we still have the data in our report.

138
00:09:02,750 --> 00:09:05,750
If your app is targeting API 21 or above,

139
00:09:05,750 --> 00:09:08,350
you don't need to use this unbuggy class.

140
00:09:08,950 --> 00:09:12,950
The DatePicker in API 21 and above doesn't have the bug anymore.

141
00:09:13,310 --> 00:09:17,410
Now you also have a reliable DatePicker for the earlier versions,

142
00:09:17,410 --> 00:09:21,510
and we've specified API 17 as our minimum SDK level.

143
00:09:22,210 --> 00:09:23,810
Our app's nearly finished.

144
00:09:24,410 --> 00:09:27,010
We still need to delete old timings data,

145
00:09:27,010 --> 00:09:31,510
and we're not yet using the settings that we've written the settings dialog class for.

146
00:09:32,110 --> 00:09:34,310
I'll complete the report menu options,

147
00:09:34,310 --> 00:09:38,310
adding the functionality to delete all records in the next video.

148
00:09:38,310 --> 00:09:39,310
See you there.

