Any time I try to getInt() from a SharedPreference my app crashes, yet I can iterate through the preferences as a map. For instance, see the starred lines below:
private void loadPref(){
myPrefs = PreferenceManager.getDefaultSharedPreferences(this);
int sf = DEFAULT_VALUE;
Map<String,?> keys = myPrefs.getAll();
for(Map.Entry<String,?> entry : keys.entrySet()){
if (entry.getKey().contentEquals("score_format"))
// this works: //*****
sf = Integer.parseInt(entry.getValue().toString()); //*****
}
// but this does not: //*****
// sf = myPrefs.getInt("score_format", DEFAULT_VALUE); //*****
setScoreFormat(sf);
}
Clearly, my prefs are being saved (as evidenced by this sample and working preference screens across multiple activities). I am calling super.onCreate() before trying to access getDefaultSharedPreferences.
What should I be considering to understand why this code is not working? Why would the map work but not the "getInt" method? I did notice that the app would also crash if I tried to cast the key value explicitly... I had to cast it toString first.
What am I missing?
if you don't want to parse, make sure the score you're putting into the intent with putExtra is an int type, not a string.
Looks like object assosiated with score_format key is a String but you are trying to obtain it as int which is a mistake.
Related
I'm wanting to store a number of different user favorites (in this example a max of 5) in sharedpreferences.
The user will be able to add and delete these favorites from within the app.
I'm having trouble getting my head around how to achieve this (I assume some sort of looping is needed).
The gist of what I'm trying to do when a user adds a new favorite:
//init prefs
public static final String PREFS_NAME = "PREFS";
SharedPreferences sharedPreferences = null;
SharedPreferences.Editor sharedPreferencesEditor;
//onCreate
sharedPreferences = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
//method called when user adds new favorite
public void addFavorite(String fav) {
//int i = 0;
//int maxFavs = 5;
//check how many favorites are already stored in shared prefs, if any (is it under maxFavs?)
//if over maxFavs, display error
Toast.makeText(getApplicationContext(),"Favorite added",Toast.LENGTH_SHORT).show();
//else continue
//upon finding available favorite 'space' (less than permitted maxFavs), add to favorites in shared prefs
sharedPreferencesEditor = sharedPreferences.edit();
sharedPreferencesEditor.putString("fav_" + i, fav);
sharedPreferencesEditor.apply();
}
Am I getting the right idea here, or is there a better way to do what I'm intending to do? Hopefully it's clear from the above.
Store favorite count in preferences as an int and read & update it as needed. Also it would be better if you store favorites in preferences as (key : favoritedItemId, value boolean)
Even better: Use a proper local database for situations like this. Preferences is a primitive key value type storage intended for simplier cases like storing a users light mode preference.
Gave up and created a simple database following the example here:
https://inducesmile.com/android/android-sqlite-database-example-tutorial/
Still, if anyone has a solution I'd be interested to see!
I can get a String from the shared preferences by using:
sharedPreferences.getString("key_name","default value");
But how can I check if key_name is actually a String?
What if it is a Boolean key value?
Is there a method we can use like:
if(sharedPreferences.isTypeOf(Boolean,"key_name")) {}
If you know you will get a boolean you can use
sharedPreferences.getBoolean("key_name",true);
Otherwise you can do (not tested, based on doc)
Map<String, ?> all = sharedPreferences.getAll();
if(all.get("key_name") instanceof String) {
//Do something
}
else if(all.get("key_name") instanceof Boolean) {
//Do something else
}
But you are suppose to know what you stored in your SharedPrefrences
What is expected is you ought to know the data type of your SharedPreference values.
All the shared prefrences that you put are inserted into a Map.
A map cannot have duplicate keys that hold different values. When you use the put operation it basically overwrites the value associated with the key if they key already exists in the map.
You can find how a Map "put" method works here - Java Map
So checking the instanceof for two(or multiple) data types as suggested by #Maloubobola, is kind of absurd since the key can only one value and that value can be of only one data type(which you should know :P).
You can do that but it doesn't make sense like #Blackbelt commented.
All the best :)
If you expect a String, you can also use a try/catch clause:
try {
String strValue = sharedPreferences.getString("key_name","default value")
actionIfString();
} catch (ClassCastException e) {
actionIfNotString();
}
I am trying to store TreeSet in the SharedPreferences using the following code:
Set<String> chemicalValuesSet = new TreeSet<>();
chemicalValuesSet.add("id: " + checkForNull(jsonChemicalValues.getString("id")));
editor.putStringSet(SP_CHEMICAL_VALUES, chemicalValuesSet);
editor.apply();
However, when I try to access that TreeSet I am getting casting error, as if this set is declared as a HashSet.
SharedPreferences sharedPreferences =
getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
TreeSet<String> chemicalValues =
(TreeSet<String>) sharedPreferences.getStringSet(SP_CHEMICAL_VALUES, null);
I have no clue to solving this issue. In addition, when I started writing this part I was setting chemicalValuesSet as HashSet and retrieving without any problems, afterwards I decided to go with TreeSets. That's why I have tried cleaning and restarting the project, but still same issues persists.
However, if I simply change type to HashSet
in the part where I retrieve this set, it works without complaining.
You're simply making false assumptions on how SharedPreferences and its editor works. The API never guarantees that the Set you get when calling getStringSet() is the same, or even the same implementation, as the one stored when calling putStringSet(). All it says is that you can pass a Set, and that you can get a Set.
If the API documentation says that it returns a Set, you should not assume that it's returning a TreeSet, or a HashSet. Only that it's returning a Set. If you absolutely need a TreeSet, then create one and copy the items from the returned Set to the TreeSet.
You cannot cast HashSet to TreeSet straight away.
Instead you can do either of the following to add all the items in the HashSet into TreeSet but keep in mind, the items added to the TreeSet will get sorted automatically.
// Passing the collection HashSet to TreeSet
HashSet<String> hashSet = sharedPreferences.getStringSet(SP_CHEMICAL_VALUES, null);
TreeSet<String> chemicalValues = new TreeSet<String>(hashSet);
or
// Adding all the values of the HashSet to TreeSet using addAll() API
// This will help to retain the values of TreeSet (if any)
TreeSet<String> chemicalValues = new TreeSet<String>();
...
HashSet<String> hashSet = sharedPreferences.getStringSet(SP_CHEMICAL_VALUES, null);
chemicalValues.addAll(hashSet);
Actually the returned set is a hash set:
TreeSet<String> chemicalValues =
(TreeSet<String>) sharedPreferences.getStringSet(SP_CHEMICAL_VALUES, null);
You can check this conclusion in source code in SharedPreferencesImpl.java
public Set<String> getStringSet(String key, Set<String> defValues) {
synchronized (this) {
awaitLoadedLocked();
Set<String> v = (Set<String>) mMap.get(key);
return v != null ? v : defValues;
}
}
And you can also get the set type like this:
chemicalValues.getClass().getSimpleName()
HashSet and TreeSet can not be interpreted to eachother.
Hope this can help you.
I have a problem with with sharing data between two different activities. I have data like :
int number
String name
int number_2
int time
int total
I'm trying to make something like order list with this set of data . So it will take one set of data , then back to previous activity , move forward and again add data to it .
I have an idea of making it in array of object - but data inside was cleared after changing activity.
How can I make it ?
I don't know if and how to add Array of object to SharedPreferences , and get value of one element from there.
You should have a look at the documentation of the Intent(s) if you want to do that on the fly associating a key to the value(s) that you want to pass to your second activity.
Anyway, you can think any(sharedpref, database,...) way to pass your parameters but for those kind of things it's a convention and a good practice to follow that.
Don't used share preferences for this...Use the singleton pattern, extend Application, or just make a class with static variables and update them...
You can use .putExtra but since you are communicating with more than one activity the above suggestions are probably the best.
public class ShareData {
private String s;
private int s;
private static ShareData shareData = new ShareData();
private ShareData(){}
public static ShareData getInstance(){ return shareData}
//create getters and setters;
}
Why not to use Intents
Intent intent = new Intent(FirstActivity.this, (destination activity)SecondActivity.class);
intent.putExtra("some_key", value);
intent.putExtra("some_other_key", "a value");
startActivity(intent);
in the second activity
Bundle bundle = getIntent().getExtras();
int value = bundle.getInt("some_key");
String value2 = bundle.getString("some_other_key");
EDIT if you want to read more about adding array to shared preferences check this
Is it possible to add an array or object to SharedPreferences on Android
also this
http://www.sherif.mobi/2012/05/string-arrays-and-object-arrays-in.html
Let's say i created a shared preference.
sp = this.getSharedPreferences("name",MODE_PRIVATE);
If i'm in another activity, is there a way i can find the name of sp and set it to a string?
you can access the sharedpreferences with the same method you have used. use a public static varibale to hold the name in a class.
Use a constant. a public final static String NAME = "the_name";. Then you can alway reference it as NameOfTheClassWhereYouPutIt.NAME
If you are looking to refer to a given shared preference in another activity, you can pass that String key of that preference to the new Activity via its Intent when creating it.
If you simply need to find a certain preference in any activity, you can iterate over all of the preferences, and get access to all the keys (and values) that way.
Assuming your shared preferences is in the variable mySharedPreferences, an example of getting all of the keys and vales would be:
Map<String,?> preferenceMap = mySharedPreferences.getAll();
for ( Map.Entry<String, ?> keyValPair : preferenceMap.entrySet() )
{
String key = keyValPair.getKey(); // this is your preference name
String val = keyValPair.getValue(); // this is your preference value
}