ver una studio sqlitedatabase para hacer gestores fichero datos crear crea como app acceder android sqlite

android - una - sqlitedatabase



¿Por qué no se invoca onUpgrade() en la base de datos sqlite de Android? (4)

Quiero actualizar mi base de datos cuando esté instalada en mi emulador de Android. He establecido la versión db en mi DbHelper que hereda de SQLiteOpenHelper a +1.

Sin embargo, cuando se carga mi primera actividad, hago una instancia de mi DbHelper, que espero que SQLiteOpenHelper llame a UpUpgrade ya que la versión de la base de datos ahora es más nueva. Sin embargo nunca se llama. Me pregunto si hay algo que me falta. ¿Dónde está almacenada la versión que DbHelper está utilizando para compararla con la nueva versión? ¿Por qué esto no funciona?

En realidad, estoy copiando la base de datos de la carpeta de activos en la carpeta de datos en lugar de volver a crear el esquema.

public class DbHelper extends SQLiteOpenHelper { private static final String TAG = "DbHelper"; static final String DB_NAME = "caddata.sqlite"; static final int DB_VERSION = 4; private static String DB_PATH = ""; private Context myContext; private SQLiteDatabase myDataBase; public DbHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); this.myContext = context; DB_PATH = "/data/data/" + context.getApplicationContext().getPackageName() + "/databases/"; } public DbHelper open() throws SQLException { myDataBase = getWritableDatabase(); Log.d(TAG, "DbHelper Opening Version: " + this.myDataBase.getVersion()); return this; } @Override public synchronized void close() { if (myDataBase != null) myDataBase.close(); super.close(); } @Override public void onCreate(SQLiteDatabase db) { Log.d(TAG, "onCreate called"); try { createDataBase(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if ( newVersion > oldVersion) { Log.d(TAG, "New database version exists for upgrade."); try { Log.d(TAG, "Copying database..."); copyDataBase(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void createDataBase() throws IOException { boolean dbExist = checkDataBase(); if (!dbExist) { try { copyDataBase(); } catch (IOException e) { throw new Error("Error copying database"); } } openDataBaseForRead(); } private boolean checkDataBase() { SQLiteDatabase checkDB = null; try { String myPath = DB_PATH + DB_NAME; checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS); Log.d(TAG, "db exists"); } catch (SQLiteException e) { // database does''t exist yet. Log.d(TAG, "db doesn''t exist"); } if (checkDB != null) { checkDB.close(); } return checkDB != null ? true : false; } private void copyDataBase() throws IOException { // Open your local db as the input stream InputStream myInput = myContext.getAssets().open(DB_NAME); // Path to the just created empty db String outFileName = DB_PATH + DB_NAME; // Open the empty db as the output stream OutputStream myOutput = new FileOutputStream(outFileName); // transfer bytes from the inputfile to the outputfile byte[] buffer = new byte[2048]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } // Close the streams myOutput.flush(); myOutput.close(); myInput.close(); myDataBase.setVersion(DB_VERSION); } public void openDataBaseForRead() throws SQLException { // Open the database String myPath = DB_PATH + DB_NAME; myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); } public void openDataBaseForWrite() throws SQLException { // Open the database String myPath = DB_PATH + DB_NAME; myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.NO_LOCALIZED_COLLATORS ); } }


En mi caso, la versión de la base de datos en la carpeta de activos y la versión actual de la base de datos en el código, ambas son iguales, más tarde aumenté la versión de la base de datos actual en el código, luego se llama al método onUpgrade.


Este es un fragmento de código de la fuente de SQLiteOpenHelper.getWritableDatabase() :

int version = db.getVersion(); if (version != mNewVersion) { db.beginTransaction(); try { if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db, version, mNewVersion); } else { onUpgrade(db, version, mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } } onOpen(db);

Como puede ver, se onCreate() o onUpgrade() dentro de la llamada a getWritableDatabase() . SQLiteDatabase usar estas llamadas siempre que necesite una instancia de SQLiteDatabase . No debe usar sus propios métodos, excepto si son envolturas getReadableDatabase método getWritableDatabase o getReadableDatabase .


He resuelto el problema. Este problema se produce solo cuando copia la base de datos de los activos. La base de datos de la carpeta de activos tiene una versión predeterminada 0. Entonces, cuando llama al asistente de apertura de la base de datos con el número de versión (por ejemplo, 1) y luego lo sobrescribe con el de activos, el número de versión se restablece a 0.

Y cuando llama a la db.getReadableDatabase () o db.getWriteableDatabase que se supone que llama al método onUpgrade, falla porque la versión número 0, que se supone es una base de datos nueva. Puedes mirar el código fuente de SqliteOpenHelper. Activa el método onUpgrade solo cuando la versión es mayor que cero y la versión actual es mayor que la anterior.

`

db.beginTransaction(); try { //Skips updating in your case if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db, version, mNewVersion); } else { onUpgrade(db, version, mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); }

`

Así que esto es lo que hice para superar este problema. No es donde una solución perfecta, pero funciona. Básicamente, necesita actualizar la versión db antes de llamar al súper método de la clase SQLiteOpenHelper (el constructor de su administrador de base de datos).

`

try { String myPath = MyApplication.context.getDatabasePath(DATABASE_NAME).toString(); //open a database directly without Sqliteopenhelper SQLiteDatabase myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.NO_LOCALIZED_COLLATORS); //if the version is default 0 the update the version if (myDataBase.getVersion() == 0) { //update the database version to the previous one myDataBase.execSQL("PRAGMA user_version = " + 1); } //Close DataBase myDataBase.close(); } catch (Exception e) { //Do Nothing a fresh install happened }

`

PD: Sé que la respuesta es tardía, pero podría ayudar a alguien como yo que estaba buscando esta solución en particular.


Documentation dice:

La base de datos no se crea ni se abre en realidad hasta que se llama a getWritableDatabase () o getReadableDatabase ().

Veo que has implementado tus propios métodos para obtener la base de datos: openDataBaseForRead() y openDataBaseForWrite() . Eso es malo ;-)