Android crashes because of SharedPreferences - android

I'm a beginner in Android, but I've done all the research I could on this problem and I just can't seem to find a way to solve it... The app worked fine until I decided to add the SharedPreferences in order to update some high scores. Now I can't seem to make it work, it always crashes at the very start (after the splash screen)
In the on Create method, below the setContentView I have the following lines:
highScores = getSharedPreferences("HighScores", 0);
hs1 = highScores.getInt("HighScore1", 0);
shs1 = highScores.getString("sHighScore1", "User1");
and a couple more, but mostle they are alternate takes on lines 2 and 3 in the prior code. I have declared the highScores as SharedPreferences in the body of the class. The only place in this class where I use the info gathered from the SharedPreferences is in editing a TextView, which uses the following code:
High1.setText(String.format("1. %04d - %s", hs1, shs1));
My guess is that I made an error somewhere in the code, but am unable to find it...
Just for additional info, I only use the SharedPreferences in one other class (which should update the high scores at the end of games) and uses a simillar code:
highScores = getSharedPreferences("HighScores", 0);
hs1 = highScores.getInt("HighScore1", 0);
shs1 = highScores.getString("sHighScore1", "User1");
The code above was for getting previous high scores, while the code below is used for updating:
prefEditor.putInt("HighScore1", hs1);
prefEditor.putString("sHighScore1", shs1);
prefEditor.commit();
I have declared the SharedPrefs editor as:
SharedPreferences.Editor prefEditor = highScores.edit();
I would really appreciate any help, as I can't seem to find what I've done wrong, probably it's a small error somewhere, but it's really driving me nuts :P I would give you more of the code, but I can't see any purpose in that, because it doesn't use the SharedPreferences and I'm pretty sure they're the cause of the issue...
Thank you in advance for your help :)

Related

Android, sharedPreferences automatically remove the list of the unused preferences when upgrading an application

My app have had many releases and some of the earlier version sharedPreferences are useless.
What would be the best way to have the app itself sorting out the one that are still used and remove the unused one ?
Basically it would be like parsing the preferences XML's to extract the current android::key and by getting all preferences present on the device remove the one not being anymore in an XML.
Not sure I am very clear, but I have lot's of shared preferences not used anymore and having to establish the list manually can be source of problem.
Any hint would be great,
Thanks a lot
you can go through the keys one by one removing any that you dont use anymore like this
Map<String,?> prefs = pref.getAll();
for(Map.Entry<String,?> prefToReset : prefs.entrySet()){
if(prefToReset.getKey().equals("someKey")){
pref.edit().remove(prefToReset.getKey()).commit();
}
}
though there really is no performance benefit from doing this really

Retrieving preferences using Gdx.app.getPreferences

I have a simple question (may be very dumb), however I did not find an answer goggling around.
I'm trying to save a simple preference say "high score" on my game that I'm using libgdx to build.
Here is my sample code -
Preferences prefs2;
prefs2= Gdx.app.getPreferences("MyPreferences");
prefs2.putString("name", "Donald Duck");
String name = prefs2.getString("name", "No name stored");
font.draw(textBatcher, name, 55, 55);
Everything in the code (reading and writing to the xml file MyPreferences) works as expected except one thing; the high score stored on the file doesn't work when I restart the game. I definitely know that I'm missing something that is very simple but don't know what it is :)
Can any one please help me ?
I have also tried this -
Preferences prefs2;
if (prefs2 == null){
prefs2= Gdx.app.getPreferences("MyPreferences");
}
However it doesn't seem to work.
You're lacking a call to prefs2.flush() after you added the highscore item to the preferences object.
Straight from the libgdx docs:
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/Preferences.html#flush()

SharedPreferences overwrite other value

I have a problem with the SharedPreferences If I want to save two different values. I tried with this code:
SharedPreferences sharedPref = getSherlockActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.SavedStartSilentHour), hour);
editor.commit();
editor.putInt(getString(R.string.SavedStartSilentMinute), min);
editor.commit();
// One editor.commit() is enough
If I run this code the first value is overwritten with the seccond value. If I delte the second part the value is saved correctly. Why is that?
Your code seems perfect!
You could simplify the thing by committing all the stuff after all the "puts" operations. Although I don't think that this could be your problem...
Just make sure SavedStartSilentHour and SavedStartSilentMinutes xml's defined values are correctly defined, i.e., if they are the same of course they will be overwritten. (This is the only one thing that makes any sense to me considering your code).
Let mew know of your progress ;)
Remove first call to
editor.commit();
and you will be fine.
The issue is most likely caused by re-using a key such that the second assignment simply overwrites the same-keyed value.
One way to test this hypothesis is to try using simple keys which eliminate such possibility, e.g.:
editor.putInt("hour", hour);
editor.putInt("min", min);
Alternatively, a debugger can be attached and the results of getString(keyId) can be compared.
If this does indeed "fix" the issue, then ensure that the SavedStartSilentHour and SavedStartSilentMinute resources actually evaluate to different strings - inspect the resource file itself.

