1

What I'm trying to do is have a setting menu pull up when a button is pressed on my main menu (settings menu is implemented as a separate activity from my main). For simplicity's sake, assume that my main menu is blank except for 1 button that pulls up the settings menu. In the setting menu, there is one check box and one button "Done" that returns to the main activity.

How do I save a CheckBox's and load it (what should the code be, where should I put it, why, etc) ? I've tried googling it, and trying to replicate the results, but I can't seem to get it. 2 things have happened so far: nothing has saved, or my program crashes.

Once I have the information about the checkbox saved, how am I able to access this information from my main activity @I want to be able to run certain code based on if the user checked the box or not?

some results that I've landed on and tried: How to save the checkbox state? - android Saving Checkbox states

(Please keep in mind that I'm completely new to this)

public class Settings extends ActionBarActivity {

    private static final String SETTING_CHECK_BOX = "SETTINGS";
    private CheckBox cb;
    //char boxChecked = '0';
    @Override
    protected void onCreate(Bundle savedSettings) {
        super.onCreate(savedSettings);
        cb = (CheckBox) findViewById(R.id.checkBox);
        setContentView(R.layout.activity_settings);
        cb.setChecked(isCheckedSettingEnabled());
    }

    private void setCheckedSettingEnabled(boolean enabled) {
        PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean(SETTING_CHECK_BOX, enabled).apply();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_settings, menu);
        return true;
    }

    private boolean isCheckedSettingEnabled() {
        return PreferenceManager.getDefaultSharedPreferences(this).getBoolean(SETTING_CHECK_BOX, false);
    }

    public void onPause() {
        super.onPause();

        // Persist the setting. Could also do this with an OnCheckedChangeListener.
        setCheckedSettingEnabled(cb.isChecked());
    }

    public void clickedDone (View v) {
        SharedPreferences settings = getSharedPreferences("SETTINGS", 0);
        settings.edit().putBoolean("check",true).commit();
        finish();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

So now my app doesn't crash anymore, but the state is not remembered (always unchecked when settings menu is open). I changed cb.setChecked(checkState) to cb.setChecked(TRUE), which didn't change anything (still always unchecked when settings menu is open). What is going on?

Community
  • 1
  • 1
Jonathan Chiou
  • 349
  • 6
  • 15

2 Answers2

3

onSaveInstanceState() is only for persisting data for that instance of the Activity. Once that Activity has had finish() invoked, that state is no longer relevant. You need to write your settings to persistent storage. A simple storage solution for your case is SharedPreferences.

public class Settings extends ActionBarActivity {
    // Create a constant for the setting that you're saving
    private static final String SETTING_CHECK_BOX = "checkbox_setting";

    private CheckBox mCheckBox;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);
        mCheckBox = (CheckBox) findViewById(R.id.checkBox);

        // Set the initial state of the check box based on saved value
        mCheckBox.setChecked(isCheckedSettingEnabled());
    }

    @Override
    public void onPause() {
        super.onPause();

        // Persist the setting. Could also do this with an OnCheckedChangeListener.
        setCheckedSettingEnabled(mCheckBox.isChecked());
    }

    /**
     * Returns true if the setting has been saved as enabled,
     * false by default
     */
    private boolean isCheckedSettingEnabled() {
        return PreferenceManager.getDefaultSharedPreferences(this)
                .getBoolean(SETTING_CHECK_BOX, false);
    }

    /**
     * Persists the new state of the setting
     * 
     * @param enabled the new state for the setting
     */
    private void setCheckedSettingEnabled(boolean enabled) {
        PreferenceManager.getDefaultSharedPreferences(this)
                .edit()
                .putBoolean(SETTING_CHECK_BOX, enabled)
                .apply();
    }
}
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • This crashes my app the moment I hit "settings". – Jonathan Chiou Jan 12 '15 at 05:27
  • With what error? Read your stack trace. EDIT: If it's what you added to your question, you have to call `setContentView()` **before** you retrieve references to Views (e.g. the CheckBox). – Kevin Coppock Jan 12 '15 at 05:30
  • Exactly as stated. Flip the lines of code where you set the content view and where you get the checkbox reference. You'll see that your onCreate() differs from what I posted. – Kevin Coppock Jan 12 '15 at 05:41
  • I meant the stack trace. Switched those 2 lines, app stopped crashing. Checkbox state is saved. Can you explain why those 2 lines had to be flipped? – Jonathan Chiou Jan 12 '15 at 05:44
  • 1
    Ah, gotcha. Check [this answer](http://stackoverflow.com/a/23353174/321697) for a nice rundown of what you need to do. This should always be your first stop when your app crashes. As to why it crashed, `findViewById()` looks recursively through the layout (provided by the call to `setContentView()`) for a view with the given ID. Since you were looking for the CheckBox before actually setting the content view that *contains* the CheckBox, `findViewById()` will return `null`; this will cause a crash when attempting to call `setChecked()` on that null reference. – Kevin Coppock Jan 12 '15 at 05:48
0

Once the state data is stored using onSaveInstanceState(), the system uses onRestoreInstanceState(Bundle savedInstanceState) to recreate the state.

If you are using onSaveInstanceState() You have to override the function onRestoreInstanceState() in the activity or use the saved state in onCreate(). I think it's better to use onRestoreInstanceState() , which can reduce the code in onCreate(), because the onSavedInstanceSate() is called only when the system closes the app to make room for new applications to run. If you just want to save the checked state , use shared preference, no need of onSaveInstanceState(). //decalre in class

private  CheckBox cb;
private SharedPreferences preferences ;
private SharedPreferences.Editor editor;
private boolean CHECKED_STATE;
    @Override
    protected void onCreate(Bundle savedSettings) {
        super.onCreate(savedSettings);
        setContentView(R.layout.activity_settings);
        preferences = getApplicationContext().getSharedPreferences("PROJECT_NAME",                 android.content.Context.MODE_PRIVATE);
        editor = preferences.edit();
        CHECKED_STATE = preferences.getBoolean("check", false);
        cb = (CheckBox) findViewById(R.id.checkBox);
        cb.setChecked(CHECKED_STATE);
        cb.setOnCheckedChangeListener(new OnCheckedChangeListener(){
         @Override
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
          editor.putBoolean("check", isChecked);
          editor.commit();
         }
        });
    }

   this code saves the state on clicking the check box.

