-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
Andy Gix
  • 191
  • 1
  • 13

3 Answers3

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.

laalto
  • 150,114
  • 66
  • 286
  • 303
  • 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 Apr 28 '18 at 18:21
  • 1
    You cannot use an activity as a Context before `onCreate()`. `` is too early there, too. – laalto Apr 28 '18 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());
}
Fely
  • 38
  • 8
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.

Fely
  • 38
  • 8