I just curious what makes a value inside of some variable become empty again or back to its initial value in the android life cycle.
First lets take a look at how i create a variable :
public class myData {
public static String myCode = "";
public static String getData(String Choice) {
String theData = "";
if ("Code".equals(Choice) {
theData = myCode;
}
return myCode;
}
public static void setData(String setData,String Choice) {
if ("Code".equals(Choice) {
myData.myCode = setData;
}
}
}
If I want to fill the variable, i usually do this :
myData.setData("value of variable","Code");
And if I want to get the value of the variable, I usually do this :
myData.getData("Code");
I just want to know what makes my variable gone inside of android lifecycle, of course excluding when the application is closed.
I have to try to Log and show the value in onstart , oncreate, onresume and onrestart. And all of them is still have the value inside of my variable intact without any problem.
My client always tells me that my application sometimes gets crash when they open some activity. I also ask if they did something while using my application,
some of them answer that the application get crashed after they got a phone call and when the phone call is ended, the application is started with a crash.
some of them also said that when they open the application and then idle the phone withouth closing the application until the phone become black screen, and when they open it again the application get crashed.
After I check the log, the problem was the variable become empty. which is why I want to know is there another possibilites that makes the value inside of the variable become empty?
As John Lord saying, on low-end device variables might back to its initial value again if there is not enough memory.
So for future reference, I use a shared preference to counter it, here is my structure for fetching the data :
public class myActivity extends AppCompatActivity {
String myCode = "";
protected void onCreate(Bundle savedInstanceState) {
....
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("myData", Context.MODE_PRIVATE);
myCode = sharedPreferences.getString("Code",null);
....
}
#Override
protected void onResume() {
super.onResume();
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("myData", Context.MODE_PRIVATE);
myCode = sharedPreferences.getString("Code",null);
}
}
And here is how i set the data :
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("myData",Context.MODE_PRIVATE);
sharedPreferences.edit().putString("Code","Hello World").apply();
I hope it will be helpful for those who want to search the same thing
I tried to store some values in ArrayList by SharedPreferences by the following code:
public static String jsonSavePracticeResult;
private SharedPreferences sharedPreferencesSaveResults = PreferenceManager.getDefaultSharedPreferences(this);
public void savePracticeResults(ArrayList<KeepPracticeResultsModel>
arrayListPracticeResult) {
Gson gson = new Gson();
jsonSavePracticeResult = gson.toJson(arrayListPracticeResult);
SharedPreferences.Editor editorSharedPreferencesSaveResults;
editorSharedPreferencesSaveResults =
sharedPreferencesSaveResults.edit();
editorSharedPreferencesSaveResults.clear();
editorSharedPreferencesSaveResults
.putString("donePracticeList",jsonSavePracticeResult);
editorSharedPreferencesSaveResults.apply();
}
After that, I retrieved values by the following code:
public ArrayList<KeepPracticeResultsModel> getSavedPracticeResults(){
jsonSavePracticeResult = sharedPreferencesSaveResults.getString("donePracticeList", jsonSavePracticeResult);
Gson gson = new Gson();
Type type = new TypeToken<ArrayList<KeepPracticeResultsModel>>() {}.getType();
keepPracticeResultsModels = gson.fromJson(jsonSavePracticeResult, type);
return keepPracticeResultsModels;
}
When app is open, it works fine, but when you try to close app from recent apps, and after that you open app again, SharedPreferences values are lost and jsonSavePracticeResult is Null!
Also I called getSavedPracticeResults() in onResume() and onPause().
I did all of the solutions that existed in StackOverflow but it's happening again!
Have you tried using .commit() instead?
Change
editorSharedPreferencesSaveResults.apply();
to
editorSharedPreferencesSaveResults.commit();
The reason being that .apply() writes in the background, asynchronously; wherever as .commit() will write right away. So, if you're closing your app, you want to quickly save these changes before the app is closed.
I use token based authentication in my app. When user logins through Android app the server returns token which needs to be sent with each subsequent request.
I need to store that value on the devices. Since token is a simple string, I thought I'd use SharedPreferences to hold that value.
Two think confuse me on which method save token in sharedpref. and other one is where to receive the token while implementing change password.
Use Aynch task For network task
Use Post Method Api
try something like this.. Create a class for saving values
public class SharedPreferenceCustom {
private String defValue = "";
private SharedPreferences sharedPreferences;
public SharedPreferenceCustom(Context context) {
sharedPreferences = context.getSharedPreferences("app_name", Context.MODE_PRIVATE);
}
public void setSharedPref(String inputKey, String inputValue) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(inputKey, String.valueOf(inputValue));
editor.apply();
}
public String getSharedPref(String inputKey) {
return sharedPreferences.getString(inputKey, defValue);
}
}
and call whenever needed
Call by
SharedPreferenceCustom sp = new SharedPreferenceCustom(mContext);
sp.setSharedPref("KEY", "VALUE");
// or
sp.getSharedPref("KEY");
I have a broadcast receiver running independently from my application.
When a specific number calls, i need to trigger a service to run.
I am saving the triggering number in shared preferences within my application.
How do I get this value within my broadcast receiver so that I can check that the number calling matches before I start my service call.
I have tried the following code within my receiver to retrieve it:
variables
private SharedPreferences preferenceSettingsUnique;
private SharedPreferences.Editor preferenceEditorUnique;
private static final int PREFERENCE_MODE_PRIVATE = 0;
private static final String MY_UNIQUE_SETTINGS = "MY_UNIQUE_SETTINGS";
In the function I have
preferenceSettingsUnique = getSharedPreferences(MY_UNIQUE_SETTINGS,PREFERENCE_MODE_PRIVATE);
tracker_trigger = preferenceSettingsUnique.getString("tracker_trigger",null);
The value returns as null.
If anyone knows a good way to do this please.
edit showing saving procedure
preferenceSettingsUnique = getSharedPreferences(MY_UNIQUE_SETTINGS,PREFERENCE_MODE_PRIVATE);
preferenceEditorUnique = preferenceSettingsUnique.edit();
final EditText trackertrigger_Field = (EditText) findViewById(R.id.Editsmstrigger);
preferenceEditorUnique.putString("tracking_trigger",trackertrigger_Field.getText().toString());
boolean Success = preferenceEditorUnique.commit();
if(Success){
//ALERT MESSAGE
Toast.makeText(getBaseContext(),"Successfully Saved Settings.", Toast.LENGTH_LONG).show();
super.onBackPressed();
}
You are saving data in preferences with key tracking_trigger but when retrieving data from the preferences, you are trying to get data corresponding to the key tracker_triggerwhich doesn't exists. That's why always returns the default value of null. Just make both the keys same.
SharedPreferences doesn't work correct in one existing apps. I tried many different ways but still not working. Always get default values app start again.
It's working when I use same code in created new app.
It's working all of other existing apps.
Do you know why?
String default_user = "Default_User";
SharedPreferences pref = this.getSharedPreferences("TEST_SHAREDPREF", MODE_PRIVATE);
String user = pref.getString("user", default_user);
Log.d("SHARED CHECK", user);
if (user.equals(default_user)) {
SharedPreferences.Editor edit = pref.edit();
edit.putString("user", "new_user");
boolean ok = edit.commit();
user = pref.getString("user", default_user);
Log.d("SHARED WRITE", user);
Toast.makeText(this, user + " Save process: " + ok, Toast.LENGTH_LONG).show();
} else {
Log.d("SHARED READ", user);
Toast.makeText(this, "READ SharedPrefs: " + user, Toast.LENGTH_LONG).show();
}
EDIT: log results
that block always return this for which is incorrect app and I don't know why
//first run
SHARED CHECK Default_User
SHARED WRITE new_user
//each time after first
SHARED CHECK Default_User
SHARED WRITE new_user
That block always return this for which are all apps
//first run
SHARED CHECK Default_User
SHARED WRITE new_user
//each time after first
SHARED CHECK new_user
SHARED READ new_user
When you call apply() or commit() the changes are first saved to the app's memory cache and then Android attempts to write those changes onto the disk. What is happening here is that your commit() call is failing on the disk but the changes are still made to the app's memory cache, as is visible in the source.
It is not enough to read the value from the SharedPreferences as that value might not reflect the true value that is on the disk but only that stored in the memory cache.
What you are failing to do is to check the boolean value returned from the commit() call, it is probably false for your problematic case. You could retry the commit() call a couple of times if false is returned.
Just use below method and check.
Create one Java class AppTypeDetails.java
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
public class AppTypeDetails {
private SharedPreferences sh;
private AppTypeDetails() {
}
private AppTypeDetails(Context mContext) {
sh = PreferenceManager.getDefaultSharedPreferences(mContext);
}
private static AppTypeDetails instance = null;
public synchronized static AppTypeDetails getInstance(Context mContext) {
if (instance == null) {
instance = new AppTypeDetails(mContext);
}
return instance;
}
// get user status
public String getUser() {
return sh.getString("user", "");
}
public void setUser(String user) {
sh.edit().putString("user", user).commit();
}
// Clear All Data
public void clear() {
sh.edit().clear().commit();
}
}
Now Set value to SharedPreferences.
AppTypeDetails.getInstance(MainActivity.this).setUser(<user name>);
Get Value form SharedPreferences.
String userName = AppTypeDetails.getInstance(MainActivity.this).getUser();
Now do any thing with the userName.
Always check
if(userName.trim().isEmpty())
{
// Do anything here.
}
because In SharedPreferences we set user name blank ("")
or
you can set user name null in SharedPreferences then you need check
if(userName != null){
//do anything here
}
For clear data from SharedPreferences.
AppTypeDetails.getInstance(MainActivity.this).setUser("");
or
AppTypeDetails.getInstance(MainActivity.this).clear();
One thing you could try is to get a new SharedPreference instance after committing and see what happens:
SharedPreferences pref = this.getSharedPreferences("test", MODE_PRIVATE);
String user = pref.getString("user", default_user);
if (user.equals(default_user)) {
pref.edit().putString("user", "new_user").commit();
SharedPreferences newPref = this.getSharedPreferences("test", MODE_PRIVATE);
user = newPref.getString("user", default_user);
}
Your editor is committing a new preference map into disk, but it is possible that the old SharedPreference instance is not notified of the change.
Instead of using edit.commit();, you should use edit.apply();. Apply
will update the preference object instantly and will save the new
values asynchronously, so allowing you to read the latest values.
Source - Also read detailed difference between commit() and apply() in this SO Post.
The "Source" post referenced above also states pretty much the same problem and switching to apply() seems to have resolved the issue there.
Problem statement in the referenced post:
The problem is that when I am accessing this values, it is not
returning updated values, it gives me a value of SharedPreferences.
But when I am confirming the data in XML file ,the data updated in
that.
PS: And the reason that the same code block is not working on this one app and working on all other apps could also be that you are either using the block at different places or updating the value somewhere else too.
Your code is right, the code works on any app very well, looks like that in some part of your app the shared preferences are been modified, the only way to find a solution is review all your code, because if this problem only happens on one app, it's somewhere on your app that the shared preferences are been modified, for good practices, you should have only one file class for the management of your preferences on that way you can comment or find usage for a method and you can find where the shared preferences was been modified.
BTW the best way to store an user, password, or any account info is using Account Manager.
For good practices you can see this sample PreferenceHelper class.
public class PreferencesHelper {
public static final String DEFAULT_STRING_VALUE = "default_value";
/**
* Returns Editor to modify values of SharedPreferences
* #param context Application context
* #return editor instance
*/
private static Editor getEditor(Context context){
return getPreferences(context).edit();
}
/**
* Returns SharedPreferences object
* #param context Application context
* #return shared preferences instance
*/
private static SharedPreferences getPreferences(Context context){
String name = "YourAppPreferences";
return context.getSharedPreferences(name,
Context.MODE_PRIVATE);
}
/**
* Save a string on SharedPreferences
* #param tag tag
* #param value value
* #param context Application context
*/
public static void putString(String tag, String value, Context context) {
Editor editor = getEditor(context);
editor.putString(tag, value);
editor.commit();
}
/**
* Get a string value from SharedPreferences
* #param tag tag
* #param context Application context
* #return String value
*/
public static String getString(String tag, Context context) {
SharedPreferences sharedPreferences = getPreferences(context);
return sharedPreferences.getString(tag, DEFAULT_STRING_VALUE);
}}
I used the below code pattern in one of my app and I always get the latest value stored in SharedPreferences. Below is the edited version for your problem:
public class AppPreference
implements
OnSharedPreferenceChangeListener {
private static final String USER = "User";
private static final String DEFAULT_USER = "Default_User";
private Context mContext;
private String mDefaultUser;
private SharedPreferences mPref;
private static AppPreference mInstance;
/**
* hide it.
*/
private AppPreference(Context context) {
mContext = context;
mPref = PreferenceManager.getDefaultSharedPreferences(context);
mPref.registerOnSharedPreferenceChangeListener(this);
reloadPreferences();
}
/**
* #param context
* #return single instance of shared preferences.
*/
public static AppPreference getInstance(Context context) {
return mInstance == null ?
(mInstance = new AppPreference(context)) :
mInstance;
}
/**
* #return value of default user
*/
public String getDefaultUser() {
return mDefaultUser;
}
/**
* Set value for default user
*/
public void setDefaultUser(String user) {
mDefaultUser = user;
mPref.edit().putString(USER, mDefaultUser).apply();
}
/**
* Reloads all values if preference values are changed.
*/
private void reloadPreferences() {
mDefaultUser = mPref.getString(USER, DEFAULT_USER);
// reload all your preferences value here
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
reloadPreferences();
}
}
You can set the value as below in your activity:
AppPreference.getInstance(this).setDefaultUser("user_value");
To get the updated value for saved user, use below code:
String user = AppPreference.getInstance(this).getDefaultUser();
Hope this solution will fix the problem you are facing.
For saving and retrieving data from SharedPrefrence create a util type methods in your Utility class:
Below I have given code snippet for both the methods i.e for saving and retrieving SharedPrefrence data:
public class Utility {
public static void putStringValueInSharedPreference(Context context, String key, String value) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(key, value);
editor.commit();
}
public static String getStringSharedPreference(Context context, String param) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(param, "");
}
}
Now you just need to call Utility.putStringValueInSharedPreference(Activity_Context,KEY,VALUE); to put data in prefrence and Utility.getStringSharedPreference(Activity_Context,KEY); to get value from prefrence.
This methodology reduces chances of error; May this will be helpful for you.
I recommend controlling your preference check with another preference value.
String user = pref.getString("user", default_user);
In your preference check:
String getStatus = pref.getString("register", "nil");
if (getStatus.equals("true")) {
// move on code stuff
}
else{
// ask for preferences
}
In the part where the preference is added.
edit.putString("user", "new_user");
editor.putString("register", "true");
edit.commit;
Don't know if this is correct or not, but you can implement a Shared preference change listener and you can log in that and check if the shared preference is not called again in any other class, which is again setting the value to Default user.
I Mean you got to make sure that there is no other code resetting the value of user.
The code itself looks fine and you say it works in other apps. Since you have confirmed the XML file gets properly created, the only remaining option is that something happens to the file before you read it during app launch. If there is no other code in the app that handles any shared preferences, then something must wipe the file during the launch.
You should take careful look at launch configuration of this particular app and compare to other apps where this is working. Maybe there is some option that wipes user data when app is started. I know there is such an option at least for emulator (in Eclipse), but I am not sure if you are running this in emulator or device.
You should also try launching the app directly from the device instead of IDE. This tells if the problem is in the app itself or IDE configuration. And try moving this from onCreate (where I presume this is) to onResume and compare does it work when you resume to the app versus when you completely restart it.
Finally I solved that problem.
A method was added by one of other developers.
All files under data/data/packageName folder except libs folder were being deleted by this method.
I think they tried delete cache folder.
Removed this method and it solved.