Home > Articles > Programming > Java

  • Print
  • + Share This
This chapter is from the book

Saving User Preferences

Because an activity’s state is not saved automatically during its lifecycle, you need to save user preferences so that you can redisplay an activity in the correct state. Let’s see how to do that.

Creating a New Activity

Applications often consist of more than one activity. Let’s create a new Settings activity to enable and disable vibration and create the best possible experience for the user.

  1. Create a new activity called activity_settings via the Android New Activity wizard. Select BlankActivity as the template, Settings as the activity name, and activity_settings as the layout file. Type Settings as the title.
  2. Open the activity_settings file. Change the RelativeLayout to a LinearLayout with a vertical orientation:

    <LinearLayout xmlns:android=http://schemas.android.com/apk/res/android
        xmlns:tools=http://schemas.android.com/tools
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
  3. Add a new checkbox view inside the linear layout. Give it a new id of vibrate_check, and set the layout_width and layout_height to wrap_content. Set a resource text to the value @string/vibrate_checkbox:
    <CheckBox
        android:id="@+id/vibrate_checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/vibrate_checkbox" />
  4. Add the new resource string vibrate_checkbox to the strings.xml file:

        <string name="vibrate_checkbox">Vibrate</string>

Showing a New Activity

To show a new activity, you first need to create an intent. Intents, in their simplest form, are a description of an activity that you want to occur. (You can also start activities in other applications, as covered later in the book.)

Next, you’ll create a new intent to display the Settings activity.

  1. Open the activity_timer layout. To launch the new activity, add a new button to the linear layout. Give the button an ID of settings_button, and a click handler to call the method clickedSettings when the button is pressed:

    <Button
        android:id="@+id/settings_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="@string/settings_button"
        android:onClick="clickedSettings" />
  2. Add the new resource string for the Settings button:

    <string name="settings_button">Settings</string>
  3. In the TimerActivity.java file, add a new clickedSettings method:

    public void clickedSettings(View view) {
        Log.d(CLASS_NAME, "clickedSettings");
    }
  4. Debug the application, and check that the clickedSettings call is logged in the LogCat view. If an RTE occurs, double-check that the onClick contains exactly the same method name as the new method just added.
  5. In the clickedSettings method, create a new Intent. Then pass the application context and the class property of the SettingsActivity. Run Quick fix to add the import statement for the Intent class:

    Intent settingsIntent = new Intent(getApplicationContext(),
        SettingsActivity.class);
  6. Display the new activity by calling startActivity, passing the intent you just created:

    startActivity(settingsIntent);
  7. Run the application again, and click the Settings button. The setting activity (displaying a checkbox) with a single checkbox will replace the timer activity, as shown in Figure 4.9.

    Figure 4.9

    Figure 4.9 The new Settings activity

Saving an Application’s State

Application state can be stored in many ways, either as static properties stored globally in the application or through the use of the singleton pattern. This pattern is designed to control object creation, limiting the number of objects to one. Because there is only ever one instance of the application class, you can use that to act as a singleton.

