update tabla studio registros registro que onupgrade insertar execsql ejemplo datos crear buscar borrar android sqlite

tabla - ¿Qué se puede hacer sobre el hecho de que Android elimina automáticamente los archivos corruptos de SQLite?



que es sqlite android (4)

Cuando Android abre un archivo SQLite y el archivo está dañado, Android elimina el archivo.

Por sorprendente que parezca, este comportamiento se implementa claramente en el código fuente de Android, lo que lleva a la consternation y a este problema de Android .

De todos modos, como desarrolladores de aplicaciones solo tenemos que lidiar con eso. ¿Cuál es la mejor estrategia al abrir un archivo SQLite?

  • Los archivos corruptos a menudo son recuperables, por lo que no podemos correr el riesgo de perder uno de esos archivos corruptos.
  • Crear una copia de seguridad antes de abrirla es muy costoso y haría que el inicio de la aplicación fuera muy lento, por lo que cualquier cosa más inteligente sería muy apreciada.

El problema se ha solucionado a partir del nivel de API 11. Ahora existe una interfaz: DatabaseErrorHandler que puede implementar para definir su propio método onCorruption () . En la apertura de su base de datos, puede pasar este DatabaseErrorHandler como un parámetro al constructor de SQLiteOpenHelper .

p.ej

public class MyDbErrorHandler implements DatabaseErrorHandler { @Override onCorruption(SQLiteDatabase db) { // Back up the db or do some other stuff } } SQLiteOpenHelper dbHelper = new SQLiteOpenHelper(context, "MyDbName", null, 1, new MyDbErrorHandler()); SQLiteDatabase db = dbHelper.getWritableDatabase();

Para los sistemas con un nivel de API inferior a 11 y para aquellos que no desean utilizar este enfoque, existen varias alternativas.

1. Copia de seguridad de datos de Android

Android ofrece un servicio de respaldo que copia automáticamente los datos de la aplicación a un almacenamiento remoto en "nube". Si una base de datos se corrompe o la aplicación se vuelve a instalar después del restablecimiento de fábrica. Los datos de la aplicación se pueden restaurar desde los datos remotos.

Para obtener más información, consulte: http://developer.android.com/guide/topics/data/backup.html

2. JDBC (sqldroid)

Un enfoque podría ser implementar su propio conector de base de datos, ya sea JDBC nativo o con la biblioteca sqldroid . Google no lo admite oficialmente y no puede estar seguro de si seguirá estando disponible en futuras versiones de Android.

3. Berkley DB Java Edition

Un enfoque interesante, también con una mirada al rendimiento que maneja grandes cantidades de datos, es la Berkley DB Java Edition .

Aquí hay un tutorial sobre cómo usarlo en Android: http://download.oracle.com/docs/cd/E17277_02/html/HOWTO-Android.html

4. Personalizando las bibliotecas de Android

Otro enfoque más arriesgado es implementar su propia clase de base de datos copiando o extendiendo SQLiteDatabase.java de la fuente de Android y reimplementando o anulando las partes críticas que son:

public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) { SQLiteDatabase sqliteDatabase = null; try { // Open the database. sqliteDatabase = new SQLiteDatabase(path, factory, flags); if (SQLiteDebug.DEBUG_SQL_STATEMENTS) { sqliteDatabase.enableSqlTracing(path); } if (SQLiteDebug.DEBUG_SQL_TIME) { sqliteDatabase.enableSqlProfiling(path); } } catch (SQLiteDatabaseCorruptException e) { // Try to recover from this, if we can. // TODO: should we do this for other open failures? Log.e(TAG, "Deleting and re-creating corrupt database " + path, e); EventLog.writeEvent(EVENT_DB_CORRUPT, path); if (!path.equalsIgnoreCase(":memory")) { // delete is only for non-memory database files new File(path).delete(); } sqliteDatabase = new SQLiteDatabase(path, factory, flags); } ActiveDatabases.getInstance().mActiveDatabases.add( new WeakReference<SQLiteDatabase>(sqliteDatabase)); return sqliteDatabase; }

y:

/* package */ void onCorruption() { Log.e(TAG, "Removing corrupt database: " + mPath); EventLog.writeEvent(EVENT_DB_CORRUPT, mPath); try { // Close the database (if we can), which will cause subsequent operations to fail. close(); } finally { // Delete the corrupt file. Don''t re-create it now -- that would just confuse people // -- but the next time someone tries to open it, they can set it up from scratch. if (!mPath.equalsIgnoreCase(":memory")) { // delete is only for non-memory database files new File(mPath).delete(); } } }

La parte peligrosa de esto es que también tendría que volver a implementar las clases auxiliares que acceden a la base de datos SQLite, como SQLiteOpenHelper . Dado que la clase SQLiteDatabase usa métodos de fábrica, podría enfrentar efectos secundarios inesperados.


Enfrenté el mismo problema e hice una pregunta al respecto here . Regularmente hago una copia de seguridad de mi base de datos en la tarjeta SD, pero no puedo recomendarlo. Parece que una base de datos que se copia de las tarjetas SD utilizadas en los teléfonos Android más nuevos se considera corrupta después de que se completa la copia en las versiones anteriores de SQLite que aún se usa en Android 2.3.6.

Si su base de datos es lo suficientemente pequeña, le recomendaría mantener una copia de seguridad, pero mantenerla en la memoria interna. A menos que enoje a sus usuarios, no habilite la opción "instalar en sd-card", creo que está relacionada con el problema. Después de estas precauciones, su base de datos debe ser relativamente segura.

Acerca del tiempo de inicio más lento: hago mis copias de seguridad en un subproceso en segundo plano cuando la aplicación está cerrada, este es el momento más probable en el que el teléfono tiene que hacer algún trabajo en segundo plano sin molestar al usuario.


Una solución simple para este problema sería replicar el DB por completo.

Por ejemplo, en el método de Destruir de tu aplicación. Copie la base de datos en cada Destroy, cuando la base de datos principal está dañada (y eliminada por Android) puede cambiar a la base de datos de copia de seguridad.


Not for at opening every time , pero creo que cada vez que nuestra database make a changes or upgrades en ese momento, make copy of DB files for back-up es one of the solutions .

También, si es posible, usar la SQLite source and modifies y la usamos en nuestra aplicación con JNI or Library , entonces podemos lograrla.

Gracias.