Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens to the existing data of Android user preferences when preferences structure changes in a new version?

For example, if a few entries of preferences are added or deleted, how does Android handle the existing preference data when the app is updated with the new preferences structure?

I am sorry for this rudimentary question, but my diligent search and reading could not find the answer.

like image 651
Hong Avatar asked Dec 29 '12 15:12

Hong


People also ask

What is the importance of shared preferences in developing Android applications?

Android provides many ways of storing data of an application. One of this way is called Shared Preferences. Shared Preferences allow you to save and retrieve data in the form of key,value pair.

What is preference data in Android?

Shared Preferences is the way in which one can store and retrieve small amounts of primitive data as key/value pairs to a file on the device storage such as String, int, float, Boolean that make up your preferences in an XML file inside the app on the device storage.

Where shared preferences are stored in Android device?

Android Shared Preferences Overview Android stores Shared Preferences settings as XML file in shared_prefs folder under DATA/data/{application package} directory. The DATA folder can be obtained by calling Environment.

How we can save and load user preferences in Android?

Android provides the SharedPreferences object to help you save simple application data. Using the SharedPreferences object, you can save the data you want through the use of key/value pairs — specify a key for the data you want to save, and then both it and its value will be saved automatically to an XML file.


2 Answers

The shared preferences are stored in the xml file in the folder data/data/your.application.package/shared_prefs/. The file is called your.application.package_preferences.xml;

When you retrieve the shared preferences, you call the Context.getSharedPreferences method. It creates the SharedReferences object and invokes the SharedReferences.startLoadFromDisk method.

If you open this method, you will see that the xml file with preferences (mFile) is parsed and preferences are loaded into the memory storage (map).

BufferedInputStream str = new BufferedInputStream(new FileInputStream(mFile), 16*1024);
map = XmlUtils.readMapXml(str);

From then you will always read your preferences from the memory. More exactly from the private Map<String, Object> mMap variable. Also the application can call the startReloadIfChangedUnexpectedly method and if the underlying file has been changed, it will be parsed and a new HashMap will be created.

As to your question, there are the following cases:

  1. You added a preference item in a new version. Then the default value specified as the second parameter will be returned. Note: the attribute android:defaultValue is not used, so be aware.

    String v = (String)mMap.get(key); // not found => v = null

    return v != null ? v : defValue; // return defValue

  2. You removed a preference item in a new version. The xml file and map object will contain some redundant data, but it will be fixed when the user saves preferences next time.

  3. You changed the key of a preference item to some key which wasn't used. Then the default value will be returned. The same result as p.1.

  4. You removed one preference item (with the key pref1_key, for example) and changed the key of another item so that it refers to the first item (from pref2_key to pref1_key). Then the second preference item will have the value of the first item.

  5. You changed a type of a preference item (from boolean to int, for example). Then it will throw the CastException because of this and similar code: (Integer)mMap.get(key);. But you can change, for example, EditTextPreference to ListPreference, because they both have the String type.

Maybe there are some more test cases, but so far I've made up only 5.

Also here is the example of the preferences file with ListPreference, EditTextPreference and CheckBoxPreference:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="pref_theme_key">THEME_LIGHT</string>
    <string name="pref_homepage_key">test</string>
    <boolean name="pref_display_name_key" value="true" />
</map>
like image 174
vortexwolf Avatar answered Oct 19 '22 14:10

vortexwolf


how does Android handle the existing preference data when the app is updated with the new preferences structure?

It is unclear what you mean by "preferences structure".

You can think of a SharedPreferences as being a persistent HashMap. You store various values under various keys, and you can get them back later. Android has no a priori knowledge of the keys or the types of values that will be stored under those keys, until you actually store something.

My guess is that by "preference structure", you mean "preference screen definitions in XML". In that case:

  • if you add new preferences, Android will handle those normally, just as if the preferences has been around all along but the user had never set those preferences before

  • if you remove preferences that you had used before, the old data remains, unless you elect to get rid of it, as Android has no way to know that you will never use that data again

  • if you re-key a preference (i.e., replace keyA with key1 for what logically is the same preference), Android will treat key1 as a totally new preference, and so you will need to put smarts in your code somewhere to update your SharedPreferences data to reflect the key change, if you so choose

There is no SharedPreferencesOpenHelper equivalent of SQLiteOpenHelper to manage preference "schema versions" and help you migrate data. You are welcome to create such a system, if you so choose, if you feel that it will help you manage frequently-changing "preference structure".

like image 26
CommonsWare Avatar answered Oct 19 '22 13:10

CommonsWare