TimePicker in PreferenceScreen
Asked Answered
B

9

79

I'd like to create a preference field called Interval and I want to be able to popup a TimePicker and set a mm:ss formated value with minimal value 00:30 and step 30 seconds.

Is it possible to use TimePicker in PreferenceScreen ?

Badlands answered 3/4, 2011 at 22:53 Comment(0)
C
151

There is no TimePreference built into Android. However, creating your own is fairly easy. Here's one I did:

import android.content.Context;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TimePicker;

public class TimePreference extends DialogPreference {
    private int lastHour=0;
    private int lastMinute=0;
    private TimePicker picker=null;

    public static int getHour(String time) {
        String[] pieces=time.split(":");

        return(Integer.parseInt(pieces[0]));
    }

    public static int getMinute(String time) {
        String[] pieces=time.split(":");

        return(Integer.parseInt(pieces[1]));
    }

    public TimePreference(Context ctxt, AttributeSet attrs) {
        super(ctxt, attrs);

        setPositiveButtonText("Set");
        setNegativeButtonText("Cancel");
    }

    @Override
    protected View onCreateDialogView() {
        picker=new TimePicker(getContext());

        return(picker);
    }

    @Override
    protected void onBindDialogView(View v) {
        super.onBindDialogView(v);

        picker.setCurrentHour(lastHour);
        picker.setCurrentMinute(lastMinute);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            lastHour=picker.getCurrentHour();
            lastMinute=picker.getCurrentMinute();

            String time=String.valueOf(lastHour)+":"+String.valueOf(lastMinute);

            if (callChangeListener(time)) {
                persistString(time);
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return(a.getString(index));
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        String time=null;

        if (restoreValue) {
            if (defaultValue==null) {
                time=getPersistedString("00:00");
            }
            else {
                time=getPersistedString(defaultValue.toString());
            }
        }
        else {
            time=defaultValue.toString();
        }

        lastHour=getHour(time);
        lastMinute=getMinute(time);
    }
}
Cooler answered 3/4, 2011 at 23:42 Comment(18)
Works great, but how do you capture the AM/PM? Is there a property for it? picker.getCurrentHour(); gets the hour, but what about getting AM/PM?Microwave
@Jesse: getCurrentHour() should return a value from 0 to 23.Cooler
This is handy to make sure that typed values are picked up along with those chosen by the spinner: #3993320Mute
How do I retrieve the value of TimePreference in another class? I coded it this way: hora_inicio = Integer.parseInt(sharedPrefs.getString("hora_inicio", "0")); but I'm not sure if this is the way it's supposed to be called?Kerin
@input: The implementation in this question stores the time as a string, in HH:MM format. Another answer in this question has an alternative version that stores the time as a long.Cooler
@CommonsWare, thanks. That helped! Another thing I have noticed is that if I manually enter the hours or mins through EditText inTimePreference it does't save the preference. But if I use the arrow buttons to change the numbers, it will save the preference. A user might want to directly enter the numbers rather than navigating through the arrows. How can I save the preference through EditText?Kerin
@input: Beats me; I never looked at that scenario. It should save the preference regardless when the dialog is submitted.Cooler
@Cooler how to store time in long with time containing ":" which gives class cast exceptionPauper
@Cooler thanks for nice code, i have one question how do i use same class to open timePicker dialog on button click within an activity.i mean without preference screenDyslogistic
@juned: You would not need TimePreference for that. Just create a DialogFragment around the TimePickerDialog, or use the older managed-dialog facility if you are not using fragments. Here is a DialogFragment sample app (albeit one creating an AlertDialog instead of a TimePickerDialog): github.com/commonsguy/cw-omnibus/tree/master/Dialogs/…Cooler
@Cooler Thanks for quick response, but i want use your TimePreference.java class to show time picker but on button click like this showTimePickerDialog() method of this link actually TimePreference.java class is perfect for me so i want to reuse it.Dyslogistic
@juned: You cannot really use a Preference outside of the preference framework. You can use a TimePickerDialog separately from TimePreference, using dialog fragments or managed dialogs.Cooler
@Cooler THanks everything is clear now,i will try to implement separate TimePickerDialogDyslogistic
+1 This answer helped me, thanks! However, I need the minutes in 2 characters only, so I replaced String time=String.valueOf(lastHour)+":"+String.valueOf(lastMinute); with String lastMinuteString = String.valueOf(lastMinute); String time = String.valueOf(lastHour) + ":" + (lastMinuteString.length() == 1 ? "0" + lastMinuteString : lastMinuteString); so the length would always be 2 characters. Still works on Lollipop 5.1 :)Barbaraanne
I updated to androidx and this solution doesn't work anymore, you have to use support library, do not use the new one. (developer.android.com/guide/topics/ui/settings)Africander
Very nice! Is it possible to create one for the new androidx api?Semeiology
@MartinVysny: Presumably, though I haven't tried it.Cooler
@MartinVysny I am also trying to get same one with androidx but it's not showing onCreateDialogView method as overrided method. Did you found any solution?Couch
W
72

