Preference not getting initialised with default values from the xml - android

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.

Related

getPreferences always returns default value

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()

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 :)

Default Shared Preferences give me wrong values in Service

I have a PreferenceFragment where I have defined a CheckBoxPreference in XML. I need to check this value in a Service, but it always gives me the old value. I noticed the value is correctly changed when I restart the application.
My Preference Fragment :
public class OptionsFragment extends PreferenceFragment
{
public static final String WIFI_ONLY = "wifi";
private SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(MyApplication.getInstance());
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.config);
}
}
My config.xml :
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:defaultValue="true"
android:key="wifi"
android:summary="Check if you want to use wifi only"
android:title="Use Wifi only" />
</PreferenceScreen>
My Service :
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MyApplication.getInstance());
Log.d(TAG, "isWifiOnly : "+settings.getBoolean(OptionsFragment.WIFI_ONLY, true));
The log always return the same value no matter if I change it or not, except if i restart the app. Also, in my MainActivity I have that line in OnCreate():
PreferenceManager.setDefaultValues(getApplicationContext(), R.xml.config, false);
It creates the config file with the default value if needed.
I'm doing something wrong, the question is what ?
I found a solution thanks to this link Managing SharedPreferences in both PreferenceActivity and Service within same app and thanks to Andrew T. :
The issue was the multi process mode. If you have a Service which is declared in the manifest with a android:process="" (which is my case) then it's necessary to set a multi process mode.
Here is what i did :
in PreferenceFragment :
public static final String CONFIG_NAME = "pref";
...
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getPreferenceManager().setSharedPreferencesName(CONFIG_NAME);
getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS);
addPreferencesFromResource(R.xml.config);
...
}
My Service :
SharedPreferences settings = MyApplication.getInstance().getSharedPreferences(OptionsFragment.CONFIG_NAME, Context.MODE_MULTI_PROCESS);
and I set the default values in MainActivity this way :
PreferenceManager.setDefaultValues(getApplicationContext(), OptionsFragment.CONFIG_NAME, Context.MODE_MULTI_PROCESS, R.xml.config, false);
And now it works fine. Hope it will help !
Thank you again Andrew T.
I had the same issue for the last days...
I have a preference.xml with my layout and keys and inflate it into a PreferenceFragment while Listening on changes and thereby informing a Service of my Application of any change.
The crucial part is to set the mode of the SharedPreference access right:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS);
}
The Context.MODE_MULTI_PROCESS flag makes commits() apply to all accessing processes so even my Service would get direct access to the just changed values.
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
if(SettingsManager.setupIsValid(getActivity())){
Intent startServiceIntent = new Intent(getActivity(), IntentService.class);
startServiceIntent.setAction("PREFERENCES_CHANGED");
getActivity().startService(startServiceIntent);
} else {
Toast.makeText(getActivity(), getString(R.string.settings_incomplete), Toast.LENGTH_SHORT).show();
}
}
This will first do check magic and whenever the settings are valid inform the service of the change.
This allows the usage of multiple processes and always current preference values across all processes.
P.S.: direct access then looks like this
SharedPreferences prefs = context.getSharedPreferences(context.getPackageName() + "_preferences", Context.MODE_MULTI_PROCESS);

Preference deactivating on its own in a PreferenceActivity

I have a PreferenceActivty in my Android app, which due to compatibility reasons I use via the getPreferenceScreen() method and some Preference objects which I create in code, mostly CheckBoxPreference and SwitchPreference.
Up to the previous version of my app there were 8 preferences in total and everything worked fine, but now I added 2 more preferences and I'm experiencing a REALLY weird issue.
The second preference on the screen is a SwitchPreference. When I open the activity, it is checked. If I scroll down the screen without actually changing anything, suddenly its value is automatically set to OFF. I tried adding an OnChangeListener to the Preference and implementing OnSharedPreferenceChangeListener, but the results are the same: once that particular Preference disappears from the screen, it is turned OFF. If it's set to OFF, it keeps its value and the change listener is not called.
Does anyone have any idea as to why could this be happening? I'm completely lost...
Thanks in advance!
The code for my preferences is basically this, repeated 5 times for 5 different settings, on the onCreate method:
controlWifiPreference = new CheckBoxPreference(this);
controlWifiPreference.setKey(Constants.PREF_1_KEY);
getPreferenceScreen().addPreference(controlWifiPreference);
wifiPreference = new SwitchPreference(this);
wifiPreference.setKey(Constants.PREF_2_KEY);
getPreferenceScreen().addPreference(wifiPreference);
Since the preferences are inside a TabActivity, on the onResume method I call setChecked() for every preference to set its value again, though I'm not sure that it's completely neccessary.
And, finally, I have an onSharedPreferenceChanged method that activates/deactivates preferences when others are clicked, because I couldn't get the setDependency method to work. It's something like this (again, repeated five times):
if (key.equals(controlWifiPreference.getKey())) {
wifiPreference.setEnabled(controlWifiPreference.isChecked());
}
Turns out it was an Android bug in the SwitchPreference class. Someone (who I'm VERY thankful to ;)) reported it to b.android.com and even posted a workaround. It's all here: https://code.google.com/p/android/issues/detail?id=26194
How you implemented preferences inside TabActivity?I checked your code in my own IDE inside a PreferenceActivity and its working like a charm.If you need to have some pseudo prefences inside your activity, you should not use prefernces and instead, you will need to use normal forms items and save their values to the preferences manually.here is the code i tested and its working ok:
public class PreferencesFromCode extends PreferenceActivity implements
OnSharedPreferenceChangeListener {
private SwitchPreference switchPref;
private CheckBoxPreference checkboxPref;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setPreferenceScreen(createPreferenceHierarchy());
}
private PreferenceScreen createPreferenceHierarchy() {
// Root
#SuppressWarnings("deprecation")
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(
this);
// Inline preferences
PreferenceCategory inlinePrefCat = new PreferenceCategory(this);
inlinePrefCat.setTitle(R.string.inline_preferences);
root.addPreference(inlinePrefCat);
// Checkbox preference
checkboxPref = new CheckBoxPreference(this);
checkboxPref.setKey("checkbox_preference");
checkboxPref.setTitle(R.string.title_checkbox_preference);
checkboxPref.setSummary(R.string.summary_checkbox_preference);
inlinePrefCat.addPreference(checkboxPref);
// Switch preference
switchPref = new SwitchPreference(this);
switchPref.setKey("switch_preference");
switchPref.setTitle(R.string.title_switch_preference);
switchPref.setSummary(R.string.summary_switch_preference);
inlinePrefCat.addPreference(switchPref);
/*
* The Preferences screenPref serves as a screen break (similar to page
* break in word processing). Like for other preference types, we assign
* a key here so that it is able to save and restore its instance state.
*/
// Screen preference
PreferenceScreen screenPref = getPreferenceManager()
.createPreferenceScreen(this);
screenPref.setKey("screen_preference");
screenPref.setTitle(R.string.title_screen_preference);
screenPref.setSummary(R.string.summary_screen_preference);
return root;
}
#Override
protected void onResume() {
super.onResume();
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this);
/*
* getPreferenceScreen().getSharedPreferences()
* .registerOnSharedPreferenceChangeListener(this);
*/
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
Log.i("ghjg", "changed key is : " + key);
if (key.equals(checkboxPref.getKey())) {
switchPref.setEnabled(checkboxPref.isChecked());
}
}
}
However you may override onContentChanged() and see what happens.

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
}
}

Categories

Resources