SharedPreference, установленное в SyncAdapter, не обновлено в Activity?

Я изменяю и передаю SharedPreference в моем SyncAdapter после успешной синхронизации, но я не вижу обновленного значения, когда получаю доступ к предпочтению в своей работе (скорее, я вижу старое значение). Что я делаю не так? Разные контексты?

Мой SyncAdapter, где я обновляю предпочтение:

class SyncAdapter extends AbstractThreadedSyncAdapter { private int PARTICIPANT_ID; private final Context mContext; private final ContentResolver mContentResolver; public SyncAdapter(Context context, boolean autoInitialize) { super(context, autoInitialize); mContext = context; mContentResolver = context.getContentResolver(); } public SyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) { super(context, autoInitialize, allowParallelSyncs); mContext = context; mContentResolver = context.getContentResolver(); } @Override public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); PARTICIPANT_ID = Integer.parseInt(prefs.getString("participant_id", "0")); if (success) { // save and set the new participant id PARTICIPANT_ID = newParticipantId; prefs.edit().putString("participant_id", String.valueOf(newParticipantId)).commit(); } } } 

Служба, инициализирующая SyncAdapter с помощью ApplicationContext:

 public class SyncService extends Service { private static final Object sSyncAdapterLock = new Object(); private static SyncAdapter sSyncAdapter = null; @Override public void onCreate() { synchronized (sSyncAdapterLock) { if (sSyncAdapter == null) { sSyncAdapter = new SyncAdapter(getApplicationContext(), false); } } } @Override public IBinder onBind(Intent intent) { return sSyncAdapter.getSyncAdapterBinder(); } } 

Статическая функция в приложении, вызываемая Activity, которая проверяет SharedPreference. Это не возвращает значение, зафиксированное в SyncAdapter, но старое значение. (Мои настройкиActivity и другие действия также используют старое значение.):

 public static boolean isUserLoggedIn(Context ctx) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx); int participantId = Integer.parseInt(prefs.getString("participant_id", "0")); LOGD("dg_Utils", "isUserLoggedIn.participantId: " + participantId);// TODO if (participantId <= 0) { ctx.startActivity(new Intent(ctx, LoginActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)); return false; } return true; } 

UPDATE: я получаю новое значение, когда полностью закрываю приложение (проведите его по экрану из приложений). У меня также есть SharedPreferenceChangeListener, который не запускается, когда предпочтение обновляется.

 private final SharedPreferences.OnSharedPreferenceChangeListener mParticipantIDPrefChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { if (key.equals("participant_id")) { LOGI(TAG, "participant_id has changed, requesting to restart the loader."); mRestartLoader = true; } } }; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // subscribe to the participant_id change lister final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); PARTICIPANT_ID = Integer.parseInt(prefs.getString("participant_id", "0")); prefs.registerOnSharedPreferenceChangeListener(mParticipantIDPrefChangeListener); } 

Solutions Collecting From Web of "SharedPreference, установленное в SyncAdapter, не обновлено в Activity?"

Хорошо, я понял это с помощью @Titus и после некоторых исследований и собрал решение для своей проблемы.

Причина, почему DefaultSharedPreferences одного и того же Context не обновляется, заключается в том, что я указал SyncService для запуска в своем собственном процессе в AndroidManifest.xml (см. Ниже). Следовательно, начиная с Android 2.3, другой процесс блокируется от доступа к обновленному файлу SharedPreferences (см. Этот ответ и документы Android в 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> 

Поэтому мне пришлось установить MODE_MULTI_PROCESS при доступе к SharedPreferences как в SyncAdapter и в процессе пользовательского интерфейса моего приложения. Поскольку я широко использовал PreferenceManager.getDefaultSharedPreferences(Context) во всем приложении, я написал метод утилиты и заменил все вызовы PreferenceManager.getDefaultSharedPreferences(Context) с помощью этого метода (см. Ниже). Имя файла настроек по умолчанию является жестко запрограммированным и выводится из исходного кода Android и этого ответа .

 public static SharedPreferences getDefaultSharedPreferencesMultiProcess( Context context) { return context.getSharedPreferences( context.getPackageName() + "_preferences", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS); } 

Поскольку SharedPreferences не являются безопасными для процесса, я бы не рекомендовал использовать AbstractThreadedSyncAdapter в другом процессе, если вам это действительно не нужно.

Зачем мне нужно несколько процессов в моем приложении?

Решение

Удалите android:process=":sync" из Сервиса, который вы заявили в своем манифесте!

 <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> 

В моем случае я пытался получить доступ к SharedPreferences из службы, запущенной BroadcastReceiver.

Я удалил android:process=":remote" из объявления в AndroidManifest.xml, чтобы заставить его работать.

 <receiver android:process=":remote" android:name=".Alarm"> </receiver>