Why are my SharedPreferences persisting across activites after using clear() in Android? - java

I've looked all over and can't seem to find an answer to my issue. For some reason the data saved in SharedPreferences reappears after switching activities. Why is my SharedPreferences still the exact same as it was before I cleared it and how can I fix this?
In first activity:
#Override
protected void onStop() {
super.onStop();
SharedPreferences sp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
Gson gson = new Gson();
String objectJson = gson.toJson(object, Object.class);
String activityJson = "FirstActivity";
SharedPreferences.Editor editor = sp.edit();
editor.putString(CONTINUE_KEY, objectJson);
editor.putString(ACTIVITY_KEY, activityJson);
editor.apply();
}
public void onClickSave() {
Gson gson = new Gson();
String objectJson = gson.toJson(object);
SharedPreferences sp getSharedPreferences(SAVE_KEY, MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString(object.getDate(), objectJson);
editor.apply();
SharedPreferences spTemp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
spTemp.edit().clear().apply();
// go back to the main menu
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
Before the apply():
After the apply():
In Main Activity:
SharedPreferences sp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
From main activity:

From Coordinating activities android documentation.
When one activity starts another, they both experience lifecycle
transitions. The first activity stops operating and enters the Paused
or Stopped state, while the other activity is created. In case these
activities share data saved to disc or elsewhere, it's important to
understand that the first activity is not completely stopped before
the second one is created. Rather, the process of starting the second
one overlaps with the process of stopping the first one.
The order of lifecycle callbacks is well defined, particularly when
the two activities are in the same process (app) and one is starting
the other. Here's the order of operations that occur when Activity A
starts Activity B:
Activity A's onPause() method executes.
Activity B's onCreate(), onStart(), and onResume() methods execute in sequence. (Activity B now has user focus.)
Then, if Activity A is no longer visible on screen, its onStop() method executes.
This predictable sequence of lifecycle callbacks allows you to manage
the transition of information from one activity to another.
Back to your case, when you start MainActivity from FirstActivity.
FirstActivity's onPause() method executes.
MainActivity's onCreate(), onStart(), and onResume() methods execute in sequence. (MainActivity now has user focus.)
Then, if FirstActivity is no longer visible on screen, its onStop() method executes.
When the code in onClickSave executes.
SharedPreferences spTemp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
spTemp.edit().clear().apply();
At this time, TEMP_KEY prefs has been cleared. After MainActivity is visible on screen, FirstActivity will be no longer visible on screen, so its onStop() method executes.
SharedPreferences sp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
Gson gson = new Gson();
String objectJson = gson.toJson(object, Object.class);
String activityJson = "FirstActivity";
SharedPreferences.Editor editor = sp.edit();
editor.putString(CONTINUE_KEY, objectJson);
editor.putString(ACTIVITY_KEY, activityJson);
editor.apply();
In this code you add two entries into TEMP_KEY prefs again. So when users click on a button in MainActivity, at that time the prefs size is 2 instead of 0 as you expected.
Why is my SharedPreferences still the exact same as it was before I
cleared it?
This is predictable or expected behavior in Android. You can put a log in onCreate(), onStart(), onResume() method of MainActivity, then you can see TEMP_KEY prefs size at that time is always 0.
How can I fix this?
Do not add new entries into TEMP_KEY in onStop(), you should add in onPause() instead.

Save To Shared Preferences
SharedPreferences sp = getSharedPreferences("test" , MODE_PRIVATE);
SharedPreferences.Editor spEditor = sp.edit();
spEditor.putString("hello1" , "hello11");
spEditor.putString("hello2" , "hello22");
spEditor.apply();
Clear From Shared Preferences
SharedPreferences sp1 = getSharedPreferences("test" , MODE_PRIVATE);
SharedPreferences.Editor spEditor1 = sp1.edit();
spEditor1.clear();
spEditor1.apply();
Get From Shared Preferences
SharedPreferences sp2 = getSharedPreferences("test" , MODE_PRIVATE);
String value = sp2.getString("hello1" ,"noting");
Log.i("test_sp" , " == == ==" +value);

First, you have different preference file name for getSharedPreferences(String name, int mode), in onStop() and onClickSave() methods:
// in onStop()
SharedPreferences sp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
// in onClickSave()
SharedPreferences sp getSharedPreferences(SAVE_KEY, MODE_PRIVATE);
you need to use the same file name to access the same preference.
Second, onStop() is not always guaranteed to be called, so it's not a reliable method to save your preferences. Related answer: Is onStop() always preceded by onPause()
Third, always save the preference when you need to keep the value in it. Don't wait to save it later and hoping that you can depend on either onPause(), onStop(), or onDestroy(). Never assume that your application will gracely terminate by user or system.

Related

How to call a method just before an app is closed?

I have a variable who contains data that can change when user is using app.
My goal is to store those data in SharedPrefs just before user is closing app,
I was thinking about something like
OnStop() {
Preferences.edit()... }
but i don't know the correct syntax ...
thanks in advance guys
Save your data in SavedPrefs in onStop Method.
Syntex will be like
In onStop Method
#Override
protected void onStop() {
super.onStop();
SharedPreferences saved_values = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = saved_values.edit();
edit.putString("key", "stringToBeSaved")
editor.commit();
}
And then to retrive your data in onCreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
SharedPreferences saved_values = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String foo = saved_values.getString("key", "default_string");
}
Remember the key should be same.
For more info check out Android docs on
Shared Preferences: Save key-value data
Android Lifecycle: Understand the Activity Lifecycle
Activity.onStop() is called just before the app is completely closed (kicked from recents)
You should probably use Activity.onPause() to save your preferences as it will also be called when the user just switches to another app.
Further information:
https://developer.android.com/guide/components/activities/activity-lifecycle
You should save your persistent data in onPause() rather than in onStop().
Then you can retrieve your data in onResume().
For saving the data you can take a look at this example
SharedPreferences.Editor editor = getSharedPreferences("myPrefs", MODE_PRIVATE).edit();
editor.putString("username", "My name");
editor.apply();
And then retrience your data like this
SharedPreferences prefs = getSharedPreferences("myPrefs", MODE_PRIVATE);
String username = prefs.getString("username", "No username"); //No username is the default value

Resuming activity from where it left if user killed the app manually

I am working on one application in which i move from Activity A(Main Activity) to Activity B to Activity C.
All of this is working fine but the problem occurs when user killed the app by removing it from Task tray.
To understand my problem say user moved from A to B and then C but before finishing the task in activity C user killed the app.
so when user again opens the app by pressing App icon i want to start the last activity C where user was when he killed the app instead of android default behavior of starting(Main Activity A) a fresh instance of app again.
What i have tried:
1) I tried using "onSaveInstanceState" and "onRestoreInstanceState", but i think they are used when orientation is changed or we go back by pressing back button.
2) I tried to save everything in "onPause" as onpause calls 99.99% times when activity destroyed and by using static flags i opens the last activity and it worked for me but i want some good example or technique to this work.
so can anyone help me on achieving the same..??
I request fellow members to provide code examples.
thanks in advance.
Store the state in every Activity's #onPause().
So in every Activity you want:
#Override
protected void onPause() {
super.onPause();
SharedPreferences prefs = getSharedPreferences("RESTART", MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putString("last_left", getClass().getName());
editor.commit();
}
And a Shell Activity which will be a Launcher, Main Activity:
public class Shell extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Class<?> classActivity;
try {
SharedPreferences prefs = getSharedPreferences("RESTART", MODE_PRIVATE);
classActivity = Class.forName(prefs.getString("last_left", getClass.getName()));
}
catch(ClassNotFoundException ex) {
classActivity = your_Activity1.class;
}
startActivity(new Intent(this, classActivity));
}
}
[Source Modified]
you can use SharedPreferences to store last user state.#onPause activity
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putString("state", "A/B/C");
editor.commit();
OnResume Activity
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String stateApp = prefs.getString("state", null);
if (stateApp != null) {
switc(stateApp){
case 'A':
// Go TO A activity
break;
case 'B':
// Go TO B activity
break;
default:
// Go TO C activity
break;
}
}
The Intent that was used to launch the activity is saved by the system when the process is about to be killed.Once the user returns into the app which has been killed, then the app is restored and the same Intent (Activity A in your case) is fired to launch the activity including all the extras that it might have.
Go for SharedPrefrences:https://developer.android.com/reference/android/content/SharedPreferences.html
refer the official documentation.
Try to use sharedPreferences concept, save the activity name in sharedPreferences while the opening of that activity, then check the sharedPreferences value while reopening the application. I think you got it!
sample tutorial link:
https://developer.android.com/training/basics/data-storage/shared-preferences.html

