getPreferences always returns default value - android

I have set up a PreferenceFragment with two boolean preferences. The Fragment works fine and the settings are stored when the app is closed and reopened. I am, however, having issues while trying to read these values; only the default value is returned. If I debug into the getBoolean method of SharedPreferences I see that the local HashMap is of size 0, hence the default value is returned, like this:
public boolean getBoolean(String key, boolean defValue) {
synchronized (this) {
awaitLoadedLocked();
Boolean v = (Boolean)mMap.get(key); // <-- mMap is of size 0: return defValue
return v != null ? v : defValue;
}
}
I find this strange since the preference values are obviously stored and loaded properly into the PreferenceFragment. What am I missing?
In Activity.onCreate():
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
res/xml/preferences.xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="mm_preferences_category_recipe_preferences"
android:title="#string/mm_preferences_category_recipe_preferences_title" >
<CheckBoxPreference
android:key="#string/mm_preferences_numbers_as_fractions_key"
android:title="#string/mm_preferences_numbers_as_fractions_title"
android:summary="#string/mm_preferences_numbers_as_fractions_summary"
android:defaultValue="true" />
<CheckBoxPreference
android:key="#string/mm_preferences_comma_as_decimal_separator_key"
android:title="#string/mm_preferences_comma_as_decimal_separator_title"
android:summary="#string/mm_preferences_comma_as_decimal_separator_summary"
android:defaultValue="true" />
</PreferenceCategory>
</PreferenceScreen>
My PreferenceFragment class:
public class MiasMatPreferencesFragment extends PreferenceFragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
Now, doing this anywhere in the app, returns only the default values (true in both cases), even though the PreferenceFragment shows that the values are set to false (if so):
boolean foo = getPreferences(Context.MODE_PRIVATE).getBoolean(getString(R.string.mm_preferences_numbers_as_fractions_key), true);
boolean bar = getPreferences(Context.MODE_PRIVATE).getBoolean(getString(R.string.mm_preferences_comma_as_decimal_separator_key), true);

After fiddling around with this for some hours I figured out the reason why this didn't work for me. There are several SharedPreferences inside a single app, which I didn't realize. This means that (1) Activity.getPreferences(int mode), (2) Context.getSharedPreferences(String name, int mode) and (3) PreferenceManager.getDefaultSharedPreferences(Context context) returns different instances of SharedPreferences.
In my case, the solution was to use PreferenceManager.getDefaultSharedPreferences(Context context). This is because I use a custom library for backwards compatibility of PreferenceFragment. This library writes to the default preferences file.
From the docs:
PreferenceManager.getDefaultSharedPreferences(Context context)
Gets a SharedPreferences instance that points to the default file that is used by the preference framework in the given context.
So this is preferences for the given Context or Activity at any time using the default filename for preferences. This is a static instance of the PreferenceManager class.
Context.getSharedPreferences(String name, int mode)
Retrieve and hold the contents of the preferences file 'name', returning a SharedPreferences through which you can retrieve and modify its values. Only one instance of the SharedPreferences object is returned to any callers for the same name, meaning they will see each other's edits as soon as they are made.
Using this method you can distinguish between several preference files, using the String argument.
Activity.getPreferences(int mode)
Retrieve a SharedPreferences object for accessing preferences that are private to this activity.
This method calls directly to the previous one like this: getSharedPreferences(getLocalClassName(), mode). Hence it points to a file depending on the name of the Activity.
Other related questions (possible duplicates):
Difference between getDefaultSharedPreferences and getSharedPreferences
PreferenceManager.getDefaultSharedPreferences() vs getPreferences()

Related

Can't resolve findPreference() from MainActivity?

I'm getting a compiler error cannot resolve method findPreference when I try to intialize an OnSharedPreferencesChanged listener in my MainActivity. According to the answer here:
findPreference() should be called from a class implementing PreferenceActivity interface
but I don't understand what the code to do this would be. How can I get rid of the compiler error and successfully set listeners for preference changes?
MainActivity.java
public class MainActivity extends FragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
private SharedPreferences.OnSharedPreferenceChangeListener listener;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
//Test preference menu
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("pref_wood")) {
Preference woodPref = findPreference(key); //COMPILER ERROR HERE
MainActivity.getGLSurfaceView().setTexture("");
// Set summary to be the user-description for the selected value
woodPref.setSummary(sharedPreferences.getString(key, ""));
}
}
}
}
}
findPreference is a method which is part of both PreferenceFragment and PreferenceActivity - these are the Fragments/Activities that actually show your Preference screen (the activity is deprecated and you should be using the PreferenceFragment).
You're trying to use it in your MainActivity. This doesn't work because the Preference objects don't actually exist on this screen (they exist in another activity that usually have a PreferenceFragment as part of it). If you need to get access to a preference value of a preference in an activity that is not your preference screen, use SharedPreferences, something like:
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getBoolean(R.bool.saved_high_score_default);
boolean wood = sharedPref.getBoolean(pref_wood, defaultValue);
You can check out the documentation for further examples.
If your MainActivity is supposed to be a screen that shows settings, then you should probably rename it and include a preference fragment inside of it.
I believe you're also going to run into trouble with setSummary because the Preference is not part of this activity, it's part of the activity where you actually modify the preferences. setSummary is used to update the actual UI of the Preference so that if you, for example, select one of three values when using a list preference, it shows the value you just selected on the screen.

