SharedPreference committed in SyncAdapter not updated in Activity?

喜夏-厌秋 提交于 2019-12-04 00:09:18
matsch

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);
}

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>

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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!