Can we have two instances of shared preferences in the same class? - java

I have two instances of shared preferences in my activity class. One instance I'm using to retrieve data that is already stored in shared preferences. The other instances I'm trying to store new sets of data, into a different file, that I'm retrieving from api. Can we do that because null values are being stored in the shared preferences.
Here is a part of my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);){
..........
SharedPreferences sharedPreferences = getSharedPreferences("User",Context.MODE_PRIVATE);
email = sharedPreferences.getString("email",DEFAULT);
//some piece of code........
setdata();//in this method I'm initializing the variables
SharedPreferences sharedPreferences2 = getSharedPreferences("File",
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences2.edit();
editor.putString("a",a);
editor.putString("b",b);
editor.putString("c",c);
editor.putString("d",d);
editor.putString("e",e);
editor.commit();
}
public void setData(){
a="hello";
b="world";
c="hello";
d="world";
e="hello";
}
All these are in my onCreate method of my activity class.
a,b,c,d,e are global variable which I'm initializing in some other method of the class. I'm making the method call in onCreate method before implementing the shared preferences. But null values are being stored.

You have answered you question... The code you have posted is in onCreate method of your activity and a,b,c,d,e are global variables.
So they have null values when the activity starts.
You need to execute the code to save the values after you have initialized the value of a,b,c,d,e which is after receiving data from the API.

Related

Android - losing variables data when partially closing an app

I am using a class with static values called DB (for Data Base) in my application. When I first run the app, a static byte array from this class is filled and used. Then, when I partially close my app (not closing it definitily just put in background) if a reopen it after 20 seconds more or less, the value of the variable is still here but if I let my app in the background for more than 1 minute the value turns to null.
How can I avoid this to happen?
store your variable value to shared preferences and load the value from shared preferences in the onResume() Method of activity and store the value in the onPause() Method.
Handling lifestyle events properly is an important aspect of Android development.
I suggest that you read the following to make sure that you understand what happens to your app when you turn off your screen, change to another application or any other action that might change the state of your app:
http://developer.android.com/training/basics/activity-lifecycle/index.html
My suggestion is to store your data by overriding onSaveInstanceState() like so:
#Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
Then on your onCreate(), you can reload it like so:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null)
{
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
else
{
// Probably initialize members with default values for a new instance
}
...
}
I hope that this helps!
Good luck in your future developing!
I found a solution with the help of the commenters.
For those who had the same problem:
Copy this in all your Activities to ensure that the data is constantly updated in the preferences:
#Override
public void onPause(){
super.onPause();
String bytearray = Base64.encodeToString(DB.bytearray, Base64.DEFAULT);
prefs.edit().putString("BYTEARRAY", bytearray).apply();
}
#Override
public void onResume(){
super.onResume();
String bytearray = prefs.getString("BYTEARRAY", Base64.encodeToString(DB.bytearray, Base64.DEFAULT));
DB.bytearray = Base64.decode(bytearray, Base64.DEFAULT);
}
Then, add this code in all your Activities to ensure that the values are not saved when you close your app.
#Override
public void onDestroy(){
super.onDestroy();
String bytearray = "";
prefs.edit().putString("BYTEARRAY", bytearray).apply();
}

SharedPreferences, Singleton Class - What should you use for calling, editing, saving and recalling two integer values

