SharedPreferences не обновляется

У меня возникает странная проблема, при которой SharedPreferences не обновляются при возврате в приложение. Здесь сценарий:

У меня есть два проекта, которые используют одни и те же общие настройки. Project1 и Project2. Это отдельные, но связанные приложения. Они подписываются с тем же ключом и используют sharedUserId для обмена информацией.

Project1 открывает Project2.

Project2 извлекает файл SharedPreferences и записывает его с помощью этого метода:

Context prefsContext = c.createPackageContext(packageNameOfProject1, Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences prefs = prefsContext.getSharedPreferences(fileName, Context.MODE_PRIVATE);
SharedPreferences.editor editor = prefs.edit();
editor.putBool("bool1", value1);
editor.putBool("bool2", value2);
...
editor.putBool("boolN", valueN);
editor.apply();

Как только это будет сделано, я вернусь к Project1, вызвав finish().

Project1 затем считывает данные следующим образом:

SharedPreferences prefs = getSharedPreferences(getPreferencesFileName(), Context.MODE_PRIVATE);
Boolean value1 = prefs.getBoolean(fileName, false);
Boolean value2 = prefs.getBoolean(fileName, false);
...
Boolean valueN = prefs.getBoolean(fileName, false);
Map<String, ?> mappings = prefs.getAll();
Set<String> keys = mappings.keySet();
for(String key : keys) {
  log.d(TAG, "_____");
  log.d(TAG, "Key = " + key);
  log.d(TAG, "Value = " + mappings.get(key));
}

Проблема заключается в том, что значения не обновляются в Project1. Я могу сказать, основываясь на журналах в конце, что файл даже не генерирует сопоставления. Тем не менее, я могу проверить, что xml обновляется. Если я принудительно остановлю приложение, перезапустите его, все сопоставления находятся в Project1. Все значения верны. Тем не менее, они мне нужны, когда пользователь покидает Project2. Я чувствую, что там что-то мне не хватает, но не могу это заметить.

Единственное, что я смог найти по этому вопросу:

SharedPreferences.Editor не обновляется после первоначальной фиксации

Значение SharedPreferences не обновляется

Это не помогает, поскольку я уже это делаю.

У меня есть WRITE_EXTERNAL_STORAGE, установленный в обоих манифестях. Имя файла одинаково (иначе я не смог бы прочитать файл при входе в приложение).

EDIT:

Я должен отметить, что я попытался сделать editor.commit() вместо editor.apply(), поскольку я думал, что столкнулся с состоянием гонки. Проблема все еще сохранялась. Я думаю, что по какой-то причине старая ссылка на SharedPreference в Project1 используется вместо новой, хотя я лениво загружаю ее каждый раз.

EDIT2:

Хорошо, чтобы еще раз проверить, что происходит с идентификатором. Я решил попробовать противоположное направление.

В Project1 я:

Float testFloat (float) Math.random();
Log.d("TEST_FLOAT", "Project1: TEST_FLOAT = " + testFloat);
prefs.edit().putFloat("TEST_FLOAT", testFloat).commit();

В Project2 я:

Log.d("TEST_FLOAT", "Project2: TEST_FLOAT = " + prefs.getFloat("TEST_FLOAT", 0.0f));

Затем я перехожу туда и обратно между ними так: Project1->Project2->Project1->Project2->Project1->Project2 и вот результат logcat:

Project1: TEST_FLOAT = 0.30341884
Project2: TEST_FLOAT = 0.30341884
Project1: TEST_FLOAT = 0.89398974
Project2: TEST_FLOAT = 0.30341884
Project1: TEST_FLOAT = 0.81929415
Project2: TEST_FLOAT = 0.30341884

Другими словами, это чтение и запись в один и тот же файл. Тем не менее, он сохранил отображение, которое оно имело, когда оно было впервые открыто в проекте. Несмотря на то, что я закрываю проект, отображение остается до тех пор, пока приложение не будет остановлено.

Ответ 1

Окончательный ответ:

Заменить

getSharedPreferences(fileName, Context.MODE_PRIVATE);

с

getSharedPreferences(fileName, Context.MODE_MULTI_PROCESS);

В соответствии с документом:

Context.MODE_MULTI_PROCESS

Флаг загрузки SharedPreferences: при установке файл на диске будет проверяется на модификацию, даже если экземпляр общих предпочтений уже загружен в этот процесс. Такое поведение иногда требуется в случаи, когда приложение имеет несколько процессов, все записи в тот же файл SharedPreferences. Как правило, существуют лучшие формы связь между процессами.

Это было наследие (но недокументированное) поведение в и до Gingerbread (Android 2.3), и этот флаг подразумевается при таргетинге таких выпусков. Для приложений, ориентированных на версии SDK, превышающие Android 2.3 (Gingerbread), этот флаг должен быть явно установлен по желанию.

Я знал, что в этом есть простой надзор.

Ответ 2

Попробуйте вызвать editor.commit(); вместо editor.apply();. Обычно они должны делать то же самое, но иногда я заметил там какое-то странное поведение.

Ответ 3

В документации SharedPreferences метод "apply()" записывает асинхронно (задерживается) в файл, а метод "commit()" записывает информацию синхронно (немедленно) в файл.

Также из документации говорится, что вам не нужно опасаться жизненного цикла деятельности при использовании любого из вышеуказанных методов, поскольку они гарантируют, что записи "apply()" будут завершены до изменения состояния, если они работающих в одном и том же системном процессе.

Однако, поскольку вы используете два разных проекта, они запускаются в двух разных процессах, и вы не можете быть уверены, что "apply()" в проекте 2 будет завершен до того, как "onResume()" начнется в проекте 1.

Я предлагаю вам попробовать "commit()" вместо "apply()" для принудительной синхронной записи. Если это не решит проблему, вы можете добавить задержку в пару секунд, прежде чем читать настройки в проекте 1, просто чтобы проверить, связана ли проблема с этой задержкой записи.

- EDITED -

Чтобы отладить проблему, сделайте следующее:

1-In Eclipse Выберите/добавьте представление "Проводник" и перейдите в каталог:

/data/data/[имя вашего пакета]/shared_prefs

ваше имя пакета должно быть чем-то вроде "com.myproject.shared"

2. Выберите файл с сохраненными настройками и нажмите кнопку "загрузить на ПК".

3 - Проверьте, соответствует ли содержимое файла вашим ожиданиям.

удачи.