I have been able to successfully implement Shared Preferences into my application but I have ran into a problem with the data being reset/deleted if I kill the application through a task manager.
I am using a static method for saving, that way I only need the method once and can call it everywhere within my app.
protected static synchronized void save(Context cntx){
SharedPreferences preferences2 = cntx.getSharedPreferences("BluRealms", 0);
SharedPreferences.Editor editor = preferences2.edit();
editor.putBoolean("level", Stats.level);
editor.commit();
}
As soon as I kill my app all of my data gets set back to the default settings in my SharedPreferences save method.
I also did some searching and found a few posts that say adding android:persistent="true" into the of the manifest file would fix the problem, yet the data is still reset even with this.
Edit: Well I think I found a bit of information on my problem. This Issue highlights a problem with Samsung Galaxy S phones not saving SharedPreferences properly, which is the device I am testing on. http://code.google.com/p/android/issues/detail?id=14359 - especially comment 6
Any more information on this would be great!
Ok I was able to solve this by removing the "protected static" from my save method.
Instead of calling a global save method, I simply placed the save method in each class that would need to save and then only call the save method in the onPause() and onDestroy() methods.
I noticed that if I called save() too many times within a class that also seemed to erase my SharedPreferences when I closed the app.
TIP:
Do not use static methods for getting or setting shared preferences
In my case remove the tag android: allowBackup = "true" from my manifest and this solves my problem
Related
I am trying to send the string from one Activity to Another WITHOUT changing the CURRENT ACTIVITY. This my code I used:
Intent intent = new Intent(this, AnotherActivity.class);
intent.putExtra("getFollowerNumberData", txt);
startActivity(intent);
Using this code bring me to the other activity or I do not want that. I just want to send this string without changing activity. I tried this one
Intent intent = new Intent();
But it is crashing my app. First of all it is possible to do so? If yes, how can I achieve that?
Edit: To be more clear, it works like follower and Following features in other apps or games. When you follow someone the number of the person you just followed goes up as well your Following number. Since my SignInPlayerProfile.Class(where the Following should go up to one too) is in another activity I was trying to get this information intent.putExtra("getFollowerNumberData, txt); from Main Activity and display that in the SignInPlayerPlayer by using text.setText(). But the Problem is by using intent = new Intent(this, AnotherActivity.class); it brings me to SignInPlayerProfile Activity which I do not like since
I am trying to send the string from one Activity to Another WITHOUT changing the CURRENT ACTIVITY(or simpler words WIHTOUT Going to the Other Activity).
Thanks for Help.
When an activity getting closed, according to it's life-cycle, it will be destroyed and no longer exists, when you start an activity it will be created and then it can get your data, so you can't send data to an destroyed activity which no longer exists
You can use Static Variables to communicate between activities (Classes), you can change value of a Static-Variable of an activity from another activity, but it's not a good option for data you need to be alive because Static Variables lives on Heap Memory and Heap will be freed if Android OS needs more Memory
Another way is to create a Message Handler in your first activity as a Static Variable and then send a Message to the Handler from second activity, see this example :
http://stacktips.com/tutorials/android/android-handler-example
I suggest you using SharedPreferences for saving your data in first activity and load from it on second activity
EDIT :
According to your edit, the "Number" you want to use in another Activity as "Following" or "Followers" is just needed when the second activity is visible, you should use sharedpreferences to save the "Number" and load from it when you need it. For example before text.settext() method you can load the number from sharedpreferences and then pass it to text.settext()
You should not save your data on the variables or classes and should save them on a file like a Database or SharedPreferences then you can load them every time you want
Furthermore you can search about Activity life-cycle and see how to use life-cycle events like OnStart to load your data
Firstly please consider startActivityForResult() ,we can send information from one activity to another and vice-versa. As mentioned consider using shared_preferences for local in memory storage. To truly accomplish this feat in a elegant way though, do consider using obervables(rxandroid). You publish observations in one activity or fragment ,
then subscribe in another activity or fragment. I did not mentioned event bus nor otto since rxjava/rxandroid surpasses it. They act a promise context management system. Also because observable in process dependent consider using broadcast receivers, to broadcast events through out your application and external if so desired.
I have an app making use of SharedPreferences. One just stores app version to check against update for a changelog, the other contains some layout info that clear() gets called on as the user chooses. I finally managed to get a PreferenceFragment working and noticed a trend, so I thought I might ask this now before i go preference crazy (though I think I have enough).
I've done my best to search and see no specific mention of a problem, only that it's possible to have multiples.
I'm a little concerned about PreferenceManager.getDefaultSharedPreferences() grabbing the wrong pref, but I might simply be misunderstanding the usage.
The only relevant code i could think of from my activity:
SharedPreferences storedVer = getSharedPreferences(VER_NUM, 0);
SharedPreferences savedLayout = getSharedPreferences(LAYOUT_SAVE, 0);
It is not bad practice at all. I think it is the opposite. I think different behaviours should use different sharedPreference files.
.getDefaultSharedPreferences() uses the default com.company.packagename.xml file. And the others create their own files.
The followings advantages of using multiple sharedPreference's come up in my mind.
When you use BackupManager, you can provide which sharedPreference files to backup and restore.
When the user logout, you can delete sharedPreference file with that users private values in it. You may not want to delete some other.
From my experience with the SharedPreferences I have noticed the following:
1) Always use try to make your SharedPreference name and Attributes name unique all over the device.
2) Do not use the name of your SharedPreference like "myPreference", "preference", "appPreference"...etc. Use your PackageName as a unique identifier for the SharedPreference name.
Example:
SharedPreferences preferences = getSharedPreferences(Context.getPackageName(), Context.MODE_PRIVATE);
3) Use also a unique Keys for your attributes by concatenating the attribute name with the package name.
Example:
Editor editor = sharedpreferences.edit();
boolean isAdminKey = Context.getPackageName()+"admin";
editor.putString(isAdminKey , "value");
editor.commit();
4) No problem with editing multiple Keys values with one commit().
5) Use MODE_PRIVATE when you create your preferences to prevent other applications from reading your SharedPreferences. See step 2 for example
6) Do not rely on the SharedPreferences 100% because it will be cleared if the user pressed Clear Data button from the App info screen. Otherwise, create file in the ExternalDirectory() or send your info to a server.
Late to the party but I would say do not use multiple preferences. Stick with getDefaultSharedPreferences. I have seen many fail to keep track of the names of the saved preferences. In general it makes the code more complicated in just the wrong way (the compiler can't help you manage your names). Moreover shared preferences are for a handful of small values - use the Filesystem for big things and a database for a lot of data.
I have seen the named shared preferences be used a lot and I believe this is an unfortunate trend spread by copyPaste().
Finally, your preference activities write to the default shared preferences - I have recently answered a question where this was the issue - would be completely avoided if default preferences were used. See: Android SharedPreferences not changing
You might consider wrapping the default shared preferences methods to make them even less verbose as I've done here
I have this listview that gets populated with the data that is downloaded from the internet.
Hence in the onCreate() method, I will run the async task to download the information and put it into the listview.
I placed a boolean value to whether if the list is downloaded or not during the saveInstanceState() method, this will work if the user gets out of the app from the home button and returns. However, when the user exits the program through the back button, the saveInstanceState() method is not run.
I do not want to download the list again, how can I check whether if it's downloaded before?
Check this out: Implementing the lifecycle callbacks
http://developer.android.com/guide/topics/fundamentals/activities.html
Use the callbacks to get noticed what happens to your activity and react if nesseceray.
You can use the Shared Preferences to store key-value data:
http://developer.android.com/guide/topics/data/data-storage.html
If you want to persist data beyond the LifeCycle of the application, you'll need to store it outside the Bundle.
Your options are:
Shared Preferences
Internal Storage (on Device)
External Storage (memory card)
Local Database
Network (which would probably defeat your question)
I'd suggest a private Internal Storage file for saving your data.
You can override Activity.onBackPressed() and save your state there as well.
Also, you can do
void onPause() {
if(isFinishing()) {
// save your state. maybe you'd be better off with using preferences (or other things suggested by people here), so you don't need to worry about the instance state.
}
}
Is there a way to know how many time a user used the app?
basicly i want to do some stuff after 3 uses, 5 uses etc... How can i hold this kind of information after it closed?
You could save that in the preferences. The following code opens the preferences, gets the number of times stored in it, and increments it.
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
int times = preferences.getInt("openKey", 0);
preferences.edit().putInt("openKey", times+1).commit();
You can call this code in your activity's onCreate method.
You can use the SharedPreferences object to store and get any arbitrary information about your application.
Use the Context.getSharedPreferences method to get and instance of this object.
To edit use the edit method to get the editor. don't forget to call commit when you are done.
Important note: if the user uninstalls the application the preferences go away to (just something to keep in mind....)
How about saving the it somewhere? Like in a Database, a SharedPreference or an XML-File?
I have an application Activity that in onCreate loads an XML file from a service using an AsyncTask. The XML is parsed into an ArrayList. When I switch to a different activity and then back to the main activity, I want to be able to recognize that that XML file was already loaded and use the populated ArrayList.
What is the best way to persist that ArrayList?
onSaveInstanceState only seems to support primitives and I've been unable to set up a case where onRetainNonConfigurationInstance actually gets called. So in onCreate, the XML data is loaded from the server ever time I switch to that Activity. I have made the models that are in the ArrayList implement Parcelable, so could use that in some way?
What is the best way to persist that ArrayList?
I don't see where your problem has anything to do with multiple activities. What happens if the user presses HOME (gasp!), for example? Your app will eventually be closed. Do you want to reload the data from the server? If the answer is "yes", then you don't need to "persist" anything, and onSaveInstanceState() may suffice (see below). If the answer is "no", then you need to rethink your approach to your data model, so you arrange to keep the data in a database, synchronizing with your Web service periodically, and probably dumping the ArrayList and replacing it with a Cursor.
onSaveInstanceState only seems to support primitives
If the answer to my HOME question is "yes", then you can just hold onto the data in a data member of your activity, and, if it is modestly sized, also stash it in the Bundle in onSaveInstanceState(). A Bundle can hold an ArrayList of Parcelable. However, if the data set is large (say, 100KB or more), you probably don't want to go this route and should consider the "no" path I described above.
I've been unable to set up a case where onRetainNonConfigurationInstance actually gets called.
Rotate the screen. There are other scenarios, but orientation changes are the easiest ones to trigger it.
However, it has nothing to do with your problem.
"onSaveInstanceState only seems to support primitives"
onSaveInstanceState supports objects, as long as they are declared serializable.
// ON_SAVE_INSTANCE_STATE
// save instance data (5) on soft kill such as user changing phone orientation
protected void onSaveInstanceState(Bundle outState){
password= editTextPassword.getText().toString();
try {
ConfuseTextStateBuilder b= ConfuseTextState.getBuilder();
b.setIsShowCharCount(isShowCharCount);
b.setTimeExpire(timeExpire);
b.setTimeoutType(timeoutType);
b.setIsValidKey(isValidKey);
b.setPassword(password);
state= b.build(); // may throw
}
catch(InvalidParameterException e){
Log.d(TAG,"FailedToSaveState",e); // will be stripped out of runtime
}
outState.putSerializable("jalcomputing.confusetext.ConfuseTextState", state); // save non view state
super.onSaveInstanceState(outState); // save view state
//Log.d(TAG,"onSaveInstance");
}