My app will carry two scores the entire time, calling them, adding to them, saving them, and later calling them back again for other functions and editing. What is the best method for this? These will be the only numbers needed throughout the app.
All I am looking for is the most efficient option I should implement. And if possible a simple example of making, editing, saving and recalling. Thank you.
I suggest using SharePreferences because you are only need to store very small data.
Hint:
synchronized void saveScores(final Context contex, final String scoreOneKey, final String scoreTwoKey, final Integer scoreOne, final Integer scoreTwo){
final SharedPreferences sharedPreferences = context.getSharedPreferences("user.score.key", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS)
final SharedPreferences.Editor preferencesEditor = sharedPreferences.edit();
preferencesEditor.putInt(scoreOneKey, scoreOne);
preferencesEditor.putInt(scoreTwoKey, scoreTwo);
preferencesEditor.commit();
}
Things to Note here are:
You are method must synchronized as multiple threads can access the game score.
Notice the sharedPreference access controls (MODE_PRIVATE | MODE_MUTI_PROCESS) that tells the OS that this sharedPreference is not accessible by other apps but at same time it is possible to access it from multiple process of your app ( if you can even encrypt the scores before saving them.)
UpdatedYou can use SharedPreferences To save Scores When you will call getFirstScore() first Time it will return 0 as the variable is not yet created and then you can call setFirstScore() to save it.
public class ScoreDatabase{
private Context context;
private SharedPreferences pref;
private SharedPreferences.Editor editor;
public ScoreDatabase(Context context){
this.context=context;
pref = context.getSharedPreferences("MY_PREFS", Context.MODE_PRIVATE);
editor = pref.edit();
}
public int getFirstScore() {
return pref.getInt("FIRST_SCORE", 0);
}
public int getSecondScore() {
return pref.getInt("SECOND_SCORE", 0);
}
public void setFirstScore(int score) {
editor.putInt("FIRST_SCORE", score);
editor.commit();
}
public void setSecondScore(int score) {
editor.putInt("SECOND_SCORE", score);
editor.commit();
}
}
Now make instance of this class and use anywhere you want just pass getApplicationContext() in the constructor
//In your MainActivity class
ScoreDatabase scoreDatabase=new ScoreDatabase(getApplicationContext());
//call set function when you want to set score
scoreDatabase.setFirstScore(10);
scoreDatabase.setSecondScore(20);
//Call get function when you want to get score
int firstScore=scoreDatabase.getFirstScore();
int secondScore=scoreDatabase.getSecondScore();

Unable to fetch SharedPreferences

I'm trying to get familiar with using SharedPreferences, by building a simple test app where I store and retrieve user preferences by using a class that extends 'PreferenceActivity'.
The problem is that every time I shut down the app and start it again I'm unable to load the SharedPreferences values that I earlier selected.
In the MainActivity's onCreate method I am first calling a method 'loadPreferences', then creating an ImageView and a button.
I assigned onclick listener to the button that creates and starts a new intent.
...onClick(View v){
Intent intent = new Intent(MainActivity.this, MyPrefsActivity.class);
startActivity(intent);
}
In MyPrefsActivity class I have a ListPreference that has a 'Preference.OnPreferenceChangeListener'.
... {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
imageNumber = Integer.parseInt(newValue.toString());
return true;
}
};
Upon return from MyPrefsActivity to MainActivity in the 'onResume':
protected void onResume() {
super.onResume();
savePreferences();
loadPreferences();
}
private void savePreferences(){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("imageNumber", MyPrefsActivity.imageNumber);
editor.apply();
}
private void loadPreferences (){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int imageNumb = prefs.getInt("imageNumber", 0);
switch (imageNumb){
case 0:
imageView.setImageResource(R.mipmap.image1);
break;
case 1:
imageView.setImageResource(R.mipmap.image2);
break;
case 2:
imageView.setImageResource(R.mipmap.image3);
break;
default:
imageView.setImageResource(R.mipmap.image4);
}
}
When 'loadPreferences' is called for the first time upon startup, 'imageNumb' allways has a value 0, instaed of the value that I assigned to on previous run in method 'savePreferences'.
I noticed that after startup when I enter 'MyPreferencesAction' for the first time and open the ListPreferences, the checkbox that I selected on the last run is already selected for me. It seems like my selection is saved but when I try to load SharedPreferences am I messing up something???
You have to save your preferences in onPause event. Right now you are saving it in onResume when values you want are no longer there.
#Override
protected void onPause(){
super.onPause();
savePreferences();
}
#Override
protected void onResume() {
super.onResume();
loadPreferences();
}
There is another issue with your code. You are saving preferences in MainActivity, but you are changing them in MyPrefsActivity. That will not work. You have to save changes to the preferences in MyPrefsActivity, use above load/save pattern in there too. If you don't have any preference changes happening in MainActivity, you can safely omit calling savePreferences from it.
Depending on MyPrefsActivity declaration calling MyPrefsActivity.imageNumber from MainActivity may not be safe, you will have to change that code too. Like I said, most likely you don't need it at all in MainActivity (if you saving are only preferences values that are set in MyPrefsActivity) and that should be part of MyPrefsActivity.
Also Preference.OnPreferenceChangeListener is probably redundant since it's main usage is to be invoked when the value of this Preference has been changed by the user and is about to be set and/or persisted. This gives the client a chance to prevent setting and/or persisting the value.
I realized there was a lot of needless complexity in my code. So I got completely rid of the method savePreferences(). Instead i simplified the PreferenceChangeListeners method onPreferenceChange(...):
This seems to me to be the most simplest way to update SharedPreferences when using PreferenceActivity.
public boolean onPreferenceChange(Preference preference, Object newValue) {
preference.getEditor().
putInt("imageNumber", Integer.parseInt(newValue.toString())).apply();
return true;
}
Now I save the SharedPreferences manually, only when 'onPreferenceChange' is called. Not on 'onResume', 'onStop', 'onRestart' or on 'onPause'.
Please inform me if this is a bad way to change SharedPreferences.
Quoting Dalija Prasnikar: "reference.OnPreferenceChangeListener is probably redundant since it's main usage is to be invoked when the value of this Preference has been changed by the user and is about to be set and/or persisted. This gives the client a chance to prevent setting and/or persisting the value."
If you understood you correctly Dalija, there is a 'onPreferenceChange(...)' like method that does the job but does not have a boolean return value but void? I was not able to find any examples, could you please show or point to an examle?