To make it save the state on Back Press , add the following to your activity.

@Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
  editor.putBoolean("check", cb.isChecked());
              editor.commit();
}

for more details on Save instance state please refer this link.

JIthin
  • 1,413
  • 1
  • 13
  • 29
  • I implemented onRestoreInstanceState() as you had given it, except I added in cb.setChecked(CHECK_SATTE) to set the check box to be checked. After running the app again, I ran into the same issue the box not being checked when I had checked it the last time I opened my settings menu. Hardcoded "TRUE" into cb.setChecked(), and the settings menu still does not seem to remember its previous state (it's always unchecked). What's going on? – Jonathan Chiou Jan 12 '15 at 03:46
  • I have made an edit.You are using preference to save a state , which is not recommended. – JIthin Jan 12 '15 at 04:01
  • Editted and put up updated code, problem still persists. – Jonathan Chiou Jan 12 '15 at 04:18
  • please check my answer again. You have to put the boolean value into the bundle ,not in preference. you should include the following line in onSaveInstanceState(). savedInstanceState.putBoolean("check",cb.isChecked() ); – JIthin Jan 12 '15 at 04:21
  • did that before I changed it back, and then re-changed back to savedInstanceState.putBoolean("check",cb.isChecked(). Nothing's happening. – Jonathan Chiou Jan 12 '15 at 04:26
  • If you are using onSaveInstanceState() You have to override the function onRestoreInstanceState() in the activity or use the saved state in onCreate(). I think it's better to use onRestoreInstanceState() , which can reduce the code in onCreate(), because the onSavedInstanceSate() is called only when the system closes the app to make room for new applications to run. If you just want to save the checked state , use shared preference, no need of onSaveInstanceState(). – JIthin Jan 12 '15 at 04:29
  • I think you need to save the state of the check box when the user closes or presses back button, not to save the state when the system itself closes he app. isn't it? – JIthin Jan 12 '15 at 04:31
  • if so there is no need of onSaveInstanceState() as it is called only when the system closes the app to make room for new applications to run.I believe it's not the current situation. – JIthin Jan 12 '15 at 04:32
  • Both OnSaveInstanceState() and onRestoreInstanceState() have always been overridden, moving the OnRestoreInstanceState() to onCreate() crashes the app, and I've already spent hours doing exactly the link you gave me in your main response before I posted here to no avail. – Jonathan Chiou Jan 12 '15 at 04:38
  • Yes, I do want information only to be saved when back or the done button is hit. How do I make it so that info is only saved on those 2 scenarios? – Jonathan Chiou Jan 12 '15 at 04:43