Handling clicks in PreferenceActivity

So I am trying to implement a preferences menu in my app. I used the standard generated template in android studio. THe issue is that now I can't figure out how save the values the user specifies. I thought about using a click listener to determine when a user clicked a checkbox and then getting the actual value of the checkbox and saving that to sharedpreferences, but I can't figure out how to do it.
Does anyone have any suggestions on how use onClick in a preference activity?
OK, we seem to be on the right track about the system storing the values automatically, but whenever I try to reference them from my main class, it always returns null. Here is my code:
boolean trueorfalse = PreferenceManager.getDefaultSharedPreferences(getActivity())
.getBoolean("my_key", false)
;
So I assume you've already defined your Preferences in res --> xml and it looks something like this:
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="my_key"
android:summary="#string/desc_string"
android:title="#string/title_string" />
</PreferenceScreen>
As soon as the user checks or unchecks the CheckBox the systen will automatically create an entry in the default Preference-file which you can access like this:
PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("my_key", false);
But back to your initial question: If you want to assign an onClick-Listener to your preference you have to do something like this:
Preference myPreference = (Preference) findPreference("my_key");
myPreference .setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
// do something
}
});
Note: In this example it isn't a CheckBoxPreference, it's just a simple Preference
I tried the same in my SettingsMenu by implementing OnSharedPreferenceChangeListener
public class SettingsMenu extends PreferenceActivity implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
Context context = getApplicationContext();
SharedPreferences menu_settings = PreferenceManager.getDefaultSharedPreferences(context);
menu_settings.registerOnSharedPreferenceChangeListener(this);
...
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// check the checkboxes
}
}
Hope it helps :)

Preference not getting initialised with default values from the xml

This question has been asked many times in this forum. But I feel it still need to be cleared for me .
public class PrefTest extends Activity {
public Button bt_start= null;
SharedPreferences mSharedPreferences;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.main);
bt_start = (Button) findViewById(R.id.button1);
bt_start.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.d("TEST","");
PreferenceManager.setDefaultValues(getApplicationContext(),
R.xml.settings_org, true);
mSharedPreferences = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
Boolean test = false;
test = mSharedPreferences.getBoolean("auto_launch_key", true);
Log.d("TEST","test = "+test);
}
});
super.onCreate(savedInstanceState);
}
#Override
protected void onStart() {
super.onStart();
}
}
In the above code
Log.d("TEST","test = "+test);
always prints true , though I have set default value in xml as false(as below)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="settings" >
<CheckBoxPreference android:key="auto_launcvh_key"
android:summaryOn="..."
android:summaryOff="---"
android:title="auto_launch_string" android:defaultValue="false" />
</PreferenceCategory>
</PreferenceScreen>
Am expecting the setDefaultValues to take the defaults values form the XML and initialize the preference.
Am I wrong in my understanding?
UPDATE
On closer inspection I can see you probably aren't correctly retrieving the SharedPreference object. although I have not tried it, to make this test work I assume you would have to call getSharedPreferences (String name, int mode) with the name of your XML file to get the object which stores the values defined in your XML file.
getDefaultSharedPreferences (Context context) states:
Gets a SharedPreferences instance that points to the default file that
is used by the preference framework in the given context. Parameters
context The context of the preferences whose values are wanted.
Returns
A SharedPreferences instance that can be used to retrieve and listen
to values of the preferences.
Your file doesn't seem to be the default file and thus the preferences you are trying to call don't exist.
Generally the way to deal with preferences is to sub class a PreferenceActivity which will create a preferences interface but I appreciate you are just trying to write a simple test.
Also I assume the CheckBoxPreference android:key="auto_launcvh_key"is a typo when writing the question. I think I checked the key when first writing this answer and it was CheckBoxPreference android:key="auto_launch_key"
ORIGINAL
Firstly I would change test = mSharedPreferences.getBoolean("auto_launch_key", true); to test = mSharedPreferences.getBoolean("auto_launch_key", false); if it now returns false then the preference doesn't exist in the system so there is a problem with your environment. Try cleaning the project and re-installing.
Secondly in the docs it states
readAgain - Whether to re-read the default values. Note: this will NOT
reset preferences back to their default values. For that
functionality, use getDefaultSharedPreferences(Context) and clear it
followed by a call to this method with this parameter set to true.
Therefore if the preference already exists in the system as true this will not overwrite and so a re-installation should sort this out as well. or you could try calling clear() on mSharedPreferences and then calling PreferenceManager.setDefaultValues(getApplicationContext(), R.xml.settings_org, true);
If this doesn't work can you post complete XML.
The answer is actually very simple.
Boolean values in a preference file are only present when they are true so when reading the boolean value you need to set default value to false:
test = mSharedPreferences.getBoolean("auto_launch_key", false);
So when the preferences in xml is true it reads true and otherwise uses the default of getBoolean. I noticed while debugging there aren't any Boolean preferences with false as the value.

