title: OnSharedPreferenceChangeListener not working in another thread task
body: <p>When using a thread/task within an android service that implements the OnSharedPreferenceChangeListener interface, the changes made in the preference screen aren't reflected back to the thread/task object within the android service.</p>
  
  <p>I want to accomplish two things:</p>
  
  <ul>
  <li><p>SharedPreference data should be loaded when MyTask is constructed and initialized.</p></li>
  <li><p>When preference change occurs, MyTask object must be updated with the new preference values set in the preference screen.</p></li>
  </ul>
  
  <p>The problem is: preference initialization and preference changes are not reflected to the MyTask object.</p>
  
  <p>This is my setup (only essential parts are mentioned):</p>
  
  <p><b>MyService.class:</b></p>
  
  <pre><code>public class MyService extends Sevice {
      private MyTask myTask;
  
      @Override
      public int onStartCommand(Intent intent, int flags, int startId) {
          if (!serviceStarted) {
              serviceStarted = true;
              myTask = new MyTask(this);
              Thread t = new Thread(myTask);
              t.start();
          }
          return Service.START_STICKY;
      }
  
      @Override
      public void onDestroy() {
          myTask.cancel();
          super.onDestroy();
      }
  }
  </code></pre>
  
  <p><b>MyTask.class:</b></p>
  
  <pre><code>public MyTask implements Runnable, OnSharedPreferenceChangeListener {
      private Context mContext;
      private boolean mCancelled;
      public MyTask(Context context) {
          mContext = context;
      }
  
      @Override
      public void run() {
          while(!mCancelled) {
              // do something
          }
      }
  
      @Override
      public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
          String key) {
          // FIXME: DOESN'T GET CALLED after change in preference!!!!
          Log.d(TAG, "Key= " + key);
      }
  
      public void cancel() {
          mCancelled = true;
      }
  }
  </code></pre>
  
  <p><b>preference_devices.xml:</b></p>
  
  <pre><code>&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" &gt;
      &lt;PreferenceCategory
          android:key="pref_category_devices"
          android:title="@string/pref_category_devices_title" &gt;
          &lt;CheckBoxPreference
              android:defaultValue="true"
              android:key="pref_devices_server"
              android:title="@string/pref_devices_server_title" /&gt;
      &lt;/PreferenceCategory&gt;
  &lt;/PreferenceScreen&gt;
  </code></pre>
  
  <p>I have tried coding a SharedPreferences listener object as a member field of the MyTask class and register/unregister the listener from the provided context, but that didn't work either. These changes also didn't work:</p>
  
  <p><b>MyTask.class (using SharedPreference listener as field member of class):</b></p>
  
  <pre><code>public MyTask implements Runnable {
      private Context mContext;
      private boolean mCancelled;
      private boolean mServerEnabled;
      private SharedPreferences mPrefs;
      private SharedPreferences.OnSharedPreferenceChangeListener
          mPreferenceListener;
  
      public MyTask(Context context) {
          mContext = context;
          mPrefs = mContext.getSharedPreferences("pref_category_devices",
                  Context.MODE_PRIVATE);
          mPreferenceListener = new OnSharedPreferenceChangeListener() {
              @Override
              public void onSharedPreferenceChanged(
                  SharedPreferences sharedPreferences, String key) {
                  // FIXME: DOESN'T GET CALLED after change in preference!!!!
                  Log.d(TAG, "Key= " + key);
              }
          };
          mPrefs.registerOnSharedPreferenceChangeListener(mPreferenceListener);
          // set the initial value of the preference setting
          mServerEnabled = mPrefs.getBoolean("pref_devices_server", false);
      }
  
      @Override
      public void run() {
          while(!mCancelled) {
              // do something
          }
      }
  
      public void cancel() {
          mCancelled = true;
      }
  }
  </code></pre>
  
  <p>I have now reached the point of throwing my computer out of the window :(</p>
  
  <p>Any help in the right direction is highly appreciated :)</p>
  
  <p>EDIT: In the code</p>
  
  <pre><code>mPrefs = mContext.getSharedPreferences("pref_category_devices", Context.MODE_PRIVATE);
  </code></pre>
  
  <p>I assumed that the first argument should be the preference category name of the preference file, like: "pref_category_devices". THIS IS INCORRECT! The first argument must be a shared preference file name. That didn't solve the problem, but at least now you know to not fall for this pitfall.</p>
  
  <p><b>=== SOLUTION: ===</b> See answer of Mr_and_Mrs_D + code below this line:</p>
  
  <p>Change in MyTask:</p>
  
  <pre><code>mPrefs = mContext.getSharedPreferences("pref_category_devices",
              Context.MODE_PRIVATE);
  </code></pre>
  
  <p>into:</p>
  
  <pre><code>mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
  mPreferenceListener = new OnSharedPreferenceChangeListener() {
      @Override
      public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
          if (key.equals("preference_name_here")) {
              mPrefValue = sharedPreferences.getBoolean(key, false);
              // do something with boolean pref value 
          }
      }
  };
  mPrefs.registerOnSharedPreferenceChangeListener(myPreferenceListener);
  </code></pre>
  
  <p>Where mPrefValue is a field member of type boolean in MyTask that needs to be set when the "preference_name_here" preference changes.</p>