Why do i get the default value back?

On my SettingsActivity i am saving a value with the following code:
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putString("ClassName", strArrClasses.get(i));' // i is a variable inside a loop
int intClassID = i+1;
editor.putInt("ClassID", intClassID);
editor.commit();
I'm now trying to get the value of the SharedPreference with the Key "ClassID" on my MainActivity with the following code:
SharedPreferences sharedPrefs = getPreferences(MODE_PRIVATE);
int intClassID = sharedPrefs.getInt("ClassID", 543548564);
My problem now is that I cant access the class ID and I am always getting the default value.
Edit:
I already checked if i can get the ClassID on my SettingsActivity and that works well
use getSharedPreferences instead. Like
SharedPreferences sharedPrefs = getSharedPreferences(name, MODE_PRIVATE);
as from document here
getPreferences retieves a SharedPreferences object for accessing
preferences that are private to this activity. This simply calls the
underlying getSharedPreferences(String, int) method by passing in this
activity's class name as the preferences name.
and getSharedPreferences retrieve SharedPreference by the name.
In your case you used getPreferences which returned SharedPreferences of those activities only.

Global EditText Variables

I'm writing my first android app, and I have an EditText object that I want to be read across my entire program (multiple activities). I'd like to take in a user's name on one screen/activity/layout and read it in several others to manipulate or display it, so I've found that the string needs to be public and static, and that there should be a class with my global variables. What is the correct way to do this? I've tried using bundles and several other methods, but none seem to work.
You should definitely be passing this value through intents.
Intent intent = new Intent(getApplicationContext(),NEXTCLASS.class);
intent.putExtra("username",mEditText1.getText().toString());
startActivity(intent);
and then to receive it in the next class
Bundle extras = intent.getExtras();
mEditText1.setText(extras.getString("username"))
You could also use shared preferences however I think that is unnecessary for your situation as you do not need the username to persist when the app is closed.
Update:
To use shared prefs..
SharedPreferences sharedPreferences = getSharedPreferences("myprefs", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username", myusername);
To read from shared prefs...
SharedPreferences sharedPreferences = getSharedPreferences("myprefs", MODE_PRIVATE);
String username = sharedPreferences.getString("username", "");
An example of using a static property
public class utility {
public static String USERNAME = "username";
}
To invoke you do not need to instantiate the class just do this from each class that needs it
String username = sharedPreferences.getString(utility.USERNAME, "")
You can use SharedPreferences to store the value. Read more here.

Categories