2010-03-05 11 views
7

Pongo mi campo de base de datos en la carpeta "assets". Y use el código de este blog para copiar la base de datos a "/ data/data/my_packname/databases /", (Este código de copia lo ejecuto en el método onCreate() cuando ejecuto esta aplicación) luego uso select * from ... para obtener datos. Pero me da la excepción: no hay tal tabla.¿Cómo usar mi propia base de datos sqlite?

Alguien me dijo que si estoy intentando copiar el archivo en onCreate() de SQLiteOpenHelper, es demasiado tarde. Entonces, el código del archivo de copia no puede copiar el archivo completo.

¿Debo utilizar adb o ddms para extraer primero la base de datos?

Entonces, ¿alguien me puede enseñar cómo usar mi propio databse? ¿Me puede decir la configuración?

Respuesta

1

Después de haber copiado la base de datos, debe intentar cerrar y volver a abrir el objeto SQLiteDatabase antes de ejecutar cualquier consulta en él. Tuve un problema similar al copiar un db de un flujo de entrada y eso fue lo que me solucionó.

11

He utilizado las instrucciones en esa publicación de blog y las encontré, aunque en el camino correcto, para complicar severamente el problema extendiendo innecesariamente SQLiteOpenHelper. He tenido mucha mejor suerte haciendo lo siguiente:

  1. Crear una clase de utilidad que crea la base de datos estática mediante la copia en el directorio correcto de los activos, pero no consigue en sí tan colgado en la siguiente SQLiteOpenHelper formato.

  2. Utilizando la misma clase de utilidad para abrir la base de datos mediante el uso de SQLiteDatabase.openDatabase()

Editar: Aquí está una versión de esta clase de utilidad que he creado; no está del todo completo, pero obtendrás la deriva.

public class DbUtils { 
    private static final String DB_PATH = "/data/data/com.mypackage.myapp/databases/"; 
    private static final String DB_NAME = "my.db"; 

    public static void createDatabaseIfNotExists(Context context) throws IOException { 
     boolean createDb = false; 

     File dbDir = new File(DB_PATH); 
     File dbFile = new File(DB_PATH + DB_NAME); 
     if (!dbDir.exists()) { 
      dbDir.mkdir(); 
      createDb = true; 
     } 
     else if (!dbFile.exists()) { 
      createDb = true; 
     } 
     else { 
      // Check that we have the latest version of the db 
      boolean doUpgrade = false; 

      // Insert your own logic here on whether to upgrade the db; I personally 
      // just store the db version # in a text file, but you can do whatever 
      // you want. I've tried MD5 hashing the db before, but that takes a while. 

      // If we are doing an upgrade, basically we just delete the db then 
      // flip the switch to create a new one 
      if (doUpgrade) { 
       dbFile.delete(); 
       createDb = true; 
      } 
     } 

     if (createDb) { 
      // Open your local db as the input stream 
      InputStream myInput = context.getAssets().open(DB_NAME); 

      // Open the empty db as the output stream 
      OutputStream myOutput = new FileOutputStream(dbFile); 

      // 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 static SQLiteDatabase getStaticDb() { 
     return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY); 
    } 
} 
+0

¿Puedes compartir la clase de utilidad? Porque no entiendo eso: "No se cuelga tanto" Muchas gracias – user275788

+0

Agregué una versión muy reducida de mi clase de utilidades, simplemente dejé la carne del código ahí. (Por ejemplo, recomiendo agregar declaraciones de registro, pero no son necesarias para este código de ejemplo). De todos modos, en esta versión del código, todo lo que necesita hacer es llamar a createDatabaseIfNotExists() cuando se inicia la aplicación, como si extiende onCreate() en android.app.Application. –

+0

También tenga en cuenta que si el tamaño de su archivo excede de 1MB, la lectura() arrojará IoException y los registros de activos "Los datos exceden a UNCOMPRESSED_DATA_MAX" ...Lo resolví nombrando mi archivo .jpg en activos -> aapt no intentó comprimirlo – Mikpa

-1

La forma de crear la base de datos del artículo que has publicado es ligeramente diversa de aquella como se hace en los ejemplos androide (no quiero decir si es bueno o malo).

He aprendido cómo utilizar bases de datos de SDKs NotePad sample

Es buen ejemplo a partir de, lástima pues abarca tanto la base de datos tema creación y acceso a la base de datos a través ContentProvider (que es realmente la única buena manera de obtener datos de db, de lo contrario, tendrá problemas al tratar de obtener datos simultáneamente de muchos lugares de su código).

