Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
like image 509
Krøllebølle Avatar asked Dec 24 '22 15:12

Krøllebølle


1 Answers

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

like image 60
Krøllebølle Avatar answered Dec 27 '22 06:12

Krøllebølle