I have modified the code from first answer:

  • it stores selected time in long form (milliseconds) which is easier to work with (using Calendar) then string
  • it automatically shows selected time in summary field in user's format (12 or 24 hour)

Updated code:

public class TimePreference extends DialogPreference {
    private Calendar calendar;
    private TimePicker picker = null;

    public TimePreference(Context ctxt) {
        this(ctxt, null);
    }

    public TimePreference(Context ctxt, AttributeSet attrs) {
        this(ctxt, attrs, android.R.attr.dialogPreferenceStyle);
    }

    public TimePreference(Context ctxt, AttributeSet attrs, int defStyle) {
        super(ctxt, attrs, defStyle);

        setPositiveButtonText(R.string.set);
        setNegativeButtonText(R.string.cancel);
        calendar = new GregorianCalendar();
    }

    @Override
    protected View onCreateDialogView() {
        picker = new TimePicker(getContext());
        return (picker);
    }

    @Override
    protected void onBindDialogView(View v) {
        super.onBindDialogView(v);
        picker.setCurrentHour(calendar.get(Calendar.HOUR_OF_DAY));
        picker.setCurrentMinute(calendar.get(Calendar.MINUTE));
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            calendar.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour());
            calendar.set(Calendar.MINUTE, picker.getCurrentMinute());

            setSummary(getSummary());
            if (callChangeListener(calendar.getTimeInMillis())) {
                persistLong(calendar.getTimeInMillis());
                notifyChanged();
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return (a.getString(index));
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {

        if (restoreValue) {
            if (defaultValue == null) {
                calendar.setTimeInMillis(getPersistedLong(System.currentTimeMillis()));
            } else {
                calendar.setTimeInMillis(Long.parseLong(getPersistedString((String) defaultValue)));
            }
        } else {
            if (defaultValue == null) {
                calendar.setTimeInMillis(System.currentTimeMillis());
            } else {
                calendar.setTimeInMillis(Long.parseLong((String) defaultValue));
            }
        }
        setSummary(getSummary());
    }

    @Override
    public CharSequence getSummary() {
        if (calendar == null) {
            return null;
        }
        return DateFormat.getTimeFormat(getContext()).format(new Date(calendar.getTimeInMillis()));
    }
} 
Wycoff answered 15/5, 2012 at 20:44 Comment(13)
Great, but how do you supply a default value in a numeric format? When I use android:defaultValue="3600000" the defaultValue is a String, so it first needs to be parsed to Long.Divulgate
@Destil i get class cast exception in onsetInitialValue...any possible remedy..thanksPauper
Your onSetInitialValue breaks the contract defined in the API documentation. You are allowed to use the defaultValue parameter only if restoreValue is false. Making it work as it is expected expected simplifies the if-else statements considerably.Isola
Does anyone know how to compare the stored value to the current time. I have to two TimePreference, a start and end time, and I'd like to tell if the current time is between the selected start and end time. I thought I could use System.currentTimeMillis() as a compare value, but that doesn't seem to work.Sabulous
+1 Because this is simply a lot better than the highest voted answer.Borneo
Is anyone else getting 07-16 15:33:41.689: W/ResourceType(9228): Failure getting entry for 0x010802c9 (t=7 e=713) in package 0 (error -75)Diaphanous
And why can i not set the android:defaultValue="3600000"Diaphanous
Caution: You cannot use the defaultValue as the default value in the getPersisted*() method, because its value is always null when restorePersistedValue is true. .....So there is no need of extra if else conditions... otherwise u had done a great job.Forthright
Great answer save for one minor issue. If restoreValue == false then you must call persistLong(calendar.getTimeInMillis()); as the last line in the code block. Otherwise PreferenceManager.setDefaultValues(...) does not work as expected and PreferenceManager.getDefaultSharedPreferences(this).getLong(...) will not return the default value unless it has actually been selected in the preferences.Farmland
If you are having issues with text style being different from other preferences then change the two argument constructor to use internal Android style rather that 0. Change: this(context, attrs, android.R.attr.dialogPreferenceStyle);Adriannaadrianne
Could you please implement how to getHour, getMinute of this class? Thank youFlabellate
How would I set a default value to 8am? I'm not sure how to sort that out when using setTimeMillis.Freewheel
I've set the default time in XML, like this: android:defaultValue="148417253000" But that gives a NumberFormatException. (because for some reason this is converted to scientific notation, e.g. 1.48417253E12) The solution for this is: long timeLong = Double.valueOf(defaultValue.toString()).longValue(); calendar.setTimeInMillis(timeLong);Fraktur
L
57

For those whom the implementation of a custom Preference isn't so obvious (like it wasn't for me), you have to add this to your preferences.xml or whatever you're calling it.

