Actualizar la base de datos sqlite que copio de la carpeta de activos (Android)
Utilizo este tutorial: Tutorial Base de datos personalizada
Copiar la base de datos de la carpeta de activos y copiarla a mi dispositivo (o emulador). Todo es correcto. Veo mi base de datos en perspectiva de DDMS. Pero también quiero actualizar mi base de datos a veces, así que lo hice:
- Error al copiar la base de datos en Android, al ejecutar el programa en el emulador
- Recuperar un nombre de usuario y una contraseña en SQLITE DB por EMAIL_ADDRESS en ANDROID
- ¿Cómo puedo obtener datos de una base de datos SQLITE en una matriz en android?
- ¿Se trata de una consulta SQLite válida?
- Android SQLite ON CONFLICT UPDATE es posible?
super(context, DB_NAME, null, 2); //changed version from 1 to 2
Y modificar el método onUpgrade:
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if(newVersion > oldVersion){ this.myContext.deleteDatabase(DB_NAME); try { this.copyDataBase(); } catch (IOException e) { e.printStackTrace(); } } }
Pero después de ejecutar todavía tengo la versión antigua de la base de datos en mi dispositivo. Cómo puedo eliminar la versión antigua de la base de datos y copiar nuevo. DB_NAME es el nombre de mi base de datos (con formato, pero no ruta) y copyDataBase () es un método que copia la base de datos al dispositivo (y su trabajo).
Me pego todo mi código:
public class DataBaseHelper extends SQLiteOpenHelper{ private static String DB_PATH = "/data/data/sitcom.quiz/databases/"; private static String DB_NAME = "sitcoms.sqlite"; private SQLiteDatabase myDataBase; private final Context myContext; public DataBaseHelper(Context context) { super(context, DB_NAME, null, 4); this.myContext = context; } public void createDataBase() throws IOException{ boolean dbExist = checkDataBase(); if(dbExist){ //do nothing - database already exist }else{ this.getReadableDatabase(); try { copyDataBase(); } catch (IOException e) { throw new Error("Error copying database"); } } } private boolean checkDataBase(){ SQLiteDatabase checkDB = null; try{ String myPath = DB_PATH + DB_NAME; checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); }catch(SQLiteException e){ //database does't exist yet. } 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[1024]; int length; while ((length = myInput.read(buffer))>0){ myOutput.write(buffer, 0, length); } //Close the streams myOutput.flush(); myOutput.close(); myInput.close(); } public void openDataBase() throws SQLException{ //Open the database String myPath = DB_PATH + DB_NAME; myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); } @Override public synchronized void close() { if(myDataBase != null) myDataBase.close(); super.close(); } @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.d("adas", "dasd"); if(newVersion > oldVersion){ String myPath = DB_PATH + DB_NAME; this.myContext.deleteDatabase(myPath); try { this.copyDataBase(); } catch (IOException e) { e.printStackTrace(); } } } }
Y mi actividad:
DataBaseHelper myDbHelper = new DataBaseHelper(this); myDbHelper = new DataBaseHelper(this); try { myDbHelper.createDataBase(); } catch (IOException ioe) { throw new Error("Unable to create database"); } try { myDbHelper.openDataBase(); }catch(SQLException sqle){ throw sqle; }
Gracias si usted puede darme la razón o la indirecta solamente porqué ésta no trabaja.
- ¿Cómo evitar la inserción de duplicados en la base de datos SQLite?
- Preguntas SQL parametrizadas en Android
- La manera más rápida y eficiente de pre-poblar la base de datos en Android
- Sqlite cómo obtener elementos de cadena con el cursor
- ¿Podemos usar Guid como clave principal en la base de datos de SQL Server?
- SQLite Context.MODE_PRIVATE
- Cómo ignorar el acento en la consulta SQLite (Android)
- Unión externa izquierda con cláusula Select en Android
Android ya abrió el db cuando se llama a la función onUpgrade (). No creo que sea posible eliminarlo en este momento. Verifique el registro para más información. Si quieres hacerlo de esta manera, necesitas mover el código de borrar y copiar a un lugar donde el db no está abierto todavía.
Prueba este código … Creo que resolverá tu problema.
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) { Log.w(DatabaseHelper.class.getName(), "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); database.execSQL("DROP TABLE IF EXISTS " + DATABASE_NAME); onCreate(database); }
Cuando se copia la base de datos de los activos, por defecto la versión es 0. En su método para copiar databse de los activos, establezca su versión utilizando el método setVersion(int version)
para su objeto de base de datos. Si db existe, compruebe su versión por el método getVersion()
en su objeto de base de datos. Ahora manejar su onUpgrade usted mismo, es decir, si db evrsion se ha actualizado noe, a continuación, actualizar la base de datos y luego setVersion(int new dbVersion)
.
Puede eliminar el Db anterior antes de actualizar DB.
if(dbExist){ Log.v("com.db","db exists"); myContext.deleteDatabase(DB_NAME);`enter code here` //openDataBase(); //do nothing - database already exist }else{ Log.v("com.db","dbnot exists"); //By calling this method and empty database will be created into the default system path //of your application so we are gonna be able to overwrite that database with our database. this.getReadableDatabase(); }
Sólo una adición:
En createDataBase () hay la siguiente comprobación;
This.getReadableDatabase ();
Esto comprueba si ya existe una base de datos con el nombre proporcionado y si no crea una base de datos vacía tal que se puede sobrescribir con la de la carpeta de activos. En los dispositivos más nuevos esto funciona sin problemas, pero hay algunos dispositivos en los que esto no funciona. Principalmente los dispositivos más antiguos. No sé exactamente por qué, pero parece que la función getReadableDatabase () no sólo recibe la base de datos sino que también la abre. Si a continuación, copiar la base de datos de la carpeta de activos sobre ella, todavía tiene el puntero a una base de datos vacía y obtendrá tabla no existen errores.
Así que para que funcione en todos los dispositivos, debes modificarlo a las siguientes líneas:
SQLiteDatabase db = this.getReadableDatabase(); if (db.isOpen()){ db.close(); }
Incluso si la base de datos se abre en el cheque, se cierra a partir de entonces y no le dará más problemas.
La idea principal es que debe usar SharedPreferences para almacenar la versión de la base de datos siempre que cree la nueva base de datos.
Después de eso, cuando usted crea la base de datos, usted debe comprobar si la base de datos tiene nueva versión entonces usted suprime la vieja base de datos y crea una nueva
Este código funciona conmigo
private static class DatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "database.name"; private static final int DATABASE_VERSION = 1; private static final String KEY_DB_VER = "database_version"; private final Context mContext; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); mContext = context; initialize(); } /** * Initializes database. Creates database if doesn't exist. */ private void initialize() { if (databaseExists()) { SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(mContext); int dbVersion = prefs.getInt(KEY_DB_VER, 1); // if (DATABASE_VERSION != dbVersion) { File dbFile = mContext.getDatabasePath(DATABASE_NAME); // delete the old databse if (!dbFile.delete()) { Log.w(TAG, "Unable to update database"); } } } // create database if needed if (!databaseExists()) { createDatabase(); } } /** * Returns true if database file exists, false otherwise. * @return */ private boolean databaseExists() { File dbFile = mContext.getDatabasePath(DATABASE_NAME); return dbFile.exists(); } public void createDataBase() throws IOException { // If database not exists copy it from the assets boolean mDataBaseExist = databaseExists(); if (!mDataBaseExist) { this.getReadableDatabase(); this.close(); try { // Copy the database from assests copyDataBase(); //**save the database version by SharedPreferences** SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(mContext); SharedPreferences.Editor editor = prefs.edit(); editor.putInt(KEY_DB_VER, DATABASE_VERSION); editor.commit(); Log.e(TAG, "createDatabase database created"); } catch (IOException mIOException) { throw new Error("ErrorCopyingDataBase"); } } } // Copy the database from assets private void copyDataBase() throws IOException { Log.i("TAG", "copy database"); InputStream mInput = mContext.getAssets().open(DB_NAME); String outFileName = DB_PATH + DB_NAME; OutputStream mOutput = new FileOutputStream(outFileName); byte[] mBuffer = new byte[1024]; int mLength; while ((mLength = mInput.read(mBuffer)) > 0) { mOutput.write(mBuffer, 0, mLength); } mOutput.flush(); mOutput.close(); mInput.close(); } @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
- ¿Seguro para AsyncTask interno para acceder a los campos de miembros privados de la clase Activity?
- Aplicación de Gmail de Android: adjunto de correo: problema de URI