Edit : I checked that the issue only appears when the phone is set with "French" language.
I'm currently building my own app and I have an issue when using the DatePicker widget on my phone (debug mode phone : Samsung S5).
The error gather is : java.util.IllegalFormatConversionException
I add more details about the issue gathered in logcat:
02-20 10:37:18.255 13029-13029/avappmobile.mytasks E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: avappmobile.mytasks, PID: 13029
java.util.IllegalFormatConversionException: %d can't format java.lang.String arguments
at java.util.Formatter.badArgumentType(Formatter.java:1489)
at java.util.Formatter.transformFromInteger(Formatter.java:1689)
at java.util.Formatter.transform(Formatter.java:1461)
at java.util.Formatter.doFormat(Formatter.java:1081)
at java.util.Formatter.format(Formatter.java:1042)
at java.util.Formatter.format(Formatter.java:1011)
at java.lang.String.format(String.java:1803)
at android.content.res.Resources.getString(Resources.java:1453)
at android.content.Context.getString(Context.java:397)
at android.widget.SimpleMonthView$MonthViewTouchHelper.getItemDescription(SimpleMonthView.java:684)
at android.widget.SimpleMonthView$MonthViewTouchHelper.onPopulateNodeForVirtualView(SimpleMonthView.java:628)
at com.android.internal.widget.ExploreByTouchHelper.createNodeForChild(ExploreByTouchHelper.java:377)
at com.android.internal.widget.ExploreByTouchHelper.createNode(ExploreByTouchHelper.java:316)
at com.android.internal.widget.ExploreByTouchHelper.access$100(ExploreByTouchHelper.java:50)
at com.android.internal.widget.ExploreByTouchHelper$ExploreByTouchNodeProvider.createAccessibilityNodeInfo(ExploreByTouchHelper.java:711)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfVirtualNode(AccessibilityInteractionController.java:1179)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1091)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchDescendantsOfRealNode(AccessibilityInteractionController.java:1087)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchAccessibilityNodeInfos(AccessibilityInteractionController.java:888)
at android.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread(AccessibilityInteractionController.java:155)
at android.view.AccessibilityInteractionController.access$400(AccessibilityInteractionController.java:53)
at android.view.AccessibilityInteractionController$PrivateHandler.handleMessage(AccessibilityInteractionController.java:1236)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5834)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
Here is my DialogFragment Code:
public class DatePFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
DatePicker dp;
OnDatePickedListener mCallback;
Integer mLayoutId = null;
// Interface definition
public interface OnDatePickedListener {
public void onDatePicked(int textId, int year, int month, int day);
}
// make sure the Activity implement the OnDatePickedListener
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (OnDatePickedListener)activity;
}
catch (final ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnDatePickedListener");
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState){
mCallback = (OnDatePickedListener)getActivity();
Calendar cal = Calendar.getInstance();
Bundle bundle = this.getArguments();
mLayoutId = bundle.getInt("layoutId");
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
View view = getActivity().getLayoutInflater().inflate(R.layout.datepfragment, null);
dp = (DatePicker) view.findViewById(R.id.datePicker);
// Create a new instance of DatePickerDialog and return it
return new DatePickerDialog(getActivity(),this,year, month, day);
}
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
if (mCallback != null) {
// Use the date chosen by the user.
mCallback.onDatePicked(mLayoutId, year, monthOfYear+1, dayOfMonth);
}
}
}
And here is the associated xml layout :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/txtDPTitle"
android:id="@+id/txtDPTitle"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginTop="35dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btnDPValidate"
android:id="@+id/btnDPValidate"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="35dp" />
<DatePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/datePicker"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="0dp"
android:datePickerMode="spinner"
android:calendarViewShown="false"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
The fact is I had two kind of issues (leading to the app crash anyway):
- When I enter my app and directly go to the DatePicker widget, the calendar is correctly displayed and as soon as I select a day (I say a day, because there's no problem changing the year for example), the app crashes.
- If I go on other function the click to display the DatePicker, it crashes directly.
I saw other threads like : DatePicker crash in samsung with android 5.0
In this thread I don't get enough information, since the given solution allows to display only the spinner view of the calendar and furthermore the spinner displayed is not centered and presented as mine (put directly at the top of the screen).
If you need further details please ask me.
Thanks. Alex.
Forget about the built-in date picker. IMHO switching the locale is not a solution, because I want to have the picker in the current locale. There's only one way to get rid of the crash: use a library that provides an independent implementation.
For a date picker fragment: https://github.com/flavienlaurent/datetimepicker
For a date picker widget: https://github.com/SingleCycleKing/CustomTimePicker (this is more a starting point than a ready-to-use-solution)
It's a Samsung bug in their Lollipop UI implementation. It affects Galaxy S4, S5, Note 3 and probably more devices. For us it occurs on de_DE and de_AT languages, but it appears to be an issue that affects multiple languages.
I fixed it by forcing Samsung devices to use the Holo theme for the date picker. In our DatePickerFragment:
Thanks to Samsung, their users will not get the nice material-designed date picker.
I observed one minor problem with @mreichelt's solution. The dialog was rendered without the title showing the currently selected date (including the day of the week). Explicitly setting the title, and immediately setting the date again solved that problem for me.
Based on mreichelts answer I created a SupportDatePickerDialog.java which wraps aroudn
DatePickerDialog
and automatically fixes the context for android 5.0 and 5.1.See gist
I have a possible FIX PATCH that will actually let the user continue using the Lollipop library.
I could only reproduce the crash by enabling TalkBack on an S4 with Android 5.0.1 French, it seems that Samsung is passing the entire date to the item selection string used for accessability instead of the day number.
Building on @mreichelt solution of wrapping the context we can override the getString(id,args) function and actually fix the issue.
So if we provide this context to the DatePickerDialog constructor, it will fix the issue.
UPDATE: This issue also appears in webview when pages contain date input fields, the best way I found that solve both issues (dialog and webview) is to override the Activity getResources function like this:
Note: The solution includes a cached resources - which means if you have events in the app changing the resources (like language change) than you might need to update the cached resources.
this also happens when you programatically define a
min date
further than themax date