You'll end up with something like this:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <EditTextPreference
        android:key="editTextPref_Key"
        android:title="@string/editTextPref_title"/>
    <com.example.myapp.TimePreference
        android:key="timePrefA_Key"
        android:title="@string/timePrefA_title"/>    
    <com.example.myapp.TimePreference
        android:key="timePrefB_Key"
        android:title="@string/timePrefB_title"/>

</PreferenceScreen>

Assuming you added the TimePreference to your own root package:
(src/com/example/myapp/TimePreference.java)

Load answered 21/4, 2012 at 23:4 Comment(6)
How do I retrieve the value of TimePreference in another class? I coded it this way: hora_inicio = Integer.parseInt(sharedPrefs.getString("hora_inicio", "0")); but I'm not sure if this is the way it's supposed to be called?Kerin
@Kerin I'm not sure if this is what you're looking for but, here it goes: SharedPreferences prefs; prefs = PreferenceManager.getDefaultSharedPreferences(this); String[] pieces = refs.getString("hora_inicio","08:00").split(":"); the second argument is the default value if it's not set.Load
Added the preference as stated which works like a charm (thanks for that). However, the style of the preference texts is different from the rest, that is, in the overview of titles and summaries, the font looks bigger and a margin seems to be added. Any ideas on how to change that?Bremer
Use this as the second constructor: public TimePreference(Context mContext, AttributeSet mAttributeSet) { this(mContext, mAttributeSet, android.R.attr.preferenceStyle); }Extirpate
Is anyone else getting 07-16 15:33:41.689: W/ResourceType(9228): Failure getting entry for 0x010802c9 (t=7 e=713) in package 0 (error -75)Diaphanous
How to access the data set in the preference ?Deracinate
I
31

For Preferences Support Library different code is needed. It requires two custom classes TimePreference and TimePreferenceDialogFragmentCompat, as well as overide of onDisplayPreferenceDialog method in PreferenceFragmentCompat extension class.


TimePreference.java

package com.test;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.v7.preference.DialogPreference;
import android.util.AttributeSet;

public class TimePreference extends DialogPreference
{
    public int hour = 0;
    public int minute = 0;

    public static int parseHour(String value)
    {
        try
        {
            String[] time = value.split(":");
            return (Integer.parseInt(time[0]));
        }
        catch (Exception e)
        {
            return 0;
        }
    }