SharedPreferences not updating value when returning to Activity, but only keeps initial Activity load value

So I am trying to use SharedPreferences to pass a value from the Activity to a Class. The problem is the following:
On initial loading of the Activity, the value is stored in SharedPreferences but if I exit the Activity and return back, and try to update the value, the SharedPreferences does not seem to update and stays at the value of the initial load of the Activity.
Some class function
private void populatePlayerQueue(){
int category_index;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.getContext());
category_index = sharedPreferences.getInt("selected_category", 0);
}
Activity onResume
#Override
public void onResume() {
super.onResume();
int tmp = Integer.parseInt(getIntent().getStringExtra("CategoryIndex"));
//store the category in the shared preferences
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("selected_category", tmp);
editor.commit();
}
What I am trying to do:
I have to send an integer from the activity to a specific class and if I come back to the activity then I need to store the update value and so the class will be able to access the newly updated value again. I only have access to the context and not the activity. This causes errors if I try to create an interface callback to communicate with the activity. So this option is eliminated, hence I am trying anything I can to do that.
For some better result remove the SharedPreference through its key at the time of exit application.
In your case when you exit your application just clear the SharedPreference like:
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.remove("selected_category"); //Just remove it by its specific key
editor.commit();
Then it will clearly load and save the new value again when you go back to your application on the same key or you can use new one.

