I have released my app to the market and I'm preparing an update.
However, I wanted to refactor the key name of some shared preference but retain the current value on the user's device. Another thing is that I also want to delete the old key name (so the SharedPreferences file is not polluted with unnecessary keys.
How can I achieve this without any hassle to my users?
Create an array of all of your preference keys
Create an array of all the new preference keys
Then create and array of all of their values.
Then call SharedPreferences.clear(). This will completely remove all keys and values from the preferences.
The step through all values and place them back into the SharedPreferences by their new key.
Related
I'm trying to build a single object that handles all my SharedPreferences, since they are mostly used in the whole app, and I don't quite Understand why it takes two keys to get a value.
The call looks like this:
context.getSharedPreferences(FirstKey, Context.MODE_PRIVATE).getString(SecondKey, default)
I get that its basically built up as a two dimensional array.
The FirstKey gives me a collection of key-value pairs I can use my SecondKey on to get my value. And I get that If I have dozens of SharedPreferences this might come in handy to manage them and prevent mixups/unwanted overwriting.
But is this necessary If I only have like 10 preferences I save anyway or is it reasonable to just use one FirstKey for all of my preferences?
But is this necessary If I only have like 10 preferences I save anyway
or is it reasonable to just use one FirstKey for all of my
preferences?
So for this case you can avoid the use of that FirstKey by using getDefaultSharedPreferences() like this:
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
editor.putString("myKey", "myValue");
editor.apply();
or read already set preferences:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String myPref = prefs.getString("myKey", "myDefaultValue");
I guess it is to encapsulate, organize and manage better groups (first key values) of data you want to store (second keys values). So in case you want for example to retrieve all settings preferences you can group them by a Settings file (first key). Or in case you would like to delete all stored values regarding a user preferences (preferred language, preferred currency.. ) then you can organize those data within a "UserPref" file (first key) and then you can iterate within it to either delete all of them when you logout or whatever pogic you see useful for your user experience.
First key
Retrieve and hold the contents of the preferences file
Second key
Retrieve and hold value in this file
You can use only your "FirstKey" for all your preferences and normally dev us it like this only. You can create multiple instances of shared preference by changing the "First key" at the time of getSharedPreference(). Suppose you want two different shared preference for two different modules in your project then change the "FirstKey" parameter, in this case, you have two be careful while storing and fetching data from preference as you have two different shared preference.
As you rightfully stated, the first key represents a group of key-value pairs (which is actually very similar to a single file) and the second key helps you fetch the values in that file/group.
I personally believe this design is great especially in cases where you may want to separate all your values into different categories. If your app is "small", you can save all your values in one single file/group. Otherwise, you can split all your values into separate files/groups.
I hope this helps.. Merry coding!
What to do if the TYPE of preference changed in Android Preferences? For instance if Boolean changed into ListPreference?
Really noone at Google thought about Preference Migrations?
The only sensible way for now seems to version preferences and mark for removal preferences that changed with a given version..?
Try to read key with new data type, in case of ClassCastException exception delete "old" key, and create new key with same name but new type. Something like this:
SharedPreferences prefs;
String key = "key";
prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (prefs.contains(key)) {
// key exists, so tetermine it's type
try {
prefs.edit().get<old_type_name>(key, <default_old_type_value>);
} catch (Exceprtion e) {
if (e instanceOf ClassCastException) {
prefs.edit().remove(key).apply();
}
}
}
// we are here if no key exists or key removed
prefs.edit().put<new_type_name>(key, <new_type_value>).apply();
and if needed do check if (prefs.contains(key)) ... only once on first app start.
I did something that works on raw SharedPreferences and does not need a PreferenceFragment:
introduced settings version.
preferences are stored in xml resources both with dedicated xml strings.
split code to load, migrate, set default settings on application start.
created two string arrays versions and keys - that keep track of preference changes - keys is a comma separated string - with the same index this pair keeps information on given version migration.
check the current version from stored settings and verify against versions stored in string arrays, if its current version is older (lower number) then delete keys provided in a keys string array with the same index (needs string split) and re-create them with default values.
This gives me a nice way of settings migration, based purely on strings xml resources and no code changes, also it should migrate step by step all following versions if user did not update the application frequently :-)
It is also good to mark recent migration for a user review of recent changes..
When i write anything into shared preferences it overwrites the previous value, how can i continuously inject values in preferences and fetch it out all at once like an array? I do not want to use database for this operation.
Thanks
You can use JSON as #CommonsWare points out to store your data in SharedPreferences. I have such an answer that using GSON here:
https://stackoverflow.com/a/5968562/617044
Though not ideal, if you want to use Preferences only, You can store String in preferences. When next value is to be added, retrive the old one add 'comma' and new value.
Whenever you want to use these values, use StringTokeniser. Tokenise elements by 'comma' character.
can i store two or more values with same key using SharedPreferences in android? If no, please tell me how to store values of username, first name, password etc when many users register in registration app?
Ex:
person A registered with username="john12", first name="john" and DOB="06/06/2000".
person B registered with username="arun89", first name="arun" and DOB="08/11/1989".
Now, I want to store these values in SharedPreferences and retrieve them later. Is it possible using SharedPreferences? If not, Please tell me how to do in other way.
Thank you in advance.
I woud consider creating a JSONObject and add the fields you want to store as a key:value pair.
json.putString(key, value);
You can then store the json object in it's string representation with json.toString() and restore it later with
JSONObject jo = new JSONObject(jsonString);
String value = jo.getString(key);
JSONObject also offeres different data types beside strings.
It really depends on how much data you want to store. Depending on that I would choose SharedPreferences or a SQLite implementation.
You cannot store these values directly (as ones added latter will overwrite previously added) but you can always store Parcelable and put your data into it
For your case it is better use SQLIte database.But if you want to use shared preference it is still possible.You have to use a key with additional index to remember different user like
UserName1:arun
UserName2:john
You have to remember the total number of user.Then can maintain all of them.you can also use other data structure like hashmap to maintain data for the shared preference.
I dont't think it is possible, as you don't know the number of users.
You could try to separate the users with commas, but that's lame.
You should consider using SQLite database.
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
Then you have to store a array List of user objects first create a class userInfo then create a array List type of userInfo then store the data in this list and put a serialize-able object in SharedPreferences.
You can also store them on a single key called "registers" as string. Concatenate each register to preference. Put ";" (or any other characther you want) between each register. Then parse the string and use the values.
Key: registers
Value: "username=john12, first name=john, DOB=06/06/2000;username=mike12, first name=mike, DOB=06/07/2012"
Using split method of String will give you a list of registers as String.
registers.split(";");
Splitting again with "," will give you properties of each register.
My application has a preference file, "settings", which contains 10 key/value pairs.
The keys act as titles for the user, and the values are URL's
Both the key and the value are changeable by the user e.g. the first setting looks something like "example" with the value "example.com", when a user changes that setting, the key also changes. So the first setting would become "different_example" with the value "different_example.com". All stored under the "settings" preference file.
I have been managing this so far, by opening a dialog containing the current key/value pairs in an ArrayList that has an onItemClickListener that pops up a second dialog containing another ArrayList of the possible key/value pairs. When the new item is clicked, I remove the current setting, add the new one, then re-populate the initial ArrayList with the new settings. This works and allows both the key and value to be simultaneously changed and updated, however it looks awkward with the two dialogs.
I'd like to switch this all over to ListPreferences. As in, have ten different ListPreference items, one for each setting, that when clicked opens the listing of all possible entryValues, and when selected, updates the key from the entry name, and the value from the entry value, and saves this under the same "settings" file. I'm not seeing how to save ListPreferences to a specific file, so that I can call
SharedPreferences settings = getSharedPreferences("settings", 0);
anywhere, though
I've also been looking for some kind of click handler for what to fire when an entry is selected so I can manually update the "settings" file, but not having any luck. Does such a thing exist? Or is there another way for me to do this?
Edit: I can use OnPreferenceChange to manually set the new value, but this doesn't return the value name, e.g. the value used in the human-readable list. Any ideas on how to get that?
See if this can give you a jump start: How do I get preferences to work in Android?
If you customize your ListPreference and come across something like this How to make a Preference not save to SharedPreferences?
Ahh, well this seems incredibly backwards, but what I've done is set each ListPreference to have an onPreferenceChangeListener, and each entryValue for the ListPreference to contain the name as well as the value separated by an arbitrary string. Then in the onPreferenceChange, I can reference the new value (which now also contains the new key) turn it into a String[] split at the arbitrary separator, then assign the String[] 0 index as the new key, and the 1 index as the new value by using SharedPreferences.Editor after removing the original setting.
Unless there's some way to return the Entry name from the ListPreference's entryValues array, or to specify ListPreference to save to a specific settings file, neither of which is documented, then this will probably be the best solution for me.