    public static int parseMinute(String value)
    {
        try
        {
            String[] time = value.split(":");
            return (Integer.parseInt(time[1]));
        }
        catch (Exception e)
        {
            return 0;
        }
    }

    public static String timeToString(int h, int m)
    {
        return String.format("%02d", h) + ":" + String.format("%02d", m);
    }

    public TimePreference(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index)
    {
        return a.getString(index);
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue)
    {
        String value;
        if (restoreValue)
        {
            if (defaultValue == null) value = getPersistedString("00:00");
            else value = getPersistedString(defaultValue.toString());
        }
        else
        {
            value = defaultValue.toString();
        }

        hour = parseHour(value);
        minute = parseMinute(value);
    }

    public void persistStringValue(String value)
    {
        persistString(value);
    }
}

TimePreferenceDialogFragmentCompat.java

package com.test;

import android.content.Context;
import android.support.v7.preference.DialogPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceDialogFragmentCompat;
import android.view.View;
import android.widget.TimePicker;

public class TimePreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat implements DialogPreference.TargetFragment
{
    TimePicker timePicker = null;

    @Override
    protected View onCreateDialogView(Context context)
    {
        timePicker = new TimePicker(context);
        return (timePicker);
    }

    @Override
    protected void onBindDialogView(View v)
    {
        super.onBindDialogView(v);
        timePicker.setIs24HourView(true);
        TimePreference pref = (TimePreference) getPreference();
        timePicker.setCurrentHour(pref.hour);
        timePicker.setCurrentMinute(pref.minute);
    }

    @Override
    public void onDialogClosed(boolean positiveResult)
    {
        if (positiveResult)
        {
            TimePreference pref = (TimePreference) getPreference();
            pref.hour = timePicker.getCurrentHour();
            pref.minute = timePicker.getCurrentMinute();

            String value = TimePreference.timeToString(pref.hour, pref.minute);
            if (pref.callChangeListener(value)) pref.persistStringValue(value);
        }
    }

    @Override
    public Preference findPreference(CharSequence charSequence)
    {
        return getPreference();
    }
}

Required modifications in PreferenceFragmentCompat extension class

    public static class PreferencesFragment extends PreferenceFragmentCompat
    {
       ....

        @Override
        public void onDisplayPreferenceDialog(Preference preference)
        {
            DialogFragment dialogFragment = null;
            if (preference instanceof TimePreference)
            {
                dialogFragment = new TimePreferenceDialogFragmentCompat();
                Bundle bundle = new Bundle(1);
                bundle.putString("key", preference.getKey());
                dialogFragment.setArguments(bundle);
            }

            if (dialogFragment != null)
            {
                dialogFragment.setTargetFragment(this, 0);
                dialogFragment.show(this.getFragmentManager(), "android.support.v7.preference.PreferenceFragment.DIALOG");
            }
            else
            {
                super.onDisplayPreferenceDialog(preference);
            }
        }
    }

With above code time preference can be used in preferences xml file like this

<com.test.TimePreference
    android:key="some_time"
    android:title="Set some time"
    android:defaultValue="12:00"
    android:summary="Set some time"/>
Inequitable answered 21/12, 2015 at 15:7 Comment(9)
If I add 2 of these, after setting the 1st TimePreference, the 2nd TimePreference's time is set to the same. How can I make a difference between 2 TimePreferences?Disgust
Solved, forgot to change the key.Disgust
Works like charm!Konstantin
Could you explain why this is needed, as opposed to the solutions above?Stickweed
@JulianDelphiki Like I said in first line of my answer Preferences Support Library requires different code. Other solutions work for regular Preference classes.Inequitable
More than perfect!! Used it to create a custom date picker for a date setting with Xamarin. Use also the PreferenceManager of the support library to set default values for example, in PreferenceManager.SetDefaultValues(context, resId, readAgain)Alisun
What do you mean by PreferenceFragmentCompat extension class? How can you modify a built in class? You didn't use it in your code, only implemented it. How do I implement abstract onCreatePreferences in PreferencesFragment class?Westering
@Westering You don't modify built in class, you extend it - hence term extension, though it is a bit imprecise and ambiguous. You create descendant class (subclass) to implement different behavior.Inequitable
Thank you @DalijaPrasnikar, I just read How to use the v7/v14 Preference Support library? and understood how to use PreferenceFragmentCompat extending class.Westering
K
5

