{"id":1820,"date":"2014-10-27T14:45:06","date_gmt":"2014-10-27T09:15:06","guid":{"rendered":"http:\/\/codetheory.in\/?p=1820"},"modified":"2014-10-27T16:31:12","modified_gmt":"2014-10-27T11:01:12","slug":"android-application-data-storage-sharedpreferences","status":"publish","type":"post","link":"https:\/\/codetheory.in\/android-application-data-storage-sharedpreferences\/","title":{"rendered":"Android Application Data Storage With SharedPreferences"},"content":{"rendered":"
Android has a concept of shared preferences using which application preferences data can be stored persistently. That means the data or state won’t be lost until the application is uninstalled. The preferences data can be stored as key\/value pairs and are available across all the Activities of the given application or can also be restricted to a particular Activity.<\/p>\n
<\/p>\n
Using the SharedPreferences<\/a> interface implementations we can store persistent sets of data in the filesystem. The data will be available across application restarts or even device stop\/start. Consider it as a small cave to hold your app’s data mostly related to settings and user preferences. Anything that is slightly more complicated like relational data should still go into the sqlite database or media files into the filesystem.<\/p>\n SharedPreferences can be used to store any (and only) primitive data types – booleans, floats, ints, longs and strings – that’ll persist across user sessions (user closes the app and re-opens it). To determine what type of data to store, just think of anything that might require caching for quick usage like username, logged in state, email, high score or level in a game, gender (or other profile info), app-related settings, etc.<\/p>\n Shared Preferences can be stored at 2 levels – activity or application. To get a SharedPreferences object for your activity or application in order to start storing, retrieving and updating data there are two methods:<\/p>\n Here’s how the first one is used:<\/p>\n You can store as many shared preferences as you want for your application and all of them will keep on getting saved in the XML file named <\/p>\n The image shows my app specific data (including shared preferences) in DDMS. com.pycitup.pyc is my application’s package name.<\/p>\n In case you don’t want to provide a name for app-wide shared preferences then we can use The activity-level method version has to be used like this:<\/p>\n This version will save its data in If you notice we passed an option called Now let’s go through how to write and read preferences.<\/p>\n Once you’ve decided whether you want application preferences or activity one, then you’ll start storing data into it. Once you’ve a valid Let’s try storing some values:<\/p>\n We stored 2 key-value pairs. This is how our Notice we had to use the Updating the preferences is similar to the setting them that we just learnt a bit back. Get the SharedPreferences.Editor object, set values using the Same code but different values. The new XML contents looks like this:<\/p>\n Fetching the preferences is done directly on the The code logged Deleting a particular preference is super simple. Just call the You can also We can listen to changes in the preferences by passing a The You can always check if a particular preference exists (is set) or not using the We can write a set of Strings to our preferences using the Here’s the XML representation (contents):<\/p>\n Using You might be wondering when to use this data storage option. A few cases that I can think off the bat are:<\/p>\n When building a full-fledged settings\/preferences section for the user in your app (somewhat similar to the Android’s Settings app), instead of building the user interface with your own custom View objects and then wiring up the functionality by writing some backend logic in the Activity class, we can use The comprehensive Android settings guide<\/a> has all the information with regards to this.<\/p>\n So we explored the SharedPreferences data storage option which eases some sort of caching by storing super simple and quick key\/value pairs (in XML files behind the scenes). Remember for more complicated data like relational data or files there are other options like saving in sqlite or the filesystem.<\/p>\n","protected":false},"excerpt":{"rendered":" Android has a concept of shared preferences using which application preferences data can be stored persistently. That means the data or state won’t be lost until the application is uninstalled. The preferences data can be stored as key\/value pairs and are available across all the Activities of the given application or can also be restricted … Continue reading “Android Application Data Storage With SharedPreferences”<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[121],"tags":[105,133,89,132],"_links":{"self":[{"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/posts\/1820"}],"collection":[{"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/comments?post=1820"}],"version-history":[{"count":9,"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/posts\/1820\/revisions"}],"predecessor-version":[{"id":1823,"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/posts\/1820\/revisions\/1823"}],"wp:attachment":[{"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/media?parent=1820"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/categories?post=1820"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codetheory.in\/wp-json\/wp\/v2\/tags?post=1820"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}\n
getSharedPreferences()<\/code><\/a> – Application-wide preferences file identified by the name passed to it as the first argument.<\/li>\n
getPreferences()<\/code><\/a> – Activity-level preferences object where no name is specified as there will be only one file for an Activity.<\/li>\n<\/ul>\n
\r\nSharedPreferences pref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);\r\n<\/pre>\n
MyPrefs<\/code> which is usually located at
\/data\/data\/[package name]\/shared_prefs\/MyPrefs.xml<\/code>. You can browse that in the File Explorer in the DDMS<\/a> view or if your device is rooted then go ahead and explore it in
$ adb shell<\/code>.<\/p>\n
PackageManager.getDefaultSharedPreferences()<\/code><\/a> (not included in the list of methods above) which uses a default name behind the scenes which is a concatenation of the package name and the string _preferences<\/em>. Hence the file path will be something like
\/data\/data\/com.package.name\/shared_prefs\/com.package.name_preferences.xml<\/code>. This is how you use it:<\/p>\n
\r\nSharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);\r\n<\/pre>\n
\r\nSharedPreferences pref = getPreferences(Context.MODE_PRIVATE);\r\n<\/pre>\n
\/data\/data\/[package name]\/shared_prefs\/[Activity Name].xml<\/code>.<\/p>\n
Context.MODE_PRIVATE<\/code> (can also pass just
MODE_PRIVATE<\/code> if in an activity or the integer
0<\/code>) which basically means that the created shared preferences file will be accessible by the calling application only.<\/p>\n
Storing Preferences<\/h3>\n
SharedPreferences<\/code> object you call
edit()<\/code> method on it to fetch a
SharedPreferences.Editor<\/code><\/a> object whose public method will allow us to start writing data to the file. To store primitive data it has various methods like
putBoolean()<\/code>,
putFloat()<\/code>,
putInt()<\/code>,
putLong()<\/code> and
putString()<\/code>.<\/p>\n
\r\nSharedPreferences pref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);\r\n\r\n\/\/ We need an editor object to make changes\r\nSharedPreferences.Editor edit = pref.edit();\r\n\r\n\/\/ Set\/Store data\r\nedit.putString("username", "Rishabh");\r\nedit.putBoolean("logged_in", true);\r\n\r\n\/\/ Commit the changes\r\nedit.commit();\r\n<\/pre>\n
\/data\/data\/[package name]\/shared_prefs\/MyPrefs.xml<\/code> should look like now:<\/p>\n
\r\n<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\r\n<map>\r\n <string name="username">Rishabh<\/string>\r\n <boolean name="logged_in" value="true" \/>\r\n<\/map>\r\n<\/pre>\n
commit()<\/code><\/a> method to commit our changes. There’s another method to do the same which is
apply()<\/code><\/a> but that is asynchronous and won’t report failures.<\/p>\n
Updating Preferences<\/h3>\n
put*()<\/code> methods and then commit your changes.<\/p>\n
\r\nSharedPreferences pref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);\r\n\r\n\/\/ We need an editor object to make changes\r\nSharedPreferences.Editor edit = pref.edit();\r\n\r\n\/\/ Set\/Store data\r\nedit.putString("username", "CodeTheory");\r\nedit.putBoolean("logged_in", false);\r\n\r\n\/\/ Commit the changes\r\nedit.commit();\r\n<\/pre>\n
\r\n<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\r\n<map>\r\n <boolean name="logged_in" value="false" \/>\r\n <string name="username">CodeTheory<\/string>\r\n<\/map>\r\n<\/pre>\n
Retrieving Preferences<\/h3>\n
SharedPreferences<\/code> object. So
SharedPreferences.Editor<\/code> is not required. There are several `get` methods for this job like
getBoolean()<\/code>,
getFloat()<\/code>,
getInt()<\/code>,
getLong()<\/code> and
getString()<\/code>. All of them accept two arguments where the first is the name of the key while the second non-optional one is the default value to return if the preference does not exists (is undefined).<\/p>\n
\r\nSharedPreferences pref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);\r\n\r\nString username = pref.getString("username", "");\r\nboolean logged_in = String.valueOf(pref.getBoolean("logged_in", false);\r\n\r\nLog.d(TAG, username);\r\nLog.d(TAG, String.valueOf(logged_in));\r\n<\/pre>\n
CodeTheory<\/code> and
false<\/code> in separate lines.<\/p>\n
Deleting Preferences<\/h3>\n
remove()<\/code><\/a> method and commit your changes.<\/p>\n
\r\n\/\/ Remove a particular key\r\npref.remove("username");\r\n\r\n\/\/ Commit changes\r\npref.commit();\r\n<\/pre>\n
clear()<\/code><\/a> the entire remaining preferences from your storage.<\/p>\n
Preferences Listener<\/h3>\n
SharedPreferences.OnSharedPreferenceChangeListener<\/code><\/a> listener to
registerOnSharedPreferenceChangeListener<\/code><\/a>. Here’s how to do that:<\/p>\n
\r\nSharedPreferences pref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);\r\n\r\npref.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {\r\n @Override\r\n public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {\r\n Log.d(TAG, "The key '" + key + "' was changed");\r\n }\r\n});\r\n\r\n\/\/ Any further code that modifies, add, removes a key will call onSharedPreferenceChanged method\r\n<\/pre>\n
onSharedPreferenceChanged()<\/code> method will be called whenever a particular key is added, changed or removed. Note: At times if this code doesn’t work then try saving the
OnSharedPreferenceChangeListener<\/code> object into a variable or an instance member to hold a reference to it. This SO answer<\/a> explains it all.<\/p>\n
Bonus<\/h3>\n
contains()<\/code><\/a> method on the SharedPreferences object like this:<\/p>\n
\r\nboolean exists = pref.contains("username"); \/\/ true\r\n<\/pre>\n
putStringSet()<\/code><\/a> method. This is how we can do it:<\/p>\n
\r\nSharedPreferences pref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);\r\n\r\n\/\/ We need an editor object to make changes\r\nSharedPreferences.Editor edit = pref.edit();\r\n\r\n\/\/ Set\/Store data\r\nHashSet<String> set = new HashSet<String>();\r\nset.add("Rich Dad Poor DaD");\r\nset.add("The Cold Steel");\r\nset.add("Steve Jobs Biography");\r\nedit.putStringSet("books", set);\r\n\r\n\/\/ Commit the changes\r\nedit.commit();\r\n<\/pre>\n
\r\n<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\r\n<map>\r\n <set name="books">\r\n <string>Steve Jobs Biography<\/string>\r\n <string>The Cold Steel<\/string>\r\n <string>Rich Dad Poor DaD<\/string>\r\n <\/set>\r\n<\/map>\r\n<\/pre>\n
getStringSet()<\/code><\/a> you can get the
Set<\/code> data back.<\/p>\n
Usage<\/h3>\n
\n
Android Preference APIs\/Objects<\/h2>\n
Preference<\/code><\/a> objects in conjunction with
PreferenceActivity<\/code><\/a> to quickly build the user interface. Along with that the other major advantage of this approach is that, saving preferences is done behind the scenes using SharedPreferences and the integration of the UI with the updated value to set the correct state of various controls (checkbox for example) is also handled automatically. Apart from that this entire framework has its own simple APIs for quick customizations.<\/p>\n
Conclusion<\/h2>\n