AndroidのOS /ユーザーによるゲームのクラッシュ/キルでのファイル操作の失敗


13

私のゲームは、ゲーム/アプリの内部ストレージのファイルに一定の間隔で状態を保存します。ゲームがユーザーまたはOSによってそれぞれ強制終了またはクラッシュした場合、そのファイルに現在のゲーム状態を書き込みます。修正間隔後のファイル書き込みは正常に機能していますが、ゲームがOSまたはユーザーによってクラッシュまたは強制終了された場合、ファイル書き込み操作は失敗します。操作が失敗すると、不完全なゲーム状態または空のゲーム状態、つまりファイルにデータがまったく書き込まれません。私は、Androidサービスを使用して複数のソリューションを試しました。サービスがNON STICKYの場合は、アプリで強制終了されます。一方、サービスがSTICKYの場合、サービスは再起動されますが、最初にサービスでアタッチされたインテントはnullまたは新しいものです。

問題は、ゲーム/アプリがユーザー/ OSによって強制終了されたときに、内部ストレージのファイルにデータを完全に保存するにはどうすればよいですか(最大2〜3MB)。


SIGTERMとSIGKILLを処理する必要があります(おそらくSIGKILLではなく、AndroidはおそらくSIGTERMを使用しています)。(調査する時間はありません/完全な答えを書くことはできませんが、それは基本的な考え方です。)
ジョンハミルトン

2
@JohnHamilton SIGKILLは、定義により処理できません。
ダークホッグ

@Darkhoggまあ、Unityではなく、それは確かです。(この特定の目的のためにプロジェクトのLinuxカーネルを一時変更しました。プログラムにSIGKILLを処理させることは確かに可能です)
ジョンハミルトン

回答:


20

過去のコンソールタイトルで一般的だったように、保存状態をダブルバッファ方式で書き込むことをお勧めします(書き込み中にメモリカードが取り外され、書き込みが遅い場合)。

セーブ:

  • ファイルが存在しない場合、ファイルAに状態を書き込みます
  • Aが存在する場合、Bに書き込みます
  • AとBの両方が存在する場合、どちらが古いかを見つけて削除し、その1つに書き込みます

負荷:

  • AとBの両方が存在する場合は、2つのうち新しい方をロードしてください。それが失敗する場合(ファイルが不完全または破損しているため)、それを削除し、もう一方をロードします
  • 存在する場合は、それをロードします
  • 両方が破損している場合は、保存状態が回復不能であることをユーザーに通知します(おそらく既にそうであるように)

このフローは、アプリが書き込み中に強制終了された場合でも、常に少なくとも1つの有効な保存がストレージに存在することを保証するために機能します。そのような失敗が発生した場合、プレーヤーは前回の保存以降のゲーム状態の変更を取得しませんが、再度開始する必要はありません。

さらに、間隔の保存に加えて、キーイベント(アプリ内購入など)の直後に保存して、クラッシュ/キルによってそのキーイベントが失われる脆弱性のウィンドウを最小限に抑える必要があります。これは、ゲームの悪用に対する保護でもあります(たとえば、命を失う前にアプリを強制終了するのは、命を失う前からゲーム状態に戻り、再試行できるためです)。もちろん、これを行う場合は、「保存がすでに進行中の場合は、保存を再開しないでください」というロジックでインターバル保存を保護する必要があります。


MrCrankyに感謝します。これは私の問題の部分的な解決策です。最後のセッション、つまりアプリ/ゲームを終了する直前のデータをどのように保存できますか?たとえば、彼はアプリ内購入を行い、アプリを殺しました。
ファイサルイムラン

12
2つのファイルも必要ありません。書き込みが成功した場合にのみ、Bに書き込みます。Aを削除し、BをAに名前変更します。名前java.nio.file.Files.move(Path source, Path target, CopyOption... options)変更と上書きはアトミック操作として実行できます。
ポリグノーム

6
@Polygnome:電源障害の場合、sync()ファイルAに移動する前にファイルB を呼び出す場合を除き、これは常に期待する保証を提供するわけではないことに注意してください(完全な保証はありませんが、sync()かなり良いです)。
ディートリッヒエップ

1
@FaisalImran重要な操作の直後、たとえばIAPの後にデータを保存します。電話をオフにすることによって操作が中断された場合、とにかく人からお金を奪うことはないと思います。ただし、念のため、何かを購入する試みとして、何らかのプラットフォームでの購入に彼のアカウントデータを保存したい場合があります。その後、収益をそのデータと比較して、この人が本当に何かを購入したかどうかを確認できます。そして、すべてのデータを保存するために使用しているオンラインサービスを介して彼のためにこの機能を開きます。IAPにローカル保存を使用している場合、この問題よりもさらにひどいです。
率直な月_Max_

1
最後に、これですべての問題を解決できるわけではありませんが、問題は完全には解決できないと思います。「ユーザーはいつでもアプリを強制終了できます」と「データが失われることはありません」の両方をサポートすることはできません。アプリを強制終了してデータを失う可能性があります。
MrCranky

3

Androidは、アプリがバックグラウンドにあるときにのみアプリを強制終了します。アプリがバックグラウンドにあるときにゲームデータを本当に更新する必要がありますか、またはアプリがフォアグラウンドに戻るまでデータの更新を停止できますか?イベントの履歴や、アプリがフォアグラウンドに戻ったときの現在の状態を取得できる場合は、マルチプレイヤーゲームでも更新を延期できる場合があります。これは、CPU、ネットワーク、およびバッテリーの効率のために、とにかく実行する必要があると思われるものです。

ユーザーがアプリを強制終了した場合、実行中のサービスはへの呼び出しを受け取る必要がありますonTaskRemoved。このメソッドで多くの処理を行おうとするとどうなるかわかりません。一定時間内に戻らない場合は、Androidがkill -9アプリを提供することを期待しています。


アプリはバックグラウンドで更新する必要はありませんが、アプリはデータを保存する必要があります。つまり、バックグラウンドまたは破棄する前にjsonファイルを保存する必要があります。
ファイサルイムラン

onTaskRemovedメソッドが呼び出されますが、ファイルを保存するのに必要な時間が長くなるか、計算時間が長いと言えます。ユーザーがアプリを強制終了すると、このメソッドは停止します。
ファイサルイムラン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.