I am changing and committing a SharedPreference in my SyncAdapter after successful sync, but I am not seeing the updated value when I access the preference in my Activity (rathe
Ok, I figured it out myself with @Titus help and after some research and pieced together a solution for my problem.
The reason why the DefaultSharedPreferences
of the same Context
are not updated is that I have specified the SyncService
to run in its own process in the AndroidManifest.xml
(see below). Hence, starting from Android 2.3, the other process is blocked from accessing the updated SharedPreferences
file (see this answer and the Android docs on Context.MODE_MULTI_PROCESS).
<service
android:name=".sync.SyncService"
android:exported="true"
android:process=":sync"
tools:ignore="ExportedService" >
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
So I had to set MODE_MULTI_PROCESS
when accessing the SharedPreferences
both in the SyncAdapter
and in the UI process of my app. Because I've used PreferenceManager.getDefaultSharedPreferences(Context)
extensively throughout the app I wrote a utility method and replaced all calls of PreferenceManager.getDefaultSharedPreferences(Context)
with this method (see below). The default name of the preferences file is hardcoded and derived from the Android source code and this answer.
public static SharedPreferences getDefaultSharedPreferencesMultiProcess(
Context context) {
return context.getSharedPreferences(
context.getPackageName() + "_preferences",
Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
}
In my case I was trying to access SharedPreferences from a service launched by a BroadcastReceiver.
I removed android:process=":remote"
from the declaration in the AndroidManifest.xml to get it to work.
<receiver
android:process=":remote"
android:name=".Alarm">
</receiver>
Since the SharedPreferences are not process-safe, i wouldn't recommend to use the AbstractThreadedSyncAdapter in another process unless you really need it.
Why do i need multiple processes in my application?
Solution
Remove android:process=":sync"
from the Service that you declared in your manifest!
<service
android:name=".sync.SyncService"
android:exported="true"
android:process=":sync"
tools:ignore="ExportedService" >
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>