0

I've been poking around the web (including SO), and have found lots of information on having persistent data. I've found strings, ints, doubles, calendars, just about everything. The ones I haven't seen a specific guide or tutorial for are booleans.

I've created an app which has a switch located on the main activity. I do not have a settings button, window, or even a pane, because the entire app is accessed from the main activity. I want to have the switch be persistent as well as the affects it holds (ie, when the app is closed, it will remember if the user disable or enable the vibrate function).

I have the switch to work where it does enable the vibration depending on which position the switch is in. I can't seem to get the switch to remain in the off position when the app is recreated.

Here's my code to save:

@Override
protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    setContentView(R.layout.activity_main);
    dBell = MediaPlayer.create(this, R.raw.doorbell);
    if ((bundle != null) && (bundle.getBoolean("vibetoggle") != false)) {
        vibeOn = false;
    } else {
        vibeOn = true;
    }

}

protected void onRestoreInstanceState(Bundle bundle) {
    super.onRestoreInstanceState(bundle);
    vibeOn = bundle.getBoolean("vibetoggle");
}

protected void onSaveInstanceState(Bundle bundle) {
    super.onSaveInstanceState(bundle);
    bundle.putBoolean("vibetoggle", vibeOn);
}

public void onToggleClicked(View view) {
    Vibrator vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
    vibeOn = ((Switch) view).isChecked();
    if (vibeOn) {
        vibe.vibrate(100);
    } else {
        // No vibrate
    }
}

public void playSound(View view) {
    dBell.start();
    if (vibeOn) {
        Vibrator vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        vibe.vibrate(300);
    } else {
        // No vibrate
    }
}

The shorter duration vibrate (100ms) is occurs when the switch is flipped from disabled to enabled. The longer one is what actually causes the button to vibrate when clicked.

I've kind of gotten the boolean logic to work, but the IO switch would still be set to default and wouldn't function correctly until it had been switched. The issue I have regarding the switch, is that I want the switch to be in the correct position when loaded (ie, if the boolean is saved false, then the switch will load in the off position). I can't figure out how to make the two communicate. I would assume the switch would have to change based on the boolean, rather than the other way around. I just can't figure out how to make the xml switch communicate with the one I have in java and visa versa.

Here's the xml code for the switch:

<Switch
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Vibration"
    android:id="@+id/switch1"
    android:layout_alignBottom="@+id/dBellButton"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:clickable="true"
    android:checked="true"
    android:onClick="onToggleClicked" />

I know the android:checked="true" causes the switch to be created in a default on position. I tried making a new boolean inside of the values xml (so rather than the code saying android:checked="true", it would say something along the lines of android:checked="@bool/vibeConvert), but found I didn't know how to edit the boolean through the java when it was there as well.

I've tried a few different methods to get this data to be persistent, but none of them worked for me. If I could get some help with persistent data, specifically regarding booleans, that would be fantastic.

EDIT: showing my attempt to use SharedPreferences.

protected void onRestoreInstanceState(Bundle bundle) {
    super.onRestoreInstanceState(bundle);
    vibeOn = bundle.getBoolean("vibetoggle");
//        preferenceSettings = getPreferences(PREFERENCE_MODE_PRIVATE);
//        vibeOn = preferenceSettings.getBoolean("on", true);
}

protected void onSaveInstanceState(Bundle bundle) {
    super.onSaveInstanceState(bundle);
    bundle.putBoolean("vibetoggle", vibeOn);
//        preferenceSettings = getPreferences(PREFERENCE_MODE_PRIVATE);
//        preferenceEditor = preferenceSettings.edit();
//        preferenceEditor.putBoolean("on", vibeOn);
//        preferenceEditor.apply();
}

I'm not quite sure how how to use the SharedPreferences, and I couldn't find anywhere which specified where to place them. They are commented out here for obvious reasons. Not sure where to go from here.

Thanks!

Nathan

EDIT:

I tried using the following code:

public static final String PREFS_NAME = "MyPrefsFile";
MediaPlayer dBell;
boolean vibeOn;

@Override
protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    setContentView(R.layout.activity_main);
    dBell = MediaPlayer.create(this, R.raw.doorbell);

    // Restore preferences
    SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
    boolean vibeSave = settings.getBoolean("vibeSave", vibeOn);
    vibeOn = vibeSave;
    Switch ("+id/switch1") = vibeSave;
}

