SQLiteOpenHelper onCreate no crea base de datos – o se está sobrescribiendo inmediatamente
Tengo mi base de datos almacenada en mi carpeta de los activos y copiada sobre en la época de la ejecución. Tengo actualmente una actividad simple que hace una llamada simple de la base de datos:
DBAdapter adapter = new DBAdapter(HomeActivity.this); final SQLiteDatabase db = adapter.getReadableDatabase(); final Cursor c = db.query("exercises", new String[] { "name" }, null, null, null, null, null); startManagingCursor(c); if (c.moveToFirst()) Log.e(TAG, c.getString(0)); else Log.e(TAG,"No dice");
Y abajo está mi DBAdapter.java (que extiende el ayudante abierto):
- Cómo crear carpeta privada en sdcard
- Volver a crear la base de datos al utilizar proveedores de contenido
- Archivo DB en carpeta de activos. ¿Se actualizará?
- Insertar datos JSON en la base de datos SQLite en android
- Limitar los registros obtenidos en Android (base de datos Sqlite)
public class DBAdapter extends SQLiteOpenHelper { private static final int DB_VERSION = 1; private static String DB_PATH = ""; private static final String DB_NAME = "gymrat.db"; private final Context myContext; private static final String TAG = "GymRat.DBAdapter"; /** * Constructor Takes and keeps a reference of the passed context in order to * access to the application assets and resources. * * @param context */ public DBAdapter(Context context) { super(context, DB_NAME, null, DB_VERSION); this.myContext = context; DB_PATH = "/data/data/" + context.getApplicationContext().getPackageName() + "/databases/"; } /** * Copies your database from your local assets-folder to the just created * empty database in the system folder, from where it can be accessed and * handled. This is done by transferring bytestream. * */ private void copyDatabase() throws IOException { InputStream myInput = myContext.getAssets().open(DB_NAME); String outFileName = DB_PATH + DB_NAME; OutputStream myOutput = new FileOutputStream(outFileName); byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } myOutput.flush(); myOutput.close(); myInput.close(); } /** * Call on creating data base for example for creating tables at run time */ @Override public void onCreate(SQLiteDatabase db) { Log.e(TAG, "onCreate"); try { copyDatabase(); } catch (IOException e) { Log.e(TAG,"IOException copying Database"); } } @Override public void onOpen(SQLiteDatabase db) { Log.e(TAG, "onOpen"); try { db.rawQuery("select * from exercises", null); } catch ( SQLiteException e) { Log.e(TAG,"DB copy didn't work"); try { copyDatabase(); } catch (IOException e1) { Log.e(TAG,"IOException recopying DB"); } } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.e(TAG, "Upgrading"); } }
Tomé este adaptador de aquí y lo modifiqué puesto que no parecía utilizar la funcionalidad de OpenHelper.
Mi Problema: Cuando mi aplicación se ejecuta por primera vez después de instalar, o después de limpiar los datos de la aplicación, onCreate se llama primero como yo esperaría, y llama al método copyDatabase. El problema es que la base de datos no se copia – o si lo hace se sobrescribe inmediatamente. En su lugar, se crea una base de datos predeterminada con sólo una tabla "meta_datos android", haciendo que la consulta de mi actividad lance una excepción porque la tabla no existe.
Si vuelvo a copiar la base de datos en el método onOpen funciona bien. ¿Estoy haciendo algo fuera de servicio o falta alguna llamada que está causando que SQLiteOpenHelper cree una base de datos predeterminada? La base de datos predeterminada creada utiliza el mismo nombre y el mismo número de versión especificado en el constructor.
Ahora mismo, como se puede ver, estoy recurriendo a usar una consulta ficticia en onOpen para ver si existe la tabla esperada y si no va adelante y volver a copiar la base de datos. Otra opción es simplemente establecer una bandera cuando onCreate se llama señalización onOpen para copiar la base de datos. Obviamente estos son un poco hacky y estoy muy curioso de lo que está pasando.
Planeo mover las llamadas reales de la base de datos a las clases auxiliares separadas fuera de la actividad, yo estaba llamando simplemente el db directamente para probarlo.
- ¿Puedo almacenar de forma segura una cadena totalmente aleatoria (cualquier valor de 16 bits) en un SQLiteDB?
- ¿Cómo actualizar la tabla en sqlite?
- Eliminar fila de SQLite con cláusula where con cláusulas múltiples
- Guardar ArrayList en la base de datos SQLite en Android
- Cómo proteger una base de datos sqlite pre hecho en android?
- Sugar ORM No hay tal tabla de excepción
- SQLite Context.MODE_PRIVATE
- copia sqlite db al dispositivo android falla
Si desea copiar la base de datos de los activos a la primera ejecución y abrir la base de datos desde data / data / programa.nombre / base de datos, debe usar el código algo como esto:
public class YourDatabase extends SQLiteOpenHelper public YourDatabase(Context context) { super(context, DatabaseName, null, DATABASE_VERSION); this.dbContext = context; // checking database and open it if exists if (checkDataBase()) { openDataBase(); } else { try { this.getReadableDatabase(); copyDataBase(); this.close(); openDataBase(); } catch (IOException e) { throw new Error("Error copying database"); } Toast.makeText(context, "Initial database is created", Toast.LENGTH_LONG).show(); } }
Respuesta completa que puedes leer de esta pregunta
- Layouts de la piel del emulador de Android – ¿Hay herramientas y una especificación?
- ¿Cómo portar un MS Access existente a SQLite para su uso con el desarrollo de aplicaciones para Android?