Wednesday, 5 October 2011

Android - Shared preferences

1. Introduction
Beside the database, in Android the another way to save permanently the data is using Shared preferences, which allows the programmer to save a set of basic type of data as key-value, which are:
  • Boolean
  • Float
  • Integer
  • Long
  • String
  • StringSet
2. Requirement
To use them, a variable of type SharedPreferences should be declared. There is also a variable of the class editor which is used to insert data in the file.

private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;

To instance the shared preferences, the method getSharedPreferences could used.

sharedPreferences = getSharedPreferences(name, mode);

This method has two parameters:
  • String name: The name of the file stored in the mobile device.
  • int mode: The mode used to store the data.
    • MODE_PRIVATE: The default mode, which only allow the access the application which has created it. This is the most usual one.
    • MODE_WORLD_READABLE: Allow other application to read the data.
    • MODE_WORLD_WRITEABLE: Allow other application to write the data on it.
    • MODE_MULTI_PROCESS: Set the mode how the file is loaded. Not recommended for beginners.
    • MODE_APPEND: Append the file if it already exists. Not recommended for beginners.
Once the shared preferences has been instantiated, his method edit() is used to instance the editor.

editor = sharedPreferences.edit();

3. Insert data into the Shared preferences
There are two steps to insert data into the file of the shared preferences file in the mobile device. The first step is insert the data into the editor and the second step is upload the data in the editor to the shared preference file. It is not necessary to do this second step for every time a new data is in the editor, only when the application want the new value be present in the shared preference file, but it is recommendable to commit for any modifications.
3.1 Insert the data to the editor
To insert data into the shared preferences, the method put+data type of the editor is used:
  • SharedPreferences.Editor putBoolean(String key, boolean value)
  • SharedPreferences.Editor putFloat(String key, float value)
  • SharedPreferences.Editor putInt(String key, int value)
  • SharedPreferences.Editor putLong(String key, long value)
  • SharedPreferences.Editor putString(String key, String value)
For example, for Long:

//Long
long newLong = 1000;
editor.putLong("newLong", newLong);
editor.commit();

Additionally there is a method called putStringSet(String key, Set<String>values) which has the API 11 (Android 3.0). At least you are completely sure that your application is going to run in a tablet and never in a phone, this method shouldn't be used.

3.2 Insert the data from the editor to the shared preference file
There are two methods to do it:
  • void apply()
  • boolean commit()
The main difference between then is the synchronisation. While the commit method is synchronous, the apply is not. Because of it and because apply only exists since API 9 (Android 2.3), it recommendable use the method commit always.

4. Retrieve value from the shared preferences
To get a data from the shared preferences, not editor is required. Instead, using the instance of Shared preference is enough.
  • boolean getBoolean(String key, boolean defValue)
  • float getFloat(String key, float defValue)
  • Int getInt(String key, int defValue)
  • Long getLong(String key, long defValue)
  • String getString(String key, String defValue)
All them have two parameters:
  • String key: The key used to identify the variable
  • object defValue: The value returned if the preference does not exit.
As I have explained in the section 3.1, is it possible to add a set of String in the Shared preference file. Analogically, there is a method to retrieve those set of keys, which also has the API level 11.
  • Set<String> getStringSet (String key, Set<String> defValues)
Additionally, there is a method called getAll which retrieve all the values in the shared preference:
  • Map<String, ?> getAll()

For example:
Map<String, ?> prefsMap = sharedPreferences.getAll();
for (Map.Entry<String, ?> entry: prefsMap.entrySet()) {
        Log.v("SharedPreferences", entry.getKey() + ":" + entry.getValue().toString());
}

This code will print all the values in the shared preferences.

5. Remove values
There are two method used to remove the values from the editor:
  • SharedPreferences.Editor remove(String key)
  • SharedPreferences.Editor clear()
The first method remove a specific value in the shared preferences and the second method remove all the values in the shared preferences.

Be aware that the method commit() should be called after those methods in order to upload the modifications to the shared preferences file.

A very important thing to know is the clear() methods has more preferences than any other put method and it will be the first one to be executed when commit() method is called. This means, between two commits, if there is any clear method, it will be called first, then all the put method will be called.

For example:
//Long
long newLong = 1000;
editor.putLong("newLong", newLong);
editor.commit();
        
//String
String newString = "This is a string";
editor.putString("newString", newString);
editor.clear();
editor.commit();

This code will save the "newLong" in the shared preference, then it will be cleaned. After it, the "newString" will be added to the shared preference. The final result is in the shared preferences, there will be only one value which has the key "newString".

6. Listen to the shared preferences
Because shared preferences could be changed by different applications if right permission has been set, is it possible to set a listener to it to know when some value has changed.
  • void registerOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener)
  • void unregisterOnSharedPreferenceChangeListener(SharedPreferences.OnSharedPreferenceChangeListener listener)
An example given by StackOverFlow:
// Use instance field for listener
// It will not be gc'd as long as this instance is kept referenced
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        //Implementation
    }
});

sharedPreferences.registerOnSharedPreferenceChangeListener(listener);

This listener should be unregistered when the application is going to be destroyed:
@Override
protected void onDestroy() {
    super.onDestroy();
    sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
}

7. Other considerations
7.1 Other methods
There is a useful method which hasn't been mentioned:
  • contains(String key)
This method, which belong to the class SharedPreferences, is used to check if there is any value with a specific key.

7.2 Accessing the physical file
The shared preferences are saved in a xml file in the mobile device. It is located in the folder:
  • /data/data/yourPackageName/shared_prefs
and it can be opened with any text program, for example "less".

8. Conclusion
The shared preference is the best way to save the settings in the permanently way in the mobile device. If it is used frequently, my personal recommendation is utilize a specific class which for each variable, create a pair of public method set and get, then utilize the class as a normal java class. This way can make the use of shared preferences much more simple.

For more information:
Android developers - SharedPreferences.Editor: 

1 comment: