9

I have read this helpful post :

SharedPreferences.onSharedPreferenceChangeListener not being called consistently

However I am having no luck. I am trying to create an OnSharedPreferenceChangeListener that runs in a service. Everything is implemented correctly but the listener is not always triggered.

public MyServiceOne extends Service {

    public SharedPreferences mSharedPreferences;

    // Listener defined by anonymous inner class.
    public OnSharedPreferenceChangeListener mListener = new OnSharedPreferenceChangeListener() {        

        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            Log.d("debug", "A preference has been changed");            
        }
    };

    @Override
    public void onCreate() {            
        mSharedPreferences = getSharedPreferences(MySharedPreferences.NAME, Context.MODE_PRIVATE);
        mSharedPreferences.registerOnSharedPreferenceChangeListener(mListener);
    }

    @Override   
    public void onDestroy() {
        super.onDestroy();
        mSharedPreferences.unregisterOnSharedPreferenceChangeListener(mListener);
    }
}

UPDATE

The problem stems from a fact I did not mention. I am running two services and when shared preference changes are made in MyService2 nothing is triggered. In the manifest I define the services to run in different processes. Is there a way to make this work?

Community
  • 1
  • 1
jjNford
  • 5,170
  • 7
  • 40
  • 64

3 Answers3

10

After gaining some experience with Android I have come back to answer this question and help anyone else who is having trouble with this type of situation.

The implementation of the OnSharedPreferenceChangeListener is correct. The problem lies in the manifest and application architecture. Because the services are running in different processes Android has created difference Dalvik Virtual Machines for each service therefore they do not "hear" each others listeners.

This was just bad design - The better way to approach the idea of running two concurrent services is to create one service that threads each "service" off to run concurrently. This way they can share the same Heap thus sharing the same Objects & Listeners

If someone were determined to use two services they could create a BroadcastReceiver to catch intents for that preferences need to be changed - or communicate through sockets. There are also ways to do this with a ContentProvider (Please NEVER DO THIS). But again, there is no reason for any of this if the design is good.

jjNford
  • 5,170
  • 7
  • 40
  • 64
  • You could also create a method that constantly renews the shared preference file before getting data or editing it. – Droid Chris Jan 03 '14 at 22:33
0

I know this thread is old. But has anyone tried this using MODE_MULTI_PROCESS?

MODE_MULTI_PROCESS

WoodsLink
  • 107
  • 5
0

Why not let your service implement OnSharedPreferenceChangeListener?

That way it's not an anonymous inner class, so it doesn't get garbage collected, and you can still do whatever you want in the service.

Lars
  • 4,082
  • 2
  • 20
  • 20
  • This was the first thing I tried and it didn't work either. Sorry for not mentioning that. – jjNford Nov 01 '11 at 15:00
  • The only thing I can think of is that maybe you are not calling the correct SharedPreferences. Have you tried using `mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());`? – Lars Nov 01 '11 at 15:03
  • Yes, I tried this and it did not work either. I know that I am calling it correctly as I tested this with the same code in the PreferenceActivity that I have and it worked perfectly. I am trying to get a listener in the service however so I can take the action in its class. Just seems more logical and easier to follow and debug. The only solution I am seeing at this point is to implement it in the PreferenceActivity and send out a broadcast... just seems like there should be a better way. – jjNford Nov 01 '11 at 15:08
  • I just check if I was calling the correct preferences by logging some values and it was correct, so that is for sure not the problem. – jjNford Nov 01 '11 at 15:11
  • Well then I'm afraid I don't know what is causing this to not work. I can suggest an alternative though. How about making your `Application` class the `OnSharedPreferenceChangedListener`? That way you can also listen when a preference is changed and the PreferenceActivity is not active. – Lars Nov 01 '11 at 15:13
  • Okay so I found the problem... check out the update because there will be another question from it. Thanks. – jjNford Nov 01 '11 at 15:14
  • I'm sorry, I don't know much about processes and the likes, and I'm afraid I can't help you any further. Best of luck though. – Lars Nov 01 '11 at 15:17