Welcome back. In the last video we discussed bugs in android
and in our own code.
There certainly have been bugs in the android framework,
and sometimes Google is unable to fix them.
The problem that google has is that they're not responsible for updating android
on devices.
They can update the Google Play side of things,
and they can provide us with updates to the support libraries,
but the individual manufacturers are responsible for the android version
on their devices.
If Google wants to maintain backwards compatibility,
they have to be very careful about what they change.
They may fix a bug in android, and break a whole lot of apps as a result.
That means that sometimes bugs don't get fixed.
Our app contains one such bug.
It's been fixed in recent android versions,
but there's still a problem on Jelly Bean and KitKat.
The bug is in the DatePicker dialog, so let's start by seeing the problem.
I'll run the app on an API 17 emulator.
The reports work fine,
and we've got a load of data displayed.
To see the bug in action, open the logcat.
To make it easier, enter date to filter,
and then clear.
When I use the calendar to pick a date,
notice that we get a DatePicker style
that will be familiar to users of Jelly Bean.
It doesn't look as good as the more modern one,
but it's functional and users won't be surprised to see it.
The DatePicker does have a quirk.
If you choose the month first,
then wind the day past the end of the month past 30 or 31,
then the month also increases.
If you go the other way, back to 31 from 1,
the month also goes backwards.
That's not a bug. It's intended behavior.
It's just a bit annoying if you choose the month before the day of the month.
The modern date pick is a lot easier to use.
Okay. I'll change the date to the 10th of May then tap done.
We're now displaying records from the 5th to the 11th of May.
That's fine. The emulator is new and is set to the USA locale,
that means the week starts on a Sunday.
The logcat entries are interesting, onDateSet's been called twice.
Luckily we checked that the date had really changed in our onDateSet function.
So the app doesn't re-query the database.
Even if we hadn't, OnDateSet being called twice
isn't the end of the world in our particular case.
We're using the date to query a local database,
and we're not performing an update.
You can imagine situations where calling OnDateSet twice
would be far from ideal though.
If we were obtaining data from the internet,
we could cause unnecessary data charges for our users,
and it would also be slow.
If we were updating the database,
this could cause all sorts of problems.
So this isn't good.
In fact, it's slightly worse than that.
What happens if I select a new date then change my mind.
Let's have a look.
I'll enter the comment cancelling date into the logcat
to make it easier to see what's going on.
It's been a while since we've entered the comment into the logcat. As a reminder,
you just click at the end of the logcat entries
and press enter to start a new line, type your text,
then press enter again.
All right. I'll tap the calendar icon in the app again
and leave the month and day the same
but choose 2020 for the year.
Instead of tapping done,
I'll use the back button to cancel a DatePicker.
All our data seems to have vanished.
We can see what's happened quite easily in the logcat.
OnDateSet still got called with the date we tried to cancel.
The logcat shows the date, and we got a new cursor with no records.
Our users will have no idea what's happened.
The bug in the DatePicker dialogue has gone from a minor inconvenience
to a problem for our users, so we need to fix it.
The fix is quite easy
and googling for DatePicker calls OnDateSet twice
produces lots of answers.
The bug's been around for a long time.
The solution, I like, can be found in google's issues tracker.
The issue can be found here.
Comment 18 contains the fix.
We create our own subclass of DatePicker dialog
but don't call the super OnStop method.
It's DatePicker dialogue's OnStop method that has the bugs.
And Wojtek Jarosz has done all the hard work for us.
It's worth reading his comments carefully
because there are implications when using an action bar with this solution.
We're not using an action bar, we're using the app bar to host the toolbar
so it's fine for us to use this solution here.
Back in android studio create new
java class.
Yes, you heard right.
The android framework's written in java,
and this is a fix for a java class.
There's no problem mixing java and Kotlin code in your projects.
In fact, we've been doing it all along
because all the libraries that our apps use have been written in java.
I'll call the class UnbuggyDatePickerDialog,
and I'll paste in the code.
I want to include credits to Wojtek and a link to this issue.
And I'm sure you won't want to watch me type it all.
The class doesn't do much.
It just overrides OnStop
and fails to call the super method.
That means the OnStop method of the original DatePicker dialog,
which is the part that contains the bug doesn't get called.
Before we change our code to use this fixed class,
have a look at the imports at the top.
DatePicker dialog is in the android.app package.
In other words, it's part of the android framework.
If Google had included DatePicker dialogue in the support libraries, instead
they could have provided a fixed version of the libraries.
That may help to explain one reason
why they recommend using the support libraries wherever possible,
and also why fragment and dialogue fragment
have been deprecated in the framework.
Okay. We need to change the OncReateDialog method
in our DatePicker fragment to use this new class.
That's it.
Now we'll be calling the UnbuggyDatePicker and our code should work.
Run the app on the API 17 emulator again,
and clear the logcat before tapping the report icon.
I'll repeat the previous test.
First, use the calendar icon to choose the 10th of May and tap done.
That looks better
OnDateSet was only called once.
We can see the data for the 5th to the 11th of May,
which again is correct for the USA locale.
How about cancelling?
Once again, I'll change the year to 2020,
and then use the back button.
That works fine. There's nothing in the logcat,
and we still have the data in our report.
If your app is targeting API 21 or above,
you don't need to use this unbuggy class.
The DatePicker in API 21 and above doesn't have the bug anymore.
Now you also have a reliable DatePicker for the earlier versions,
and we've specified API 17 as our minimum SDK level.
Our app's nearly finished.
We still need to delete old timings data,
and we're not yet using the settings that we've written the settings dialog class for.
I'll complete the report menu options,
adding the functionality to delete all records in the next video.
See you there.