CommonsWare's solution has a few problems, which I fixed:

  • It doesn't update the field properly after it is changed
  • The minutes value only persists a single digit, e.g. 10:2 instead of 10:02
  • If you use PreferenceManager.setDefaultPreferences to set initial default preferences in your app, it won't work because onSetInitialValue needs to persist it
  • The formatting of the result isn't tailored to the user's Locale (e.g. US uses AM/PM)

Here's my code, enjoy.

public class TimePreference extends DialogPreference {
    private int lastHour=0;
    private int lastMinute=0;
    private TimePicker picker=null;

    public static int getHour(String time) {
        String[] pieces=time.split(":");

        return(Integer.parseInt(pieces[0]));
    }

    public static int getMinute(String time) {
        String[] pieces=time.split(":");

        return(Integer.parseInt(pieces[1]));
    }

    public TimePreference(Context ctxt, AttributeSet attrs) {
        super(ctxt, attrs);

        setPositiveButtonText("Set");
        setNegativeButtonText("Cancel");
    }

    @Override
    protected View onCreateDialogView() {
        picker=new TimePicker(getContext());

        return(picker);
    }

    @Override
    protected void onBindDialogView(View v) {
        super.onBindDialogView(v);

        picker.setCurrentHour(lastHour);
        picker.setCurrentMinute(lastMinute);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            lastHour=picker.getCurrentHour();
            lastMinute=picker.getCurrentMinute();

            setSummary(getSummary());

            String lastMinuteString = String.valueOf(lastMinute);
            String time = String.valueOf(lastHour) + ":" + (lastMinuteString.length() == 1 ? "0" + lastMinuteString : lastMinuteString);

            if (callChangeListener(time)) {
                persistString(time);
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return(a.getString(index));
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {

        String time;
        String defaultValueStr = (defaultValue != null) ? defaultValue.toString() : "00:00";
        if (restoreValue)
            time = getPersistedString(defaultValueStr);
        else {
            time = defaultValueStr;
            if (shouldPersist())
                persistString(defaultValueStr);
        }

        lastHour=getHour(time);
        lastMinute=getMinute(time);

        setSummary(getSummary());
    }

    @Override
    public CharSequence getSummary() {

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, lastHour);
        cal.set(Calendar.MINUTE, lastMinute);
        DateFormat sdf = SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT);

        return sdf.format(cal.getTime());
    }

}
Kathikathiawar answered 30/4, 2017 at 21:9 Comment(0)
O
4

add this for Summary:

@Override
public CharSequence getSummary() {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, lastHour, lastMinute);
    return DateFormat.getTimeFormat(getContext()).format(new Date(cal.getTimeInMillis()));
}

and add

setSummary(getSummary());

to end of onSetInitialValue and onDialogClosed.

Oblation answered 25/1, 2014 at 7:14 Comment(0)
A
1

I have modified CommonsWare answer to use JodaTime library:

import android.content.Context;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TimePicker;

import org.joda.time.LocalTime;

public class TimePreference extends DialogPreference {
    private int lastHour;
    private int lastMinute;
    private TimePicker picker;

    public TimePreference(Context context, AttributeSet attrs) {
        super(context, attrs);

        setPositiveButtonText("Set");
        setNegativeButtonText("Cancel");
    }

    @Override
    protected View onCreateDialogView() {
        picker = new TimePicker(getContext());

        return(picker);
    }

