Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 861
Steel Avatar asked Dec 25 '22 09:12

Steel


2 Answers

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.

like image 124
Steel Avatar answered Apr 29 '23 19:04

Steel


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);
like image 25
DooMMasteR Avatar answered Apr 29 '23 19:04

DooMMasteR