Parsing XML one time only on 1st startup

I'm currently using a Parser and it parses every time the onCreate gets called.
My parser uses an XML file that's located in my assetfolder.
Is there any chance that I can make it parse only once, instead of every time I rotate the screen or restart the application?
Thank you :)
There are 2 answers to this question. The easy one first:
If you only want this to happen once, create a static boolean in your main activity and set it to true when the XML is parsed in. Then use:
if(!isParsed)
XML.parse();
The more complete answer to this question is to make sure you are handling configuration changes correctly.
I suggest you read this article on how to implement configuration change handling. You should be able to solve this problem "the Android way" by implementing this.
Hope this helps!
Persist a flag using the Preferences system the first time you complete a parse, and check this each time before parsing again. Do all this in your OnCreate() method.
SharedPreferences settings = getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
if (!settings.getBoolean("parsed", false)) {
parseTheXML();
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("parsed", true);
editor.commit();
}
There are other ways but this has the advantage of working across app reloads/phone power cycles - assuming that's what you want.
You could add a preference. Something like -
void setIsAppOpened() {
editor.putBoolean(APP_OPENED, true);
editor.commit();
}
Set it in your onCreate(). Then, also add the following code to check if the preference exists.
if (!prefs.contains(APP_OPENED))
{
//parse the XML
setIsAppOpened();
}
You can parse your XML in a "Application" object and have it accessible from there. Check out the documentation at http://developer.android.com/reference/android/app/Application.html

SharedPreferences will not save/load in PreferenceActivity