    @Override
    protected void onBindDialogView(@NonNull View v) {
        super.onBindDialogView(v);

        picker.setCurrentHour(lastHour);
        picker.setCurrentMinute(lastMinute);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            lastHour = picker.getCurrentHour();
            lastMinute = picker.getCurrentMinute();

            LocalTime localTime = new LocalTime(lastHour, lastMinute);
            String time = localTime.toString();

            if (callChangeListener(time)) {
                persistString(time);
            }
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return(a.getString(index));
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        LocalTime time;

        if (restoreValue) {
            if (defaultValue == null) {
                time = LocalTime.parse(getPersistedString("08:00:00.000"));
            }
            else {
                time = LocalTime.parse(getPersistedString(defaultValue.toString()));
            }
        } else {
            time = LocalTime.parse(defaultValue.toString());
        }

        lastHour = time.getHourOfDay();
        lastMinute = time.getMinuteOfHour();
    }
}

Also you will need to add a Custom preference like Sikora said.

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <EditTextPreference
        android:key="editTextPref_Key"
        android:title="@string/editTextPref_title"/>
    <com.example.myapp.TimePreference
        android:key="timePrefA_Key"
        android:title="@string/timePrefA_title"/>    
    <com.example.myapp.TimePreference
        android:key="timePrefB_Key"
        android:title="@string/timePrefB_title"/>

</PreferenceScreen>
Aragats answered 10/12, 2014 at 5:27 Comment(0)
W
1

With Android 6, "current hour" and "current minute" are deprecated. Use this to ensure Marshmallow compatibility:

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TimePicker;

public class TimePreference extends DialogPreference {

private int lastHour;
private int lastMinute;
private TimePicker picker;

public TimePreference(Context ctx, AttributeSet attrs) {
    super(ctx, attrs);
    setPositiveButtonText(ctx.getString(android.R.string.ok));
    setNegativeButtonText(ctx.getString(android.R.string.cancel));
}

@Override
protected View onCreateDialogView() {
    picker = new TimePicker(getContext());
    picker.setIs24HourView(true);
    return picker;
}

@SuppressWarnings("deprecation")
@Override
protected void onBindDialogView(View v) {
    super.onBindDialogView(v);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        picker.setCurrentHour(lastHour);
        picker.setCurrentMinute(lastMinute);
    } else {
        picker.setHour(lastHour);
        picker.setMinute(lastMinute);
    }
}

@SuppressWarnings("deprecation")
@Override
protected void onDialogClosed(boolean positiveResult) {
    super.onDialogClosed(positiveResult);
    if (positiveResult) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            lastHour = picker.getCurrentHour();
            lastMinute = picker.getCurrentMinute();
        } else {
            lastHour = picker.getHour();
            lastMinute = picker.getMinute();
        }
        String time = String.valueOf(lastHour) + ":" + String.valueOf(lastMinute);
        if (callChangeListener(time)) {
            persistString(time);
        }
    }
}

@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
    return a.getString(index);
}

@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
    String time;
    if (restoreValue) {
        if (defaultValue == null) {
            time = getPersistedString("00:00");
        } else {
            time = getPersistedString(defaultValue.toString());
        }
    } else {
        time = defaultValue.toString();
    }
    lastHour = getHour(time);
    lastMinute = getMinute(time);
}

public static int getHour(String time) {
    String[] pieces = time.split(":");
    return Integer.parseInt(pieces[0]);
}

public static int getMinute(String time) {
    String[] pieces = time.split(":");
    return Integer.parseInt(pieces[1]);
}
}
Winze answered 9/10, 2015 at 8:1 Comment(0)
C
0

Like LEO87, I was seeing ClassCastException's. The problem was due to stale persisted data from a previous control of the same name. Possible solutions are to clear the app data, use a different name (key), or if you must use the same key name, catch the exception as follows:

@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
    if (restoreValue) {
        long persistedValue;
        try {
            persistedValue = getPersistedLong(System.currentTimeMillis());
        } catch (Exception e) {
            //Stale persisted data may be the wrong type
            persistedValue = System.currentTimeMillis();
        }
        calendar.setTimeInMillis(persistedValue);
    } else if (defaultValue != null) {
        calendar.setTimeInMillis(Long.parseLong((String) defaultValue));
    } else {
        //!restoreValue, defaultValue == null
        calendar.setTimeInMillis(System.currentTimeMillis());
    }

    setSummary(getSummary());
}
Catchup answered 14/8, 2013 at 3:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.