在android上保存文件时避免因中断而导致的数据丢失?

我想知道其他人在Android上保存文件时使用什么策略来避免数据丢失。 我有几个游戏应用程序,基本上,只要用户暂停(onPause),它们就可以保存游戏状态/存档游戏。

这种情况在99.99%的情况下有效,但每隔一段时间我就会收到一个存储过程出错的存档游戏示例。 通常,这是一个格式错误的XML文件,通常在某个任意点被截断。 基于我收到的错误报告,我认为问题主要发生在用户在游戏过程中通过电话或其他类似情况中断时,Android操作系统会在应用程序完成保存之前杀死应用程序。 保存文件的代码非常简单,因此我很难看到其他可能导致此问题的原因。

这是一个严重的问题,因为它通常会导致玩家的保存进度被破坏。

我想先写一个空文件,然后再复制到“真实”文件,但我怀疑这只会增加问题,因为它总会花费更多时间,但仍然有被打断的风险。

谁有安全的方法来做到这一点Android相对保证不会搞砸?


总结一下,到目前为止建议的选项(据我所知):

  1. 使用服务进行保存过程,假设操作系统不太可能将其杀死。
  2. 保存在临时文件中; validation保存时复制。
  3. 增量保存游戏状态(我实际上已经将此用于玩家日志信息)。
  4. 2和3的组合。
  5. 将保存移动到另一个线程,因为问题可能是ANR杀死[DC的评论如下]。

我不认为SharedPreferences会对这种结构化数据起作用。目前,这些方法似乎都不是理想的解决方案,所以我仍然愿意接受建议。


我还没有设法测试所有这些方法,所以我没有浪费赏金,而是将其分配给我认为最有可能解决问题的答案。 不过,我计划在接受答案之前检查各种选项。 感谢所有好的建议。

我认为每次用户执行任何操作时(不仅在调用onPause()时),将数据的小部分(不是整个游戏状态)保存到数据库中将是这种情况下的最佳方法。 但是,这可能需要对代码进行大量修改。

折衷方案是将游戏状态分成更小的部分或子状态(比方说, round1round2 ,……, players等),并在用户执行任何操作时再次将数据存储到适当的文件,而不是等待onPause()打电话。 这将显着降低丢失的可能性,并且至少可以保证用户不会失去整个游戏进度。 此外,为了避免在保存过程中断时可能出现的应用程序状态不一致,您最好先将数据保存到临时文件,只有在成功的情况下才重命名文件,而不是复制其内容(比方说, round1.xml.tmp重命名为round1.xml )。

这对于服务来说听起来不错。

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

当我们从主线程进行持久存储(内部存储器上的私有文件系统)的I / O(通常是写入)时,我们偶尔会遇到问题。 通常这并不需要花费太多时间,但偶尔会花费很长时间(20或30秒或更长时间)。 似乎某些设备上的Android文件系统实现不支持并发访问(请参阅此内容 ,因此如果另一个进程正在使用文件系统,则I / O可能会阻塞。如果您在主线程上执行I / O,则操作系统如果它阻塞了太长时间,可以/将会杀死你的活动。这可能是你发生的事情。

由于这个问题,我建议你将所有的I / O移动到一个单独的线程(而不是主线程)。 因此,例如,为了保存游戏状态,在onPause()中调用一个方法,将游戏状态序列化为ByteArrayOutputStream,然后将其移交给最终写入文件系统的单独线程。

如果可能,使用SharedPreferences存储您的游戏状态。 只有在调用commit()后才会commit()更改。 您可以在onSaveInstanceState回调中进行保存。 阅读这里的文档。

首先,我会尝试看看应用程序是否真的被杀死而没有通知,因为我不认为应该是这种情况。 应用程序可能会因为电话等问题而被停止,但我并不认为安卓只是在没有任何通知的情况下将其删除。 它可以决定结束它,但不是没有保存状态等。

也许保存本身只会发生错误。

一种不需要太多修改的方法来检查是使用校验和还是使用其他方法来validation保存数据的完整性(大小,结束标记等)。 您所要做的就是保存,阅读并检查(记录任何错误)并重复该操作直至其正确。 如果您保存大量数据可能不是那么好,但仅仅是游戏数据它应该没问题。

您还可以在应用程序开始和结束时设置状态,然后在下次启动时知道最后一次是否正确结束以及是否必须采取额外措施。