Here’s how to create a class to save and retrieve the application settings.

  1. Create a new Java class called Settings. Add a private static (of type String) CLASS_NAME, and assign the class name in the class constructor:

    public class Settings {
        private static String CLASS_NAME;
    
        public Settings() {
            CLASS_NAME = getClass().getName();
        }
    }
  2. Create a private property to store whether or not the vibrate setting is turned on:

    protected boolean vibrateOn;
  3. Create a method to return this property. Run Quick fix to import the Log class:

    public boolean isVibrateOn() {
        Log.d(CLASS_NAME, "isVibrateOn");
        return vibrateOn;
    }
  4. Create a method to set the value of the property:

    public void setVibrate(boolean vibrate) {
        Log.d(CLASS_NAME, "setVibrate");
        vibrateOn = vibrate;
    }
  5. Create a new class called OnYourBike that extends Application. Add a settings property of type Settings to this class:

    public class OnYourBike extends Application {
        protected Settings settings;
    }
  6. Add a method named getSettings that creates an instance of Settings if it hasn’t already been created, and return the settings property:

    public Settings getSettings() {
        if (settings == null) {
            settings = new Settings();
        }
        return settings;
    }
  7. Add a method named setSettings that changes the settings property to the settings value passed in:

    public void setSettings(Settings settings) {
        this.settings = settings;
    }
  8. Change the Android manifest file so that the application uses this class as its application by setting the android:name attribute to ".OnYourBike":

    <application android:name=".OnYourBike"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
  9. Open SettingActivity.java, and add a vibrate checkbox property. Run Quick fix to import the CheckBox class:

    private CheckBox vibrate;
  10. In the onCreate method, after the call to setContentView, obtain access to the checkbox by calling findViewById:

    vibrate = (CheckBox)
        findViewById(R.id.vibrate_checkbox);
  11. Obtain the settings by calling the getSettings method just created:

    Settings settings = ((OnYourBike)getApplication()).getSettings();
  12. Just after that, set the state of the checkbox according to the setting:

    vibrate.setChecked(settings.isVibrateOn());
  13. Override the onStop method to save the settings:

    @Override
    public void onStop() {
        super.onStop();
        Settings settings = ((OnYourBike) getApplication()).getSettings();
        settings.setVibrate(vibrate.isChecked());
    }
    
  14. Run the application, click the Settings button, change the settings checkbox, and press the back button. Go back into the setting activity again by clicking the Settings button. The vibrate checkbox should still be ticked.

Notice that there was no need to add a handler to the checkbox for the state to be saved when the activity was stopped. Depending on how the activity is used in your application, you may want to save the setting right away rather than wait until the activity is stopped.

Using Shared Preferences

The settings class you created saves the application’s state only while it is running. If the application is stopped and restarted, it won’t remember the previous state. To fix that, you need to use shared preferences to save the application’s state. Shared preferences allow you to save key value pairs on a device.

You can save the vibration setting—whether it’s turned on or off—as a preference:

  1. Open Settings.java, and add a private static string called VIBRATE:

    private static String VIBRATE = "vibrate";
  2. In the isVibrateOn method, obtain an instance of shared preferences by calling activity.getPreferences:

    SharedPreferences preferences
         = activity.getPreferences(Activity.MODE_PRIVATE);

    Run Quick fix to import the SharedPreferences and Activity classes.

  3. Check whether the VIBRATE keys exist, and, if they do, set vibrateOn to be the saved value:

    if (preferences.contains(VIBRATE)) {
        vibrateOn = preferences.getBoolean(VIBRATE, false);
    }
  4. Change the isVibrateOn method to take a single parameter of type Activity:

    public boolean isVibrateOn(Activity activity)
  5. In the setVibrate method, after the existing code, save the vibrate property by getting access to the shared preferences, creating an editor, saving the property by calling putBoolean, and committing the changes by calling apply:

    SharedPreferences preferences
         = activity.getPreferences(Activity.MODE_PRIVATE);
    Editor editor = preferences.edit();
    editor.putBoolean(VIBRATE, vibrate);
    editor.apply();

    Run Quick fix to import the Editor class.

  6. Change the setVibrate method to take an additional parameter of type Activity:

    public void setVibrate(Activity activity, boolean vibrate)
  7. Open SettingsActivity.java, and fix the two errors by passing this to the isVibrateOn and setVibrate methods:

    vibrate.setChecked(settings.isVibrateOn(this));
    settings.setVibrate(this, vibrate.isChecked());
  8. Run the application, click Settings, check the vibrate checkbox, and press the back button. Click Menu, and select all apps. Select your application, and click force stop. Run the application again, and click the Settings button. The vibrate checkbox should still be checked.
  • + Share This
  • 🔖 Save To Your Account