Shared preferences - Bundles intent

I'am trying to put a shared preference in a bundle so i can use it in another class.
So for example I have a class that views the strings inside a shared preference.
Then i have another class which can edit the string.
In my main class where i have created the bundle:
SharedPreferences sharedpreferences;
Intent i = new Intent(getBaseContext(),verification.class);
i.putExtra("sharedpreferences", sharedpreferences);
The issue is with the putExtra. it works for normal strings but not for the bundles, any ideas, i think its something simple
Of course Intent.putExtra(...) works with Bundles:
Intent.putExtra(String name, Bundle value);
Anyways, there is no need to pass the SharedPreferences as a Bundle to the next Activity.
Simply retrieve the SharedPreferences from the next Activity itself.
Save stuff into the SharedPreferences:
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(Context);
Editor e = sp.edit();
e.putString("key", "value"); // save "value" to the SharedPreferences
e.commit();
Retrieve stuff from the SharedPreferences:
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(Context);
String s = sp.getString("key", null); // get "value" from the SharedPreferences
This makes not that much sense, but here is how to put a String from the SharedPreferences into an Intent:
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(Context);
Intent i = new Intent(Context, YourActivity.class);
i.putExtra("key", sp.getString("key", null));

Reload SharedPreferences on resume? (or how to refresh/reload activity)

How can I reload SharedPreferences when I resume from one activity to another? If I resume, it is possible that user has changed the settings. Is it possible to reload SharedPreferences or do I need to refresh/reload activity. And if, then how?
There is no difference in how you get and set SharedPreferences normally and from doing so in onResume. What you will need to do in addition to getting the most recent preferences, is update any objects you have in the Activity that use preference values. This will ensure your Activity is working with the most recent values.
A simple example:
protected void onResume() {
super.onResume();
getPrefs();
//...Now update your objects with preference values
}
private void getPrefs() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String myPref = prefs.getString("myPref", "");
}

Categories