Reputation: 5074
The date picker I used for my activity crashed on KitKat but works on every other newer operating systems. This is the exception I get on old devices:
java.lang.IllegalArgumentException: fromDate: Mon Apr 10 07:59:25 EDT 2017 does not precede toDate: Mon Apr 10 07:59:25 EDT 2017
Code block stack trace is pointing at:
private void showDatePicker(){
DatePickerDialog datePickerDialog = new DatePickerDialog(
getActivity(), this, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
//this is where the crash happens
datePickerDialog.getDatePicker().setMinDate(new Date().getTime());
datePickerDialog.show();
}
Please let me know if the information regarding the question is sufficient. Any fix for this?
Upvotes: 1
Views: 1226
Reputation: 317
To solve this issue create a timestamp for minDate just before instantiation of DatePickerDialog:
private void showDatePicker(){
long now = System.currentTimeMillis();
DatePickerDialog datePickerDialog = new DatePickerDialog(
getActivity(), this, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
datePickerDialog.getDatePicker().setMinDate(now);
datePickerDialog.show();
}
This crash happens due to a bug in CalendarView for pre-API21, and for calendarViewMode == MODE_HOLO
for API21.
Although setMinDate
contains a correction highlighted with a comment:
public void setMinDate(long minDate) {
...
mMinDate.setTimeInMillis(minDate);
// make sure the current date is not earlier than
// the new min date since the latter is used for
// calculating the indices in the adapter thus
// avoiding out of bounds error
Calendar date = mAdapter.mSelectedDate;
if (date.before(mMinDate)) {
mAdapter.setSelectedDay(mMinDate);
}
// reinitialize the adapter since its range depends on min date
mAdapter.init();
The check in setSelectedDay
compares mMinDate
and mSelectedDate
only with date accuracy:
public void setSelectedDay(Calendar selectedDay) {
if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDate.get(Calendar.DAY_OF_YEAR)
&& selectedDay.get(Calendar.YEAR) == mSelectedDate.get(Calendar.YEAR)) {
return;
}
mSelectedDate
and mMinDate
are points into the same day, so that mSelectedDate
will remain unchanged (i.e. in a wrong state mSelectedDate < mMinDate
).
Then the control flow will run up to mAdapter.init
, and then into getWeeksSinceMinDate
. In this function a comparison of mMinDate
and mSelectedDate
will be performed with millisecond accuracy:
private int getWeeksSinceMinDate(Calendar date) {
if (date.before(mMinDate)) {
throw new IllegalArgumentException("fromDate: " + mMinDate.getTime()
+ " does not precede toDate: " + date.getTime());
}
And because mSelectedDate
was initialized in few milliseconds before mMinDate
the crash will occur.
In a newer implementation this code was rewritten, so this issue is missing for API21+.
Upvotes: 0
Reputation: 4182
I fix this issue applying a delay:
private void showDatePicker(){
DatePickerDialog datePickerDialog = new DatePickerDialog(
getActivity(), this, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
//this is where the crash happens
datePickerDialog.getDatePicker().setMinDate(new Date().getTime() - 10000);
datePickerDialog.show();
}
Upvotes: 2