EDIT: The problem described below was due to a very peculiar device issue not caused by any coding-related problem.
I have a preferenceActivity in which I have many checkBoxPreferences.
The checkBoxPreference is suppose to save the the default shared preferences file, and then be called again when I open the app in order to update the UI.
This does not happen like it's suppose to.
If I close the app and open it back up, my values remain like they are suppose to, but if I use task manager to end the app or if I power cycle the phone (when the app is not running) then the defaultValues are called again.
So, I created a SharedPreference in my onResume() to test it.
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
I then check to see if there is a key in that sharedpreference.
pref.contains("myCheckBoxPreference");
When I close out and open it back up, it returns true. if I close with the task manager or power cycle the phone off and on, then that returns false.
So, I tried manually setting the SharedPreference
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("myCheckBoxPreference", myCheckBoxPreference.isChecked());
editor.commit();
and then I called that when the checkboxpreference value changed. I also tried calling it in onStop and onPause. Still, if I close the app and open it back up, pref.contains returns true, but if I power cycle the phone off and back on, it returns false.
So I then tried using a SharedPreferences file.
In the class declaration:
public static final String PREFS = "prefs";
And in the onResume():
SharedPreferences pref = this.getSharedPreferences(PREFS, 0);
Same behavior, pref.contains still returns true if I just close the app and open it back up, but it returns false if I power the phone off and back on.
I then tried changing the key value of myCheckBoxPreference to something that did NOT match the xml key for the CheckBoxPreference, and it still had the same effect.
And I uninstalled the application from the phone, then powered the phone off and back on, and then re-installed, and it still has the same effect.
I just solved it, I'm pretty sure. There's no code error on my part, and there is no issue with my app whatsoever (I don't believe, anyway.)
I created a new project called "testproj", then I copied ALL the code from my settings PreferenceActivity, pasted it into the TestprojActivity, and I copied the code from the xml it relied on, then pasted that into the main.xml of TestProj.
I then installed TestProj on the Samsung Captivate, changed the settings around, cleared the ram through RAM management (a function of the custom ROM I have), and the settings stuck. I then power cycled the phone and the settings were still there like I'd configured them.
They stayed both when I manually set them using:
PreferenceManager.getDefaultSharedPreferences();
and without manually saving them to the SharedPreferences.
Since it is not my phone, I haven't tried it yet, but I assume a Factory Data reset would fix it completely
EDIT: I was able to test on both a new Samsung Captivate and a Samsung infuse, and it worked.
I wasted a lot of my time trying to figure this out, and I hope it helps someone else. :)
I encountered a possibly similar problem on a Samsung Galaxy S, where the permissions for the preferences XML file had somehow changed/corrupted.
The log revealed some host process was failing to read the file, causing all the settings to reset to their defaults. I don't recall the exact error message, but it was along the lines of "permission denied for /path/to/preferences/file.xml".
The resolution for me was to delete the application data through Settings, Applications, Manage Applications, MyApp, Delete data. This deletes the preference file associated with the app and the problem instantly disappeared.
I assumed it was an isolated event, as I've not run into it again on a variety of Android devices (including the Galaxy S II).
On the client's main test device I came across the very same issue. The Device used is a Samsung Galaxy S with SDK level 8 (2.2.1).
The strange behavior is that either SharedPreferences are not saved, or, as after a factory reset, they're too persistent, that is to say they are not deleted after having reinstalled the application.
Due to the current distribution of 2.2.x, and the number of Samsung Galaxy S devices sold being several millions, the probability of an occurrence of this issue is significant.
So it can be considered as crucial to implement a workaround for saving preferences.
For collecting detailed characteristics to isolate this workaround in a sharp-edged way, could everyone who is also facing that issue please provide the corresponding kernel version (System.getProperty("os.version") here?
I was thinking of something like this:
// !! I know that 2.6.32.9 is not yet correct. This would be a false positive !!
if ((System.getProperty("os.version").startsWith("2.6.32.9"))
&& (android.os.Build.DEVICE.contains("GT-I9000")))
useInternalStorage();
else
useSharedPreferences();
I can post the real code here also once it's ready and someone is interested.
EDIT: some additional information:
Devices facing that issue:
Property | Values
---------------------------------+------------------------------------
Build.DEVICE | "GT-I9000T"
Build.VERSION.INCREMENTAL | "UBJP9"
Build.VERSION.RELEASE | "2.2.1"
Build.VERSION.SDK | 8
System.getProperty("os.version") | "2.6.32.9"
Similar devices NOT facing that issue:
Property | Values
---------------------------------+------------------------------------
Build.DEVICE | "GT-I9000"
Build.VERSION.INCREMENTAL | "AOJP4"
Build.VERSION.RELEASE | "2.2"
Build.VERSION.SDK | 8
System.getProperty("os.version") | "2.6.32.9"
Try clearing the editor before you set your values. I had the same problem and it worked for me.
Example:
Editor e = PreferenceManager.getDefaultSharedPreferences(getParent()).edit();
e.clear();
e.putStringSet(key, value);
It is possible to work around the issue of permissions by using sharedUserId which should be the same for any of your signed apps.
http://developer.android.com/reference/android/R.attr.html#sharedUserId
I too had a problem with saving and then retrieving data. I had my Save and Load code in a class that extends Application because I wanted a single instance of my data. I could see the String being saved, no errors in LogCat and yet when I try to load it, again with no error, my String is empty. I never checked whether the data actually went into the file so I have no idea whether there was a failure on Save or Load or both.
My code was more or less as follows: (comboToSave is simply a string generated by Gson from a simple data class)
in one method to save:
SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(getString(R.string.prefCombos), comboToSave);
editor.commit();
in another method to load:
SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
String loadedComboText = sharedPref.getString(getString(R.string.prefCombos), "");
After lots of head scratching and not knowing what to do I changed the code that retrieves the sharedPref value from
SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
to
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
There is some more here on the difference between the two (although in my case it seems exactly the same)
Still the result on my Galaxy S3 was the same. However, testing both versions on other devices, including VDs (virtual devices) worked.
In the first version of the code I passed the Activity from the calling activity; for save from the activity where the final bit of data is collected from the user, and for loading from my main activity so that I had it ready when the app is started.
I played with uninsalling the app and re-intalling, turning the device off and on again last night to no avail.
I have now moved the save and load methods from the application class to the activity where I complete the input i.e. both load and save code is now in the same activity. I have tested this with both variations of the code and they both work. I get back what I save. I then moved all the code back to the Application class and it works; this leads me to believe that somehow with all the installing/uninstalling I somehow managed to get it working. Point is: the code is correct - if it does not work the device and/or settings are probably to blame
I have the same problem, and i suffered from it for a while , finally i found the solution ,
and it is so easy , just pass the direct reference of the activity , and do not use any general context
public SessionManagment(Activity mContextActivity){
// this.contextActivity = mContext;
sharedPrefSession = mContextActivity.getSharedPreferences(
Constants.SHARED_PREFERANCES_LIGHT_TIGER_SESSION_FILE_NAME,
Context.MODE_PRIVATE);
}//enden constructor
the code above is the constructor of the class that i have written for session management , and
and when i call it in the code in the main ActivityFramgment in a AsyncTask i call it like this
SessionManagment sessionManagment = new SessionManagment(referanct2thisActivity);
where referanct2thisActivity is defined in "onCreate" function of fragment activity like this
referanct2thisActivity = this;
hope that will help others in the future

Categories

Resources