@Override
protected void onStop() {
    super.onStop();

    // Let Editor make preference changes
    // All objects are from android.context.Context
    SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
    SharedPreferences.Editor editor = settings.edit();
    editor.putBoolean("vibeSave", vibeOn);
    editor.commit();
}

Here's my XML:

<Switch
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Vibration"
    android:id="@+id/switch1"
    android:layout_alignBottom="@+id/dBellButton"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:clickable="true"
    android:checked="true"
    android:onClick="onToggleClicked" />

I'm not sure if:

  1. The boolean value is being saved.

  2. The switch can be edited inside of the java code.

I've tried to play with the idea with the following line of code: Switch ("+id/switch1") = vibeSave;, but that didn't work. I'm not sure how to proceed from here. I want my XML to be able to start in the correct position based on the value in the boolean, but I'm not sure how to make my XML and my java talk to each other.

Nathan Lundgren
  • 79
  • 3
  • 14

1 Answers1

0

You can use SharedPreferences to store primitive values.

The best place to do this, is right after the value is changed.

So add the saving to the logic of your switch listener, and the loading to the logic of your switch initializer.

To get a SharedPreferences object for your application, use one of two methods:

getSharedPreferences() - Use this if you need multiple preferences files identified by name, which you specify with the first parameter.

getPreferences() - Use this if you need only one preferences file for your Activity. Because this will be the only preferences file for your Activity, you don't supply a name.

To write values:

Call edit() to get a SharedPreferences.Editor.

Add values with methods such as putBoolean() and putString().

Commit the new values with commit()

To read values, use SharedPreferences methods such as getBoolean() and getString().

The code in your onCreate should look something like this:

@Override
protected void onCreate(Bundle bundle) {
    (...)
    SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
    boolean vibeSave = settings.getBoolean("vibeSave", false);
    Switch switch = (Switch) findViewById(R.id.switch1);
    switch.setChecked(vibeSave);
}
Community
  • 1
  • 1
wvdz
  • 16,251
  • 4
  • 53
  • 90
  • I'm not quite sure of where to place these SharedPreference objects. I had tried them before, and I can link them to show what I used. I had tried them before I posted this, but couldn't manage to get them working... I'll add what I did and where I put them to the original post. – Nathan Lundgren Apr 11 '15 at 15:34
  • I don't understand what you mean with where to place them. You can just retrieve the SharedPreferences editor from your Context (Activity extends Context) and store or retrieve values from it. Plenty examples to be found online, like here: http://stackoverflow.com/a/23024962/2947592 – wvdz Apr 11 '15 at 16:10
  • Okay, now I see your problem. You except the value to be automatically in your savedInstanceState, but you need to do some work for this. If you want to make the value persistent over multiple application life cycles, you don't have to do anything with the savedInstanceState. Just use the sharedPreferences in the listener of your switch to save the value immediately after it is set, and in the initialization logic of the switch to set it to the saved value. – wvdz Apr 11 '15 at 16:16
  • So, I used the link you attached, and one inside of that page. Long story short, I used this URL: http://developer.android.com/guide/topics/data/data-storage.html#pref . But, when I implemented the suggestions and the example they have there, it still didn't work. I'm not sure if the data is saving properly. I'm also unsure if the changes aren't showing because of my switch in XML. I don't know how to make sure the XML is being altered. I'll link my XML code to the end of my original post. As well as my new onCreate() and onStop(). Do I need to add the edit command into the onToggleClicked()? – Nathan Lundgren Apr 13 '15 at 23:57
  • Okay, so I got the boolean value to persist. That's done now. All that's left is for my switch to be able to be created in the off position when it's created if that's what the boolean wants. I'm not sure how to do this. My switch is created in my XML and I'm unsure how to make it change based on a boolean in my java. Halp! – Nathan Lundgren Apr 14 '15 at 00:26
  • @NathanLundgren use findViewById(R.id.your_switch_id) in your activity, after inflating the xml. You can cast this view to `Switch` and then do any manipulation on it that you want. I edited some example code in my answer. – wvdz Apr 14 '15 at 09:58