I have a boolean variable public static boolean isInDarkTheme but when I try to change the value in my settings activity it only gets changed tempolarily.
I did it so:
if (on) {
//Do something when Switch button is on/checked
MainActivity.isInDarkTheme = true;
} else {
//Do something when Switch is off/unchecked
MainActivity.isInDarkTheme = false;
}
Log.d("DarkTheme", "SETTINGS " + MainActivity.isInDarkTheme);
in my settings the variable is changed but when I go back to my main with the
arrow I created with this:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
picture with this button
it is still the same in the main
but! when I use my software key to get back to the MainActivity it get saved
picture with software back key
Any idea what I can do that it get saved with the other button?
your variable will not be saved and will be collected by garbage collector once the activity is destroyed.
you have to use something like SharedPreferences.
to save the variable
SharedPreferences sharedPrefrences = getSharedPreferences("pref_name", MODE_PRIVATE);
sharedPrefrences.edit().putBoolean("isDarkTheme", true).apply();
to load
SharedPreferences sharedPrefrences = getSharedPreferences("pref_name", MODE_PRIVATE);
// key , default value
boolean isDark= sharedPrefrences.getBoolean("isDarkThem", false);
read about SharedPreferences here
The most likely reason is that both activities are loaded by different class loaders with the effect that the MainActivity you "see" in your Settings activity is a different one than the one you "see" in your other activity. You can find that out by logging the classloader "attached" to the MainActivity by calling MainActivity.class.getClassLoader()
Related
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();
}
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?
I don't know if this is even possible but I have several activities, two at the moment, and I have time limit of 20 minutes for player to finish the game. The problem is, he starts at one activity, then goes to another and so on. How to keep the timer going even in another activity, and keep it visible in a textView?
EDIT for minhaz:
public void getTime(long value, String PREFERENCE_NAME){
SharedPreferences myPrefs = mContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putLong("time", value);
prefsEditor.commit();
}
Just create a global timer class.
class Timer {
private static long startTime = -1;
public static void reset() {Timer.startTime = -1;}
public static void initialize() {Timer.startTime = System.currentTimeMillis();}
public static long getTimeMillis() {return System.currentTimeMillis() - startTime;}
private Timer() {}
}
Then, by importing this class (wherever you've put it), you can access the current time.
As stated by Lukas, extending Application would be nice.
You could also use a preference that store the time at which the timer was started...
But working working with timer start time sounds the best way, I think.
Start timer from one activity and when user switch to next one pass the value inside an Intent
Intent intent=new Intent(Current.class, NextActivity.class);
intent.putExtra("time", timer_value);
And on the another activity get the value as
time_value=intent.getLongExtra("time")
In this way user will get some buffer time, when their is delay in between activities, as starting activity call is Asynchronous. You can call finsh() or do something else based on your requirement from the time.
Extending Application class is also a good solution, if you want to limit time from starting the app. But thats not exactly the total play time.
Update:
For storing data, you can use persistence storage based on your requirement. Right now, shared preference look like a good candidate.
Store Data
SharedPreferences myPrefs = mContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = myPrefs.edit();
prefsEditor.putLong("time", value);
prefsEditor.commit();
Retrieve data
SharedPreferences sharedPref = mContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
return sharedPref.getLong("time", 0);
I have my settings.java and my fragment.java.
In the fragment (that exists in my settings.java) I have a randomized number to set a view. Which works perfectly. I'm trying to change it from a random int to something pulled out of shared prefs. In my settings.java I have a method:
public int getHour() {
SharedPreferences settings = getSharedPreferences("My_Prefs",
MODE_PRIVATE);
int timeout = settings.getInt("timeout_hour", 8);
return timeout;
}
and I call this in my fragment.java by saying
...settings.getHour();
But this causes it to crash. If I simply replace it with a random int (any int) ...8 the program runs perfectly. Why does my app run when I just have the number 8, but when getHour() returns a number (8 in this case) it fails. Is this some kind of limitation with fragments?
Because settings is a local variable to getHour() function. If you want to access it inside your fragment make it a field and provide a public getter function getSettings(). Then get activity instance in fragment by
activity = (Settings) getActivity();
Now access settings by
activity.getHour()
inside fragment.
Because my mainActivity does not run my Tab2Activity at startup until the user press the setting button to run the PreferenceActivity, therefore i have to first check the audioStatus boolean value in order to avoid unwanted boolean result but after this step i'm kinna lost because of the bug in CheckBoxPreference it gives me...
Now i don't know how to work with the logic comparison to get the audio even without navigating to Tab2Activity? Main problem here i'm facing is working with the logics yet getting the desirable result..
I'm kinna new in java/android and currently creating an car blackbox app can someone help me... Thanks :)
My mainActivity file
if(Tab2Activity.audioPref == false)
audioStatus = false;
else
audioStatus = Tab2Activity.audioPref;
if(audioStatus == false)
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
if(audioStatus == false)
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
My Tab2Activity.java file
public static boolean audioPref;
public static String timeIntervalPref;
public void getPrefs() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
audioPref = prefs.getBoolean("AudioPref", true);//Suppose to produce "false" isn't it?
timeIntervalPref = prefs.getString("TimeIntervalPref", "60000");
}
}
My xml file
<CheckBoxPreference
android:title="Audio"
android:defaultValue="True"
android:summary="Select w/o Audio when Recording"
android:key="AudioPref" />
save your settings to a SharedPreferences then read them from there rather than relying on the state of a public boolean in the Tab2Activity.
http://developer.android.com/reference/android/content/SharedPreferences.html
example of use:
http://saigeethamn.blogspot.com/2009/10/shared-preferences-android-developer.html
EDIT: I don't know why you are trying to get the preferences from tab2activity.
why wouldn't you do the following in mainActivity:
SharedPreferences prefs=PreferenceManager.getDefaultSharedreferences(getBaseContext());
audioStatus=prefs.getBoolean("AudioPref",true); // (only use true if you want the default to be true if the value has not yet been set, otherwise you should be doing ("AudioPref",false) )
if(!audioStatus)
{
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
}
The bug you linked describes issues when you try to set default shared preference values to 'false'. If you want that to be the default, then just use "false" as the default value when you go to retrieve the value using getBoolean(string,defValue)