Database Android corrotto, ma può essere aperto in SQLite Manager. Recuperabile?

Nelle ultime due settimane, senza rilasciare un aggiornamento alla mia app, ho iniziato a ricevere un sacco di report con database danneggiati. Di seguito è riportato lo stacktrace. Android non può aprire il database e nemmeno il programma sqlite-manager sul mio computer. Tuttavia, il gestore di SQLite-addon di Firefox potrebbe aprirlo. Dopo aver eseguito il comando “database compatto”, il database è stato risolto e potrei aprirlo in Android. C’è un modo per fare qualcosa di simile nella mia app? Il grosso problema è che non riesco nemmeno a tentare di aprire il database, perché le versioni più recenti di Android elimineranno e sostituiranno immediatamente il database, come puoi vedere nello stacktrace sottostante. Le dichiarazioni di PRAGMA possono essere eseguite in qualche modo senza aprire il database?

Saluti,

02-22 09:55:20.245: ERROR/Database(5382): CREATE TABLE android_metadata failed 02-22 09:55:20.245: ERROR/Database(5382): Failed to setLocale() when constructing, closing the database 02-22 09:55:20.245: ERROR/Database(5382): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformsd 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1950) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.(SQLiteDatabase.java:1818) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844) 02-22 09:55:20.245: ERROR/Database(5382): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540) 02-22 09:55:20.245: ERROR/Database(5382): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203) 02-22 09:55:20.245: ERROR/Database(5382): Deleting and re-creating corrupt database /mnt/sdcard/myapp/backup.sqlite 02-22 09:55:20.245: ERROR/Database(5382): android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformsd 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1950) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.(SQLiteDatabase.java:1818) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851) 02-22 09:55:20.245: ERROR/Database(5382): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844) 02-22 09:55:20.245: ERROR/Database(5382): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540) 02-22 09:55:20.245: ERROR/Database(5382): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203) 

Modifica: I manager per aprire il database in questo modo:

 db = SQLiteDatabase.openDatabase(database, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 

Ma quando eseguo questo:

 String sqlQuery = "pragma integrity_check"; db.execSQL(sqlQuery); 

Ho capito:

 ERROR/AndroidRuntime(9144): Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformsd: pragma integrity_check 

Edit2: mi sono reso conto che passare l’aspirapolvere al database risolve il problema. Ma se vuoto dall’interno della mia app, con exeSQL (“vuoto”), non aiuta. Perchè è questo? : ‘(

Il buon metodo canonico per recuperare un database corrotto consiste nel scaricarlo come SQL e quindi rileggerlo in un nuovo database. È semplicissimo con lo strumento sqlite:

 sqlite in.db .dump | sqlite out.db 

… ma, naturalmente, è necessario farlo in codice, e davvero non so se .dump è disponibile da qualsiasi luogo.

Ti suggerirei di volere guardare in che modo si sta corrompendo in primo luogo — SQLite è sempre stato solido per me, anche se l’ho sempre usato nella memoria interna. Puoi controllare il filesystem FAT per vedere se è corrotto? Ho visto, ad esempio, fotocamere digitali che maneggiano il filesystem su tabs in vari modi oscuri …

Android che cancella il database è davvero un problema .

Ho appena realizzato che una soluzione potrebbe essere l’uso di SQLJet invece dell’implementazione predefinita di SQL SQLite.
Poiché il nome non suggerisce, SQLJet è un client SQLite Java open source e funziona su Android.

Nella tua app chiudi il database prima di uscire dall’attività? Guarda il logcat e controlla se ci sono errori o avvisi quando esegui la tua app.