Sunday, 14 June 2015

Using Shared Preferences in your Android Application

Shared Preferences

Shared preferences are like sessions (if you can relate to sessions running in your browser). For eg. when you are shopping on a site like Amazon or Flipkart you don't have to login to browse each item, do you? That's because you are in a session and the session data is stored in cookies in your browser. It will get invalidated when you logout or when the time expires. Shared preferences in Android are something like that. You can save or persist your settings across activities when user navigates across them. One major difference from sessions though is that sessions expire where as shared preference is a persistence storage. We will shortly see the code for it.

NOTE : Shared preference is a persistence storage.

When to use shared preferences?

If you have a relatively small collection of key-values that you'd like to save, you should use the SharedPreferences APIs. A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them. Each SharedPreferences file is managed by the framework and can be private or shared. (Source)

Goal

Lets set our goal first before we begin to write code. We are going to store setting in shared preference which will be used to play music or sound. So User can choose whether he wants to listen to the music or not.

Getting Started with using PreferenceActivity

Lets write our own class that extends PreferenceActivity

public class MyPreferenceActivity extends PreferenceActivity {
    
    private static final String OPT_MUSIC = "music";
    private static final Boolean OPT_SOUND_DEF = true; //default value of the setting

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.settings);
    }
    
    public static boolean getSound(Context context) {
        return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(OPT_MUSIC, OPT_SOUND_DEF);
    }
}

Note : Notice the getSound() method that returns the boolean ? We will use that to see what setting is currently set. Also note it is static so we can directly call it using the class name. Note the use of PreferenceManager here and how we supply the default value (true in this case).

Loading Settings


As you can see above piece of code gets settings from an xml file named "settings". Inside folder res/xml  create a file named settings.xml and populate it with following content - 

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <CheckBoxPreference
        android:defaultValue="true"
        android:key="sound"
        android:summary="@string/music_setting_summary"
        android:title="@string/music_setting_title" />

</PreferenceScreen>

In above xml I am showing a simple check box preference. It will be as simple as user checking and unchecking the checkbox to enable/disable music.

Displaying Settings

Now that we have coded for the music setting lets create a workflow to show it to the user. You can put in anywhere. For simplicity I am assuming it is one of the options in the options menu. Lets call it Settings (see 3rd option in below screenshot).



Now on click of it we should open the shared preference intent that we have created above. Code to do that is as follows - 

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
        case R.id.settings:
            Log.i(TAG, "Showing Preference Activity");
            startActivity(new Intent(this, MyPreferenceActivity .class));
            break;
        }
        return true;
    } 

Now on click you should see another activity with a checkbox to enable/disable sound/music (Like below).






Obeying the Setting

That's the code to create and display the setting but we also need to obey our music playing logic according to this setting. So lets go ahead and see how that works.



        if(MyPreferenceActivity .getSound(context)) {
            try {
                final ToneGenerator tg = new ToneGenerator(
                        AudioManager.STREAM_NOTIFICATION, 100);
                tg.startTone(ToneGenerator.TONE_PROP_BEEP);
            } catch (Exception ex) {
                Log.e(TAG, "Could not play notification sound", ex);
            }
        }

What above code does is very simply. Get the sound setting and if it is enabled then play a beep tone else don't. You can easily inject this code in some View's onclicklistener.

Last but not the least

Lastly don't forget to list your preference activity in your applications manifest file :)

        <activity
            android:name=".MyPreferenceActivity "
            android:label="@string/title_activity_prefs" >
        </activity> 


Using shared preferences without PreferenceActivity

Yes you can simply use shared preferences without Preference activity as well. Refer to following syntax.

Setting value in Preference : 

SharedPreferences.Editor editor = getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE).edit();

editor.putBoolean("music", true);

editor.putString("someStringSetting", "StringSettingValue");

editor.putInt("someIntSetting", 1);

editor.commit();

Retrieving Value from preference :

SharedPreferences prefs = getSharedPreferences(PREFERENCE_NAME, MODE_PRIVATE); 

boolean musicPref = prefs.getBoolean("music", true);

String stringSetting = prefs.getString("someStringSetting", "StringSettingFefaultValue");

String intSetting = prefs.getString("someIntSetting", 1);


NOTE : You can only store primitive type of data like String, integer, boolean etc. You cannot store your custom Objects. To Store your object instances you can convert them in json string (serialize) and then store it. While retrieving convert json string to your object (deserialize) and use it.

Related Links

t> UA-39527780-1 back to top