Intereting Posts
Как тренировать сеть тензорного потока с использованием JNI на Android? Цель CONNECTIVITY_ACTION получена дважды при подключении Wi-Fi Предел макета листа в Android Как переключаться между портретным и ландшафтным режимом с помощью libGDX? Как разместить вертикально ViewPager в горизонтальном режиме ViewPager Почему между CardViews на Lollipop нет места? Как обмениваться изображениями с моим приложением в whatsapp? NumberPicker не отображается в AlertDialog Ошибка Android Studio: Ошибка: CreateProcess error = 216, эта версия% 1 несовместима с версией Windows, в которой вы работаете Можно ли использовать adb для имитации 3 длинных кранов на устройстве? Экспортированная служба не требует разрешения: что это значит? Java.lang.OutOfMemoryError: размер растрового изображения превышает бюджет VM – андроид – сколько изображений? Изменение яркости экрана в программном обеспечении Android Нарисовать прозрачную форму на холст Значение по умолчанию для resultCode, когда активность завершается

Избежать потери данных из-за прерывания при сохранении файлов на Android?

Мне интересно, какие стратегии используют другие, чтобы избежать потери данных при сохранении файлов на Android. У меня есть несколько игровых приложений, которые, по сути, потенциально сохраняют состояние игры / savegame всякий раз, когда пользователь делает паузу (onPause).

Это работает в 99,99% случаев, но каждый раз в то время я получаю пример savegame, в котором процесс сохранения поступил неправильно. Обычно это плохо сформированный XML-файл, обычно усеченный в некоторой произвольной точке. Основываясь на отчетах об ошибках, которые я получаю, я считаю, что проблема в основном возникает, когда пользователь прерывается во время игры с помощью телефонного звонка или что-то в этом роде, а ОС Android затем убивает приложение, прежде чем он сможет завершить сохранение. Код для сохранения файлов довольно прост, поэтому мне трудно понять, что еще может вызвать эту проблему.

Это серьезная проблема, потому что это обычно приводит к разрушению прогресса игрока.

Сначала я подумывал писать в пустой файл, а затем копировать в «настоящий» файл только после этого, но я подозреваю, что это просто увеличит проблему, так как в целом это займет больше времени и все еще рискует прерваться.

Любой, у кого есть безопасный способ сделать это, что Android относительно гарантированно не испортить?


Итак, варианты, предложенные до сих пор (как я их понимаю):

  1. Используйте сервис для процесса сохранения, исходя из предположения, что это будет менее вероятно, чтобы быть убитым ОС.
  2. Сохранить во временном файле; Копировать, когда сохранение подтверждено.
  3. Инкрементное сохранение состояния игры (я на самом деле уже использую это для информации журнала игрока).
  4. Комбинация 2 и 3.
  5. Переместите сохранение в другой поток, так как проблема может быть с ANR убивает [комментарии DC ниже].

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


Мне еще не удалось протестировать все эти подходы, поэтому вместо того, чтобы тратить щедрость, я назначил его на ответ, который, как я считаю, с большей вероятностью разрешит проблему. Однако я планирую проверить различные варианты, прежде чем принимать ответ. Спасибо за все хорошие предложения.

Я думаю, что сохранение небольшого количества данных (а не целого состояния игры) в базу данных каждый раз, когда пользователь выполняет какое-либо действие (не только при onPause() ), это лучший подход в этом случае. Однако для этого может потребоваться много изменений кода.

Компромисс заключался бы в том, чтобы разделить состояние игры на более мелкие части или под-состояния (скажем, round1 , round2 , …, players и т. Д.) И снова хранить данные в соответствующих файлах, когда пользователь выполняет какое-либо действие, не дожидаясь onPause() . Это значительно уменьшит вероятность потери и, по крайней мере, гарантирует, что пользователь не потеряет весь ход игры. Кроме того, во избежание непоследовательных состояний вашего приложения, которое может появиться при прерывании процесса сохранения, вам лучше сначала сохранить данные во временный файл, и только в случае успеха просто переименуйте файл, а не round1.xml.tmp его содержимое (скажем, round1.xml.tmp переименовать в round1.xml ).

Это звучит как хорошая работа для службы.

http://developer.android.com/reference/android/app/Service.html

У нас были случайные проблемы, когда мы делали ввод-вывод (обычно записывая) в постоянное хранилище (частная файловая система во внутренней памяти) из основного потока. Обычно это не занимает много времени, но иногда необъяснимо требуется возраст (20 или 30 секунд или более). Похоже, что реализация файловой системы Android на некоторых устройствах не поддерживает одновременный доступ (см. Это , поэтому ваш I / O может блокировать, если другой процесс использует файловую систему. Если вы делаете свой ввод-вывод в основном потоке, ОС Может / будет убивать вашу активность, если она слишком долго блокируется. Возможно, это может произойти с вами.

Из-за этой проблемы я предлагаю вам переместить все ваши входы / выходы в отдельный поток (а не основной поток). Так, например, чтобы сохранить состояние игры, в onPause () вызывается метод, который сериализует состояние игры в ByteArrayOutputStream, который затем передается отдельному потоку, который в конечном итоге будет записан в файловую систему.

Если возможно, используйте SharedPreferences для сохранения состояния игры. Ваши изменения будут совершены только после вызова commit() . Вы можете выполнить сохранение в onSaveInstanceState . Прочтите документы здесь.

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

Возможно, есть ошибка, которая возникает при сохранении самой.

Способ, который не требует большой модификации, чтобы проверить, что будет использовать контрольную сумму, или использовать другой способ проверки целостности сохраненных данных (размер, конечный маркер и т. Д.). Все, что вам нужно сделать, это сохранить его, прочитать и проверить (запишите любые ошибки) и повторите это до тех пор, пока оно не будет правильно. Возможно, это не так хорошо, если вы сохраняете большие объемы данных, но для простых gamedata все должно быть в порядке.

Вы также можете установить состояние, когда приложение запустится и закончится, а затем вы узнаете о следующем запуске, если он закончится правильно в прошлый раз или нет, и если вам нужно принять дополнительные меры.