DatePicker zawiesza się na moim urządzeniu po kliknięciu (w aplikacji osobistej)
Edit: sprawdziłem, że problem pojawia się tylko wtedy, gdy telefon jest ustawiony z" francuskim " językiem.
Obecnie buduję własną aplikację i mam problem z używaniem widżetu DatePicker w telefonie (tryb debugowania telefon : Samsung S5).
Błąd: java.util.IllegalFormatConversionException
Dodaję więcej szczegółów na temat problemu zebranego w 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)
Oto Mój kod dialogowy:
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);
}
}
}
A oto 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>
Faktem jest, że miałem dwa rodzaje problemów (prowadzące do awarii aplikacji i tak):
- kiedy wejdę do aplikacji i przejdę bezpośrednio do widżetu DatePicker, kalendarz jest poprawnie wyświetlany i jak tylko wybieram dzień (mówię dzień, bo nie ma problemu ze zmianą roku na przykład), aplikacja ulega awarii.
- jeśli przejdę na inną funkcję Kliknij, aby wyświetlić DatePicker, to zawiesza się bezpośrednio.
Widziałem inne wątki jak : awaria DatePicker w Samsungu z Androidem 5.0
W tym wątku nie dostaję wystarczającej ilości informacji, ponieważ podane rozwiązanie pozwala na wyświetlenie tylko widoku spinnera kalendarza, a ponadto wyświetlany spinner nie jest wyśrodkowany i przedstawiony jako mój (umieszczony bezpośrednio na górze ekranu).
Jeśli potrzebujesz więcej szczegółów, Zapytaj mnie. Dzięki. Alex.7 answers
To błąd Samsunga w implementacji Lollipop UI. Dotyczy Galaxy S4, S5, Note 3 i prawdopodobnie więcej urządzeń. Dla nas występuje na językach de_DE i de_AT, ale wydaje się, że jest to problem, który dotyczy wielu języków.
Naprawiłem to, zmuszając urządzenia Samsung do używania motywu Holo do wyboru daty. W naszym DatePickerFragment:
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
/* calendar code here */
Context context = getActivity();
if (isBrokenSamsungDevice()) {
context = new ContextThemeWrapper(getActivity(), android.R.style.Theme_Holo_Light_Dialog);
}
return new DatePickerDialog(context, this, year, month, day);
}
private static boolean isBrokenSamsungDevice() {
return (Build.MANUFACTURER.equalsIgnoreCase("samsung")
&& isBetweenAndroidVersions(
Build.VERSION_CODES.LOLLIPOP,
Build.VERSION_CODES.LOLLIPOP_MR1));
}
private static boolean isBetweenAndroidVersions(int min, int max) {
return Build.VERSION.SDK_INT >= min && Build.VERSION.SDK_INT <= max;
}
Dzięki Samsungowi ich użytkownicy nie dostaną ładnego, zaprojektowanego z materiału, datownika.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-06 12:25:46
Mam możliwą łatkę, która pozwoli użytkownikowi kontynuować korzystanie z biblioteki Lollipop.
Mogłem tylko odtworzyć awarię, włączając TalkBack na s4 z Androidem 5.0.1 French, wydaje się, że Samsung przekazuje całą datę do ciągu wyboru pozycji używanego do dostępu zamiast numeru dnia.
Bazując na @ mreichelt rozwiązanie zawijania kontekstu możemy nadpisać getString (id,args) funkcja i rzeczywiście rozwiązać problem.
context = new ContextWrapper(getActivity()) {
private Resources wrappedResources;
@Override
public Resources getResources() {
Resources r = super.getResources();
if(wrappedResources == null) {
wrappedResources = new Resources(r.getAssets(), r.getDisplayMetrics(), r.getConfiguration()) {
@NonNull
@Override
public String getString(int id, Object... formatArgs) throws NotFoundException {
try {
return super.getString(id, formatArgs);
} catch (IllegalFormatConversionException ifce) {
Log.e("DatePickerDialogFix", "IllegalFormatConversionException Fixed!", ifce);
String template = super.getString(id);
template = template.replaceAll("%" + ifce.getConversion(), "%s");
return String.format(getConfiguration().locale, template, formatArgs);
}
}
};
}
return wrappedResources;
}
};
Więc jeśli dostarczymy ten kontekst konstruktorowi DatePickerDialog, rozwiąże to problem.
Aktualizacja: Ten problem pojawia się również w widoku sieci Web, gdy strony zawierają pola wprowadzania daty, najlepszym sposobem rozwiązania obu problemów (dialog i webview) jest nadpisanie funkcji Activity getResources w następujący sposób: {]}
@Override
public Resources getResources() {
if (wrappedResources == null) {
wrappedResources = wrapResourcesFixDateDialogCrash(super.getResources());
}
return wrappedResources;
}
public Resources wrapResourcesFixDateDialogCrash(Resources r) {
return new Resources(r.getAssets(), r.getDisplayMetrics(), r.getConfiguration()) {
@NonNull
@Override
public String getString(int id, Object... formatArgs) throws NotFoundException {
try {
return super.getString(id, formatArgs);
} catch (IllegalFormatConversionException ifce) {
Log.i("DatePickerDialogFix", "IllegalFormatConversionException Fixed!", ifce);
String template = super.getString(id);
template = template.replaceAll("%" + ifce.getConversion(), "%s");
return String.format(getConfiguration().locale, template, formatArgs);
}
}
};
}
Uwaga: rozwiązanie zawiera zasoby buforowane - co oznacza, że jeśli w aplikacji występują zdarzenia zmieniające zasoby (np. zmiana języka), może być konieczne zaktualizuj zasoby pamięci podręcznej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-08 13:20:57
Znajduję obejście, bawiąc się zmiennymi konfiguracyjnymi i Locale.
I juste modyfikować język, jeśli wykryję, że jest to język francuski ("fr") i zastąpić go językiem angielskim ("en"), a następnie umieścić z powrotem do normalnego raz z datepicker DialogFragment.
public void showDatePickerDialog(int layoutId) {
Integer year = cal.get(Calendar.YEAR);
Integer month = cal.get(Calendar.MONTH);
Integer day = cal.get(Calendar.DAY_OF_MONTH);
// Due to an issue with DatePicker and fr language (locale), if locale language is french, this is changed to us to make the DatePicker working
if(Locale.getDefault().getLanguage().toString().equals(FR_LANG_CONTEXT)){
Configuration config = new Configuration();
config.locale = new Locale(US_LANG_CONTEXT);
getApplicationContext().getResources().updateConfiguration(config, null);
}
Bundle bundle = createDatePickerBundle(layoutId, year, month, day);
DialogFragment newFragment = new DatePFragment();
newFragment.setArguments(bundle);
newFragment.show(fm, Integer.toString(layoutId));
}
A gdy już wyjdę
@Override
public void onDatePicked(int LayoutId, int year, int month, int day){
// Once out from the DatePicker, if we were working on a fr language, we update back the configuration with fr language.
if(Locale.getDefault().getLanguage().toString().equals(FR_LANG_CONTEXT)){
Configuration config = new Configuration();
config.locale = new Locale(FR_LANG_CONTEXT);
getApplicationContext().getResources().updateConfiguration(config, null);
}
String date = day + "/" + month + "/" + year;
txtTaskDate.setText(date);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-20 14:59:28
Zapomnij o wbudowanym selektorze dat. IMHO przełączanie locale nie jest rozwiązaniem, ponieważ chcę mieć selektor w bieżącym locale. Jest tylko jeden sposób, aby pozbyć się awarii: użyj biblioteki, która zapewnia niezależną implementację.
Dla fragmentu wyboru daty: https://github.com/flavienlaurent/datetimepicker
Dla widżetu wyboru daty: https://github.com/SingleCycleKing/CustomTimePicker (jest to bardziej punkt wyjścia niż ready-to-use-solution)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-22 06:29:29
Zauważyłem jeden drobny problem z rozwiązaniem @mreichelt. Okno zostało renderowane bez tytułu pokazującego aktualnie wybraną datę (w tym dzień tygodnia). Jawne ustawienie tytułu i natychmiastowe ponowne ustawienie daty rozwiązało ten problem.
Context context = getActivity();
if (isBrokenSamsungDevice()) {
context = new ContextThemeWrapper(getActivity(), android.R.style.Theme_Holo_Light_Dialog);
}
DatePickerDialog datePickerDialog = new DatePickerDialog(context, this, year, month, day);
if (isBrokenSamsungDevice()) {
datePickerDialog.setTitle("");
datePickerDialog.updateDate(year, month, day);
}
return datePickerDialog;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-12 20:22:50
Na podstawie mreichelts answer stworzyłem SupportDatePickerDialog.java, która zawija aroudn DatePickerDialog
i automatycznie naprawia kontekst dla Androida 5.0 i 5.1.
Zobacz gist
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:13
Dzieje się tak również wtedy, gdy programowo zdefiniujesz min date
dalej niż max date
datePicker.getDatePicker().setMaxDate(15000000);
datePicker.getDatePicker().setMinDate(16000000);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-29 11:24:06