2012-04-20 11 views
14

Mi chiedo quali strategie altri usano per evitare la perdita di dati durante il salvataggio di file su Android. Ho un paio di app di gioco che, essenzialmente, salvano potenzialmente lo stato/il salvataggio del gioco ogni volta che l'utente fa una pausa (onPause).Evitare la perdita di dati dovuta all'interruzione durante il salvataggio dei file su Android?

Questo funziona nel 99,99% dei casi, ma ogni tanto ricevo un esempio di salvataggio in cui il processo di salvataggio è andato storto. Di solito, questo è un file XML mal formato, tipicamente troncato in un punto arbitrario. Sulla base delle segnalazioni di bug che ricevo, credo che il problema si verifica soprattutto quando l'utente viene interrotto durante il gioco da una telefonata o qualcosa del genere e il sistema operativo Android uccide l'app prima che possa terminare il salvataggio. Il codice per il salvataggio dei file è piuttosto semplice, quindi ho difficoltà a vedere quale altro potrebbe causare questo problema.

Questo è un problema serio, perché di solito porta a rovinare i progressi di salvataggio del giocatore.

Stavo pensando di scrivere prima su un file vuoto, e poi copiare sul file "reale" solo dopo, ma sospetto che ciò aumenterebbe semplicemente il problema poiché in generale ci vorrà più tempo e rischia ancora di essere interrotto.

Chiunque abbia un modo sicuro di fare ciò con Android è relativamente garantito da non rovinare?


Così riassunto, le opzioni suggerite finora (come li capisco):

  1. utilizzare un servizio per il processo di salvataggio, sul presupposto che questo sarà meno probabilità di essere uccisi dal OS.
  2. Salva nel file temporaneo; copia su quando il salvataggio è verificato.
  3. Salvataggio incrementale dello stato del gioco (in realtà lo utilizzo già per le informazioni del registro del lettore).
  4. Combinazione di 2 & 3.
  5. Spostare il salvataggio su un altro thread, poiché il problema potrebbe essere con ANR uccide [commenti DC in basso].

Non credo che SharedPreferences funzionerà per questo tipo di dati strutturati. Al momento, nessuno di questi metad mi sembra una soluzione ideale, quindi sono ancora aperto a suggerimenti.


non ho ancora riuscito a testare tutti questi approcci, così piuttosto che sprecare la generosità, ho assegnato alla risposta che mi sento sarebbe più probabilità di risolvere il problema. Ho intenzione di verificare ancora le varie opzioni, prima di accettare una risposta. Grazie per tutti i buoni suggerimenti.

+0

È troppi dati da salvare in 'SharedPreference'? – Ronnie

+0

Sì - circa 20K di dati in XML. potrebbe non essere un grosso problema (non ho provato), ma la struttura piuttosto complessa dei dati sarebbe, credo. –

+0

Come stai salvando lo stato del gioco in 'onPause()'? Stai facendo I/O sul thread principale (UI)? Dove stai salvando lo stato del gioco (su scheda SD o altra posizione)? –

risposta

2

Credo che il risparmio piccole porzioni di dati (non l'intero stato del gioco) al database ogni utente volta esegue alcuna azione (non solo quando onPause() viene chiamato) sarebbe la soluzione migliore in questo caso. Tuttavia, questo potrebbe richiedere molte modifiche al codice.

Il compromesso potrebbe essere quella di dividere lo stato del gioco in porzioni più piccole o sub-stato (diciamo, round1, round2, ..., players, ecc) e di nuovo memorizzare dati in file opportune l'utente esegue qualsiasi azione, non aspettando la chiamata onPause(). Ciò ridurrebbe significativamente la probabilità di perdita e almeno garantirebbe che l'utente non perda l'intero avanzamento del gioco. Inoltre, per evitare stati incoerenti della tua app, che possono apparire quando il processo di salvataggio viene interrotto, è meglio salvare i dati in un file temporaneo e solo in caso di successo semplicemente rinominare il file, non copiarne il contenuto (diciamo, round1.xml.tmp rinomina a round1.xml).

4

Questo sembra un buon lavoro per un servizio.

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

+0

A quanto ho capito, un servizio può anche essere forzato ad essere forzato, ed è connesso al processo che l'ha avviato. Non è sicuro che ciò sarà di grande aiuto, in tal caso, poiché il problema sembra essere causato da un sistema operativo Android che uccide forzatamente l'app. –

+0

Un servizio viene eseguito in background, il sistema operativo sta sicuramente uccidendo la tua app. Forse dovresti considerare questo suggerimento ... – Kickaha

+0

Qualsiasi cosa può essere uccisa dal sistema operativo, tuttavia, credo ancora che un servizio sia quello che vuoi usare. –

0

Se possibile, utilizzare SharedPreferences per memorizzare lo stato del gioco. Le modifiche verranno confermate solo dopo aver chiamato commit(). È possibile effettuare il salvataggio nella richiamata onSaveInstanceState. Leggi il docs here.

0

Prima di tutto vorrei provare a vedere se l'app è stata davvero uccisa senza notifica perché non penso che dovrebbe essere il caso. Le app potrebbero essere bloccate per qualcosa come una telefonata, ma non penso che Android lo stia semplicemente uccidendo senza alcuna notifica. Potrebbe decidere di terminarlo, ma non senza salvare lo stato, ecc.

Forse c'è solo un errore che si verifica con il salvataggio stesso.

Un modo che non richiede molte modifiche per controllare che sarebbe utilizzare un checksum o utilizzare un altro modo per verificare l'integrità dei dati salvati (dimensione, marcatore finale, ecc.). Tutto quello che devi fare è salvarlo, leggerlo e controllarlo (registra eventuali errori) e ripeterlo fino alla sua corretta. Potrebbe non essere così buono se si salvano grandi quantità di dati, ma per il semplice gamedata dovrebbe essere tutto a posto.

È inoltre possibile impostare uno stato all'avvio e alla fine dell'app, quindi si saprà al prossimo avvio se è terminato correttamente l'ultima volta o meno e se si devono prendere ulteriori misure.

+0

È difficile esserne certi, dal momento che non sono in grado di ricreare la situazione da solo. Ma tutti i rapporti confermati che ho ricevuto con questo tipo di problema sono stati in genere casi in cui l'utente è stato interrotto da una telefonata o qualcosa di simile. –

+0

Sono abbastanza sicuro che non ci siano errori con il salvataggio stesso; l'API XML non dovrebbe essere in grado di scrivere file troncati di questo tipo in circostanze normali. –

3

Abbiamo avuto problemi occasionali durante l'esecuzione di I/O (in genere in fase di scrittura) su memoria persistente (file system privato nella memoria interna) dal thread principale. Di solito questo non richiede molto tempo, ma a volte inspiegabilmente richiede anni (20 o 30 secondi o più). Sembra che le implementazioni del filesystem Android su alcuni dispositivi non supportino l'accesso simultaneo (vedi this, così il tuo I/O può bloccare se un altro processo sta usando il filesystem. Se stai facendo il tuo I/O sul thread principale, il SO può/ucciderà la tua attività se bloccherà troppo a lungo Questo potrebbe essere quello che ti sta succedendo

A causa di questo problema, ti suggerirei di spostare tutto il tuo I/O su un thread separato (non il principale thread) Quindi, per esempio, per salvare lo stato del gioco, in onPause() chiama un metodo che serializza lo stato del gioco in un ByteArrayOutputStream che poi passi a un thread separato da scrivere sul filesystem.

+0

Sembra abbastanza interessante; certamente qualcosa che dovrò esaminare. –

Problemi correlati