SQLite Android

_Sioke_

Buenas,

Estoy teniendo problemas al insertar datos en la tabla. El problema está en que no reconoce un campo _id y no sé si el problema está al crear la tabla, o al hacer el insert.

La pregunta es: ¿cómo puedo hacer para abrir el archivo sqlite de la carpeta data/data/app/databases y ver que tiene dentro?

Tengo instalado en el móvil aShell y aSQLiteManager pero sin resultados. :/

elkaoD

#1 necesitas tener el teléfono rooteado.

1 respuesta
C

#1 supongo que habrás creado una base de datos en tu clase de acceso a datos (o donde sea). Bien, para acceder desde consola haz lo siguiente (hay más formas, pero a mí me mola esta):

1) Conecta el teléfono a un puerto usb
2) Te vas a la carpeta 'platform-tools' que está dentro de la carpeta donde tengas el sdk de android instalado. En esa carpeta tienes que tener el adb.exe
3) Escribes: adb devices y tiene que aparecer un id del teléfono que tienes conectado
4) Escribes: adb -s xxxxxxxxxxxxxx shell (donde xxxxxxxxxxxxxxx es el id del teléfono). Te aparecerá el símbolo $
5) Escribes: su (te da permisos de super usuario. pero ojo! el teléfono tiene que estar rooteado). Te aparecerá el símbolo #
6) Escribes: cd data/data
7) Ahora miras lo que tienes en ese directorio (escribe: ls). Tienes que tener una carpeta con el package de tu proyecto. Escribes: cd nombredelpackagedetuproyecto
8) Escribes: cd databases
9) Escribes: Miras el contenido del directorio (escribe: ls). Tendrás que ver el nombre del archivo de tu base de datos. Imaginemos que es mibasededatos.db
10) Escribes: sqlite3 mibasededatos.db
11) Te aparecerá un shell tal que así sqlite>
12) Prueba a poner: .tables y verás las tablas de tu base de datos

Suerte.

2 2 respuestas
_Sioke_

Gracias por las respuestas, ahora mismo está recogiendo bien los datos y los está mostrando.

#2 Tengo el móvil rooteado y puedo acceder a la carpeta através de aShell pero luego no es capaz de abrirlo.

#3 No he conseguido detectar el móvil desde el shell, con el emulador si he tenido suerte. Muy instructivo, muchas gracias :si:

1 respuesta
MTX_Anubis

Te comento que cuando reinstalas la app, la BBDD no se actualiza porque ya está creada a no ser que hayas borrado los datos antes o la hayas desinstalado (lo mismo ocurre con las preferencias). Si llevas el control de version de la BBDD pues puedes hacerlo ahí. Te lo comento por si acaso creaste previamente la bbdd y luego le añadiste el campo _id y de más.

Puedes hacer en tu aplicación que te copie la bbdd a una carpeta distinta. Basicamente es abrir el fichero (con el path que te ha explicado #3) y copiarlo a la sd.

1 respuesta
Tig

#4 qué SO usas? Tendrás que instalar drivers en windows o modificar unos ficheros en linux para que te lo detecte desde shell, además de poner el teléfono en modo debug

Para sqlite, recomiendo a todos este plugin para eclipse:

http://www.questoid.com/Tools/CellObjectSQLiteXMLBrowser.aspx

Y si tenéis un teléfono rooteado, para acceder al sistema de ficheros desde DDMS yo uso esta app

https://play.google.com/store/apps/details?id=eu.chainfire.adbd&hl=es

básicamente monta el sistema de ficheros para permitir lectura por adb, pero te ahorra tener que entrar por shell

1 respuesta
_Sioke_

Gracias otra vez.

#5 Pues era precisamente eso :palm:, al no cambiar la versión de la base de datos, no había actualizado la tabla con los nuevos atributos.

#6 Uso Windows(shame on me). De cualquier forma los drivers están instalados y el modo debug activao en el móvil, ya digo que en Eclipse puedo hacer debug con el móvil pero no sé bien porque no lo ha detectado desde el abd shell.

He probado el plugin y está muy bien, bastante útil.

1 respuesta
Tig

#7 si en una consola de windows escribes "adb devices", te tiene que salir el teléfono. Si no, es imposible que eclipse te lo detecte. Tendrás que tener adb en el path o ir al directorio de la sdk.

Para conectarte por shell haz "adb -d shell". Ese "-d" significa que quieres acceder al device, mientras que "-e" sería para el emulador. Si tienes más de 2, te toca usar "-s", como te han dicho por arriba. Si sólo tienes un dispositivo, no hace falta escribir nada.

PD: no uses Windows para trabajar, diría que bastantes cosas te serán más difíciles porque están pensadas para usar desdeconsola unix... y no solo de Android, digo en general.

Querosvan

No sé si lo has resuelto.

Yo las bases de datos que escribo las exporto a una carpeta visible para poder acceder desde aSQLite ó conectando el dispositivo al ordenador y abriendo cualquier visor de SQLite.

Si quieres puedo ponerte una función para exportarlo, no necesitas root ni nada. Hazme quote y la busco si no lo has resuelto

29 días después
_Sioke_

Bueno, resucito el hilo en nueva búsqueda de luz...
Tengo un problemilla al hacer los selectedArg con atributos boolean o integer, de momento he estado trabajando con los string y no he tenido problemas.

db.update("nombre_tabla", contentValues, "id=?" , new String[]{objeto.getId().toString()});

El codigo no peta pero la funcion devuelve 0. En cambio usando "name=?" la base de datos actualiza correctamente el campo concreto de la fila que coincide con el nombre. Dejarlo con el name me parece una solución harta gitana.

¿Alguna idea? Estoy por cambiar el atributo a VARCHAR en la tabla, a ver si así...

1 respuesta
elkaoD

#10 pero cuál es el esquema?

1 respuesta
_Sioke_

#11 Esta mañana me puse a copiar código para ponerte en situación y releyendo a la mil y una encontré un fallo tonto en la asignación de la id, que estaba llamando nuevamente a hashCode()
el caso es que cuando hacia la comprobación en los Log, las id's eran iguales... :wtf:

En stackoverflow había leído que había problemas con estos tipos y me he obcecado con eso, al final tanto con boolean(teniendo cuidado con los 0's y 1's) como con integer, funciona bien esto.

Spacelord

Un tema, ¿SQLite sigue sin garantizar integridad referencial o ya se lo han añadido? Es que estuve mirándolo hace año y pico para una cosa y no lo pude usar precisamente por eso.

1 respuesta
B

#13: Creo que no (que sigue sin garantizarla).

elkaoD

Sigue y seguirá. He ahí el Lite de SQLite. La integridad referencial es de todo menos ligera ;)

1 respuesta
Spacelord

#15 Vaya, no lo sabía. ¿Alguna alternativa para montar una BBDD portable (es decir, que no te obligue a arrancar un server en local para instalarla y hacer transacciones) y que sí garantice integridad referencial?

1 respuesta
elkaoD

#16 no creo, no tiene mucho sentido levantar un server pesadísimo por cada aplicación, de ahí que sean centralizados. Igual me equivoco vamos, pero una BD con transacciones, journaling y demás más vale que la tengas corriendo el 100% del tiempo.

Igual me equivoco, pero no me suena.

EDIT: #16 Clojure ofrece STM (Software Transactional Memory) que igual te interesa.

Algunas implementaciones para Java:

http://en.wikipedia.org/wiki/Software_transactional_memory#Java

Aunque la persistencia te la tendrías que currar tú y no ofrece integridad referencial.

1 respuesta
Spacelord

#17 Bueno, algo es algo. Estaba pensando en demos, versiones de prueba de software y esas cosas; algo que fuese una muestra y no el software final. Para una implantación normal sí que es mucho mejor instalar el server, meterle la BBDD y tenerlo siempre en marcha, eso sí.