Debe tener en cuenta que SQLiteOpenHelper es realmente potente y "lo ayudará" si lo va a utilizar correctamente. Por ejemplo, almacena la versión actual de la base de datos (no la versión sqlite pero el número que asigne con la versión del esquema de la base de datos) y cuando crea una nueva versión con nueva estructura de base de datos puede actualizar el esquema actual a la nueva versión en onUpdate.

+0

No creo que entiendas el propósito de la publicación del blog; el ejemplo de NotePad es para * crear * una base de datos, pero lo que el interlocutor quiere hacer es crear una base de datos en el dispositivo basada en un archivo sqlite db preexistente. –

+0

Lo sé, pero el que pregunta también quería saber cómo debería usar las bases de datos en Android que no están cubiertas por la publicación. – skyman

0

aquí está mi versión del código "Silvio Donnini" :), ahora puede actualizar la base de datos fácilmente.

private static final String DB_PATH = "/data/data/pakagename/databases/"; 
private static final String DB_NAME = "databaseName";  
private static SQLiteDatabase db; 

public static void createDatabaseIfNotExists(Context context,int version) throws IOException { 
    boolean createDb = false; 

    File dbDir = new File(DB_PATH); 
    File dbFile = new File(DB_PATH + DB_NAME); 
    if (!dbDir.exists()) { 
     dbDir.mkdir(); 
     createDb = true; 
    } 
    else if (!dbFile.exists()) { 
     createDb = true; 
    } 
    else { 
     // Check that we have the latest version of the db  
     db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY); 

     if (db.getVersion() != version) { 
      dbFile.delete(); 
      createDb = true; 
     } 

    } 

    if (createDb) { 

     // Open your local db as the input stream 
     InputStream myInput = context.getResources().openRawResource(R.raw.database); 

     // Open the empty db as the output stream 
     OutputStream myOutput = new FileOutputStream(dbFile); 

     // 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(); 
     SQLiteDatabase dbwrite = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE); 
     dbwrite.setVersion(version); 
     dbwrite.close(); 
     if (db != null) 
      db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY); 

    } 
} 

public static SQLiteDatabase getStaticDb() { 
    if (db != null) 
     return db; 

    return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY); 
} 
0

Sé que esto es una vieja pregunta, pero he perdido mucho tiempo averiguarlo, con la ayuda de todas las respuestas.


La cuestión es que un dispositivo almacena una base de datos en su carpeta de datos/datos /.../ bases de datos. Por lo tanto, cuando cambia algo acerca de la base de datos (nombre, agregar tabla de metadatos android, tamaño ...) no hará ninguna diferencia debido a la base de datos almacenada y al método que verificó la base de datos existente.


Para obtener la base de datos más reciente, después de cambiarlo, debe ejecutar el programa sin comprobar databses existentes (por ejemplo, en lugar de hacerlo simplemente dbExist = checkDataBase(); falsa).

dbExist = checkDataBase(); 

Cambiar a:

dbExists = false; 

Después de que recogió el "nuevo" DATABSE puede volver a comprobar los ya existentes.

espero que ayude a alguien, dina

0

Sé que esto es una entrada antigua, pero para aquellos que aún así obtener aquí después de un Google o una búsqueda Bing, esta es la solución al problema planteado:

en createDataBase() existe la siguiente verificación;

this.getReadableDatabase(); 

Esto comprueba si ya existe una base de datos con el nombre proporcionado y si no se crea una base de datos vacía de tal manera que se puede sobrescribir con el que está en la carpeta de activos. En los dispositivos más nuevos, esto funciona sin problemas, pero hay algunos dispositivos en los que esto no funciona. Dispositivos principalmente más antiguos. No sé exactamente por qué, pero parece que la función getReadableDatabase() no solo obtiene la base de datos sino que también la abre. Si luego copia 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á errores de tabla no existe.

Así que con el fin de hacer que funcione en todos los dispositivos que debe modificarlo para las siguientes líneas:

SQLiteDatabase db = this.getReadableDatabase(); 
if (db.isOpen()){ 
    db.close(); 
} 

Incluso si la base de datos se abre en el cheque, que está cerrado a partir de entonces y no le dará más problemas

0

Cálmate chicos, Después de una investigación a largo finalmente encontró tonto error de "no hay tal mesa" error

Comprobar nombre de la base de datos en la carpeta Activos si es como "DATABASE_NAME.EXTENSION" a continuación, poner el nombre completo en Clase auxiliar con extensión solucionó mi problema

como decir en Activos nombre de la base de datos es login.sqlite o login.db cualquier cosa. ponga DB_NAME = login.sqlite completamente con extensión. this tutorial ahora funciona perfectamente.

Cuestiones relacionadas