-2

I am trying to play around with sharedPreferences in order to understand how they work. I have a date picker and want the following: When the app opens for the first time, the date picker would show up and someone selects a date. After that the date would be stored and then a textView displays the date everytime the app is opened, without the date picker appearing again. Also, I want the date stored for future reference.

This is my code:

Main class

private TextView mDisplayDate;
DialogFragment bday = new BdayPick();
public static final String TAG = "main_date";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mDisplayDate = findViewById(R.id.tvDate);
    }

@SuppressLint({"SetTextI18n", "ApplySharedPref"})
@Override
protected void onResume() {
    super.onResume();
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
    boolean previouslyStarted = prefs.getBoolean(getString(R.string.pref_previously_started), false);
    if (!previouslyStarted) {
        SharedPreferences.Editor edit = prefs.edit();
        edit.putBoolean(getString(R.string.pref_previously_started), Boolean.TRUE);
        edit.commit();
        bday.show(getSupportFragmentManager(), "datePicker");
    } else setDateChosen();
}

@SuppressLint("SetTextI18n")
private void setDateChosen() {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        int day = prefs.getInt(String.valueOf(selected_day), 0);
        int year = prefs.getInt(String.valueOf(selected_year), 0);
        String month = prefs.getString(String.valueOf(selected_month), "0");
        Log.d(TAG, day + " / " + month + " / " + year);
        mDisplayDate.setText("The Selected date is: " + day + "-" + month + "-" + year);
}

Picker class

public class BdayPick extends DialogFragment
                            implements DatePickerDialog.OnDateSetListener {

   // Context context = getActivity();
    SharedPreferences sharedPrefs = getActivity().getPreferences(Context.MODE_PRIVATE);
@NonNull
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public Dialog onCreateDialog (Bundle savedInstanceState) {
    final Calendar cal = Calendar.getInstance();
    int year = cal.get(Calendar.YEAR);
    int month = cal.get(Calendar.MONTH);
    int day = cal.get(Calendar.DAY_OF_MONTH);

    return new DatePickerDialog(Objects.requireNonNull(getActivity()),
            android.R.style.Theme_Holo_Dialog,
            this,
            year, month, day);
}

@SuppressLint("StringFormatInvalid")
public void onDateSet(DatePicker view, int year, int month, int day) {
    //TODO calculate and show required textl
    month = month + 1;
    String date = day + "-" + month + "-" + year;

    SharedPreferences.Editor editor = sharedPrefs.edit();
    editor.putInt(getString(R.string.selected_day), day);
    editor.putString(getString(R.string.selected_month), String.valueOf(month));
    editor.putInt(getString(R.string.selected_year), year);
    editor.apply();

    Toast.makeText(getActivity(), date, Toast.LENGTH_LONG).show();
}
}

I have no build or compile errors, but when I try to open the app it simply crashes and I don't understand why.

**Edit: Logcat is solved with this. I have edited based oin the answers:

public void onDateSet(DatePicker view, int year, int month, int day) {
        month = month + 1;
        String date = day + "-" + month + "-" + year;

        SharedPreferences.Editor editor = sharedPrefs.edit();
        /*editor.putInt(getContext().getResources().getString(R.string.selected_day), day);
        editor.putString(getContext().getResources().getString(R.string.selected_month), String.valueOf(month));
        editor.putInt(getContext().getResources().getString(R.string.selected_year), year);
        editor.apply();
        */

    Calendar cal;
    cal= Calendar.getInstance().set(view.getYear(), view.getMonth(), view.getDayOfMonth());
    Date d = cal.getTime();
    PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putString("pref_date", new SimpleDateFormat("ddMMyyyy").format(d));
    //editor.putString("date", new SimpleDateFormat("ddMMyyyy").format(c.getTime()));
        editor.apply();

    Toast.makeText(getActivity(), date, Toast.LENGTH_LONG).show();
    }

But now I have the following error:

incompatible types: void cannot be converted to Calendar
6
  • check the logcat and see the error Commented Apr 6, 2018 at 15:57
  • You are posting a log that has nothing to do with the crash
    – Chisko
    Commented Apr 6, 2018 at 16:07
  • Not sure what log I should add in this case.
    – Andy Gix
    Commented Apr 6, 2018 at 16:11
  • Search with 'exception' in the log. Then post it here. Commented Apr 6, 2018 at 16:13
  • This? '04-06 16:19:23.842 1693-1715/system_process E/KernelUidCpuFreqTimeReader: Failed to read /proc/uid_time_in_state: java.io.FileNotFoundException: /proc/uid_time_in_state (No such file or directory) '
    – Andy Gix
    Commented Apr 6, 2018 at 16:22

3 Answers 3

2
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.SharedPreferences android.support.v4.app.FragmentActivity.getPreferences(int)' on a null object reference
  at com.example.zodiac.zodiac.BdayPick.<init>(BdayPick.java:23)

You're calling getPreferences() on a null here:

SharedPreferences sharedPrefs = getActivity().getPreferences(Context.MODE_PRIVATE);

where <init> refers to that the object is being initialized, with field init in this case. <init> is too early for getActivity() to return anything other than null - the fragment is not attached to any activity yet.

You'll need to move the code that requires a Context to a later phase, onAttach() or later in the fragment lifecycle.

2
  • What if I am not using fragments? I am getting a similar null error on a main activity, while trying to use this.getPreferences(Context.MODE_PRIVATE)
    – Andy Gix
    Commented Apr 28, 2018 at 18:21
  • 1
    You cannot use an activity as a Context before onCreate(). <init> is too early there, too.
    – laalto
    Commented Apr 28, 2018 at 18:26
0

In Main class change edit.commit(); to edit.apply();

and also use putBoolean(..., true) instead of putBoolean(..., Boolean.TRUE).

**EDIT: DO NOT use string resource in SharedPrefernece. Use constant string instead. You can try to use Date formats, like:

f.e.:

Calendar c = Calendar.getInstance().set(view.getYear(), view.getMonth(), view.getDayOfMonth());
Date d = c.getTime();
PreferenceManager.getDefaultSharedPreferences(getAppliactionContext()).edit().putString("pref_date", new SimpleDateFormat("ddMMyyyy").format(d));

and read value using:

try {
    Date d = new SimpleDateFormat("ddMMyyyy").parse(PreferenceManager.getDefaultSharedPreferences(getAppliactionContext()).getString("pref_date", ""));

    //DO SOMETHING WITH THE VALUE
}
catch (ParseException e){
    Log.e("PreferenceRead ", e.getMessage());
}
3
  • Tried it. Still crashes.
    – Andy Gix
    Commented Apr 6, 2018 at 16:30
  • So post your full LogCat. Not just few of lines.
    – Fely
    Commented Apr 6, 2018 at 16:35
  • Tried this, but I am getting error incompatible types: void cannot be converted to Calendar
    – Andy Gix
    Commented Apr 6, 2018 at 20:04
0

Your problem is there:

SharedPreferences sharedPrefs = getActivity().getPreferences(Context.MODE_PRIVATE);

You may use: SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); instead.

If you want not default SharedPreferences you can use getActivity().getPreferences("name", Context.MODE_PRIVATE);, but I recommend you to use default for this.

Not the answer you're looking for? Browse other questions tagged or ask your own question.