How to update internal values of a PreferenceActivity when SharedPreferences change

I use a Preference in a PreferenceActivity to load default values: when this specific Preference is clicked, something like this happens:
private String mResetKeys = "key1,key2,key3";
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor prefs_editor = prefs.edit();
for (String current_pref : mResetKeys.split(",")) {
prefs_editor.remove(current_pref);
}
prefs_editor.commit();
But afterwards, the Preferences whose corresponding SharedPreference was reset still show the old value - it seems to be cached in the Preference. Only when I leave the PreferenceActivity and reopen it, the Preferences show the new values.
How can I update the PreferenceActivity programmatically?
I had a similar problem. This probably isn't the most correct fix but it worked for my purposes. Right after I did the commits, I called the Activity.recreate(); method.
The activity will restart (onDestroy()/onCreate()/etc) but for my purposes all I needed was a special handling on one preference. I listened for a certain preference with an OnPreferenceClickListener and made an alert dialog box with a kind of warning message and an option to change their mind. If they did want to change their mind, I did my commit of the new value to the preference activity and then called recreate() so that the checkbox preference would be updated.
However, I am also interested in a way to do this without recreating the activity...
Update preference value without reloading PreferenceActivity
from http://liquidlabs.ca/2011/08/25/update-preference-value-without-reloading-preferenceactivity/
Here is how to update default shared preference value of target element (in this case EditTextPreference)
public class YourCustomPreference extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
// some logic goes above, when you want to reset value and update EditTextPreference value
// For convenience, I am going to wrap two different task in different methods
private void resetPreferenceValue() {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this.getApplicationContext());
SharedPreferences.Editor prefEditor = sharedPref.edit(); // Get preference in editor mode
prefEditor.putString("your_edit_text_pref_key", "DEFAULT-VALUE"); // set your default value here (could be empty as well)
prefEditor.commit(); // finally save changes
// Now we have updated shared preference value, but in activity it still hold the old value
this.resetElementValue();
}
private void resetElementValue() {
// First get reference to edit-text view elements
EditTextPreference myPrefText = (EditTextPreference) super.findPreference("your_edit_text_pref_key");
// Now, manually update it's value to default/empty
myPrefText.setText("DEFAULT-VALUE"); // Now, if you click on the item, you'll see the value you've just set here
}
}

Android: Preference default Value

I have 3 - 4 Activities. One of those is the main activity and a second one is a Preference Screen. I have a preference screen with different Preferences like ListPreference etc that have default values.
How can i activate default Value of Settings when I start my project?
By default, they activate only when I start the Settings Activity. Shortly: I need to use the default value in the main activity without calling the Settings Activity.
What I do is have a static method in my Preferences activity class, so it can be called from anywhere:
static public boolean getOrderByDate(Context context) {
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean("order_by_date", true);
}
Note that my default value (true) is specified here in the getBoolean() call. If you want all the defaults specified in one place, you might need to call Preference.setDefaultValue() rather than setting it in the XML.
Just set it like that if you use Shared Preferences.
public static String PlayerName = "";
public static int CardsCount = 52;
public static int PlayersCount = 5;
Also implement LoadSettings() and SaveSettings() methods and it will work fine
Store the preferences using SharedPreferences, and load them in your MainActivity. SharedPreferences has get methods that you pass in a default value to return if the preference doesn't yet exist.
Update: Code Example
In your Main Activity
// get the shared preferences for your package context
SharedPreferences sharedPreferences = PreferencesManager.getSharedPreferences(this);
// get the boolean preference with a default value of false
boolean somePref = sharedPrefernces.getBoolean("somePref", false);
// get the string preference with a default value of "default"
String someOtherPref = sharedPreferences.getStirng("someOtherPref", "default");
There is a method for this. See the docs
PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
Call it at in the onCreate of your main activity. It initializes the preferences to the values stored in your XML file.

Categories

Resources