Muchas gracias, le echaré un ojo a ver.

2 meses después
_Sioke_

Buenas morenos,

Nuevamente me ha surgido otro problema. Hasta ahora estaba usando el patrón DAO, y tenía una clase para cada una de las tablas. El caso es que con el tiempo he empezado a necesitar del uso de joins y, por lo que he estado leyendo, los DAOs no tienen porque estar limitados a una tabla, así que debería de poder hacer eso de los joins.

Se me ocurre un par de soluciones.

La primera sería meterlo todo junto. Es decir, puedo crearme una clase con varias tablas y que el helper, en onCreate y en upgrade me cree y actualice las diferentes tablas. En mi caso actual sólo tendria que unir dos tablas para hacer las consultas join que necesito.
Pero en un caso en el que puedan implicarse diferentes joins para consultas complejas, podrías acabar con un DAO que lo tenga que abarcar todo.

La otra sería hacer el "join" en la parte lógica del programa procesando las listas devueltas en las consultas.

Y luego están las soluciones que no se me ocurren, que puedan ser la buena. :wtf: ¿Qué os parece más adecuado?

2 respuestas
forlayo

#1 Puedes copiar en la sd la base de datos sin necesidad de ser root:


String backupDBPath = System.currentTimeMillis()+"-midb.db";
File sd = Environment.getExternalStorageDirectory();
            if (sd.canWrite()) {

            File currentDB = ctx.getDatabasePath(DataBaseHelper.DATABASE_NAME);
            backupDB = new File(sd, backupDBPath);
            if (currentDB.exists()) {
                FileChannel src = new FileInputStream(currentDB).getChannel();
                FileChannel dst = new FileOutputStream(backupDB).getChannel();
                dst.transferFrom(src, 0, src.size());
                src.close();
                dst.close();
            }
}

No tiene nada.

1 respuesta
elkaoD

#19 y esto es lo que pasa cuando reusáis threads! xDDD

1 respuesta
_Sioke_

#21 :D Bueno, al menos hemos sacado otra respuesta interesante para ver las bases de datos de las aplicaciones.

#20 Gracias, como digo respuesta muy interesante. Aunque estaba yo ahora con la duda
que planteaba en #19

1 respuesta
forlayo

#22 De nada y me alegro de que te sirva, sobre la duda que plantea #19; por la experiencia tratando con las bases de datos SQLite en Android mi recomendación es que no se entiendan las mismas como un SGDB porque realmente no rinde como debería.

Siempre intento enfocar las tablas denormalizadas para el propósito concreto y suelo hacer uso de un helper en singleton del cual se nutren varios providers. Recientemente he estado usando ADA Framework con bastantes buenos resultados ( http://www.adaframework.com/why/ ) y también está el conocido ORMLite ( http://ormlite.com/ ).

Pero eso mi recomendación es un uso simplista, pues no se comporta del todo bien ( probad a usar triggers y verás que divertido en según que móvil ).

Un saludo.

1 respuesta
_Sioke_

#23 Gracias otra vez, esta mañana he estado probando con ORMLite y mirando un par de proyectos en Git para ayudarme. De momento va avanzando la cosa.
Como decía no es que sea un proyecto muy grande y tampoco necesito de consultas muy complejas pero me anoto para un futuro lo de mantenerlo de forma más simple.

1 respuesta
forlayo

#24 Cualquier cosa que necesites me puedes preguntar, si tengo un rato te contesto encantado :)

Tig

En el proyecto que estoy ahora uso GreenDAO, que es otro ORM. No he usado ORMLite ni el otro que mencionáis, así que no tengo opinión, pero sí puedo decir que hacer tus propios DAOs acaba dando problemas.

En el pasado he trabajado con ContentProviders y directamente con Cursor, que realmente es lo que quiere Android, pues observas directamente los datos y te notifican si cambian. El problema es cuando no puedes servir los datos tal cual vienen de la base de datos, que es mi caso actual.

Usuarios habituales