Usar nuestra propia Base de Datos SQLite en Android

Comienzo con éste una serie de tutoriales relacionados con la aplicación de la Feria de Albacete 2011 en la que se explicará paso por paso como dotar de diversas características a nuestras aplicaciones.

En este caso explicaré como utilizar una base de datos con datos por defecto, es decir, utilizando un fichero externo de base de datos creado con un editor de bases de datos SQLite.

Tabla de Contenidos

Preparando el fichero de base de datos SQLite

Una vez tengamos nuestro propio fichero de base de datos tendremos que modificarla un poco. Para editar la base de datos utilizaremos la aplicación de código abierto SQLite Database Browser disponible para Windows Mac y Linux. Para profundizar más en el uso de esta aplicación existen multitud de cursos y tutoriales como el que ofrece Guru99.com.

Abrimos nuestro fichero de base de datos y añadimos una nueva tabla llamada ‘android_metadata’. Para ello podemos ejecutar el siguiente código SQL:

CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'es_ES')

Seguidamente insertamos una nueva fila con el texto ‘es_ES’ en la tabla recién creada.

INSERT INTO "android_metadata" VALUES ('es_ES')

Una vez hecho esto tenemos que cambiar el nombre identificativo de las claves primarias de las tablas de nuestra base de datos a ‘_id’ para que de esta manera Android pueda identificarlas. Para ello podemos hacer clic en el botón Botón de Edición de SQLite, y tras seleccionar la tabla que queremos modificar, podremos editar el nombre del campo.

Finalmente nuestra base de datos tiene que tener un aspecto similar al siguiente:

SQLite Browser

Manejando la Base de Datos desde nuestra Aplicación Android

Para poder tener acceso desde nuestra aplicación al fichero de base de datos éste debe encontrarse en una carpeta dentro de nuestro proyecto llamada ‘assets’. Si ya está creada, copiamos el fichero de base de datos ahí, si no, tendremos que crear la carpeta antes.

Proyecto Android SQLite

El manejo de la base de datos se hará utilizando una clase personalizada que extenderá la clase SQLiteOpenHelper, en la cual podremos incluir todos los métodos relacionados con la base de datos para insertar, actualizar y borrar datos.

Recuerda cambiar en el siguiente código las cadenas «TU_PAQUETE» y «NOMBRE_DE_FICHERO» por el nombre del paquete de tu proyecto, y el nombre del fichero de tu base de datos respectivamente.

public class DBHelper extends SQLiteOpenHelper{
    
    //Ruta por defecto de las bases de datos en el sistema Android
    private static String DB_PATH = "/data/data/TU_PAQUETE/databases/";
    
    private static String DB_NAME = "filename.db";
    
    private SQLiteDatabase myDataBase;
    
    private final Context myContext;
    
    /**
    * Constructor
    * Toma referencia hacia el contexto de la aplicación que lo invoca para
    * poder acceder a los 'assets' y 'resources' de la aplicación.
    * Crea un objeto DBOpenHelper que nos permitirá controlar la apertura de
    * la base de datos.
    * @param context
    */
    public DBHelper(Context context) {
        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }
    
    /**
    * Crea una base de datos vacía en el sistema y la reescribe con nuestro
    * fichero de base de datos.
    * */
    public void createDataBase() throws IOException{
        
        boolean dbExist = checkDataBase();
        
        if(dbExist){
            //la base de datos existe y no hacemos nada.
        }else{
            //Llamando a este método se crea la base de datos vacía en la ruta
            //por defecto del sistema de nuestra aplicación por lo que podremos
            //sobreescribirla con nuestra base de datos.
            this.getReadableDatabase();
            
            try {
                
                copyDataBase();
                
            } catch (IOException e) {
                throw new Error("Error copiando Base de Datos");
            }
        }
        
    }
    
    /**
    * Comprueba si la base de datos existe para evitar copiar siempre el
    * fichero cada vez que se abra la aplicación.
    * @return true si existe, false si no existe
    */
    private boolean checkDataBase(){
        
        SQLiteDatabase checkDB = null;
        
        try{
            
            String myPath = DB_PATH + DB_NAME;
            checkDB = SQLiteDatabase
                        .openDatabase(myPath, 
                            null, 
                            SQLiteDatabase.OPEN_READONLY);
            
        }catch(SQLiteException e){
            
            //si llegamos aqui es porque la base de datos no existe todavía.
            
        }
        if(checkDB != null){
            
            checkDB.close();
            
        }
        return checkDB != null ? true : false;
    }
    
    /**
    * Copia nuestra base de datos desde la carpeta assets a la recién creada
    * base de datos en la carpeta de sistema, desde dónde podremos acceder a
    * ella.
    * Esto se hace con bytestream.
    * */
    private void copyDataBase() throws IOException{
        
        //Abrimos el fichero de base de datos como entrada
        InputStream myInput = myContext.getAssets().open(DB_NAME);
        
        //Ruta a la base de datos vacía recién creada
        String outFileName = DB_PATH + DB_NAME;
        
        //Abrimos la base de datos vacía como salida
        OutputStream myOutput = new FileOutputStream(outFileName);
        
        //Transferimos los bytes desde el fichero de entrada al de salida
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer))>0){
            myOutput.write(buffer, 0, length);
        }
        
        //Liberamos los streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
        
    }
    
    public void open() throws SQLException{
        
        //Abre la base de datos
        try {
            createDataBase();
        } catch (IOException e) {
            throw new Error("Ha sido imposible crear la Base de Datos");
        }
        
        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) {
        
    }
    /**
    * A continuación se crearán los métodos de lectura, inserción,
    * actualización y borrado de la base de datos.
    * */

Métodos útiles de lectura, inserción, actualización y borrado

A continuación pongo ejemplos de los métodos más habituales de uso de base de datos que deberían introducirse en la misma clase DBHelper. Para ello utilizaré como ejemplo la tabla que puede verse en la imagen del Paso 1, que consta de tres columnas (‘_id’, ‘alarma’ y ‘evento’):

//Establecemos los nombres de las columnas
public static final String KEY_ID = "_id";
public final static String KEY_COL1 = "alarma";
public final static String KEY_COL2 = "evento";

//Array de strings para su uso en los diferentes métodos
private static final String[] cols = new String[] { KEY_ID, KEY_COL1, KEY_COL2 };

Los métodos de inserción, borrado y actualización son bastante simples. Para más información sobre ellos podéis echarle un ojo a la información de la clase SQLiteDatabase.

/**
* INSERTAR NUEVA ALARMA
* */
public long insertAlarma(Integer id, Integer alarma, Integer evento) {
    ContentValues newValues = new ContentValues();
    newValues.put(KEY_ID, id);
    newValues.put(KEY_COL1, alarma);
    newValues.put(KEY_COL2, evento);
    return db.insert(DATABASE_TABLE, null, newValues);
}

/**
* BORRAR ALARMA CON _id = _rowIndex
* */
public boolean removeAlarma(long _rowIndex) {
    return db.delete(DATABASE_TABLE, KEY_ID + "=" + _rowIndex, null) > 0;
}

/**
* ACTUALIZAR ALARMA _id = _rowIndex
* */
public boolean updateAlarma(Integer _rowIndex, Integer alarma, Integer evento) {
    ContentValues newValues = new ContentValues();
    newValues.put(KEY_COL1,alarma);
    newValues.put(KEY_COL2, evento);
    return db.update(DATABASE_TABLE, newValues, KEY_ID + "=" + _rowIndex, null) > 0;
}

Por otro lado, para la lectura de la base de datos, se utiliza el método ‘query’, el cual nos devuelve un cursor con las filas que se corresponden con el criterio de búsqueda. Mi recomendación para evitar el uso de cursores en nuestra aplicación es crear objetos de una clase propia personalizada para el tipo de datos que vamos a recuperar. De este modo nuestros métodos devolverán el tipo de objetos que realmente vamos a utilizar. Para este ejemplo utilizamos el tipo de objeto «Alarma» que contiene los dos campos de la base de datos que queremos utilizar como variables:

public class Alarma {
    
    private Integer Evento;
    private Integer Alarma;
    
    public Alarma(Integer idEvento, Integer idAlarma) {
        super();
        this.idEvento = idEvento;
        this.idAlarma = idAlarma;
    }
    
}

De este modo podemos crear dos tipos de métodos para obtener datos. Uno que nos devuelva un único resultado, y otro que nos devuelva un objeto List<Alarma> con todos los resultados. Para más información acerca del método ‘query’ y crear consultas más avanzadas os recomiendo echarle un ojo a la información de la clase SQLiteDatabase:

public Alarma getAlarma(long _rowIndex) {
    Alarma alarm = new Alarma();
    Cursor result = db.query(true, DATABASE_TABLE,
    cols,
    KEY_ID + "=" + _rowIndex, null, null, null,
    null, null);
    if ((result.getCount() == 0) || !result.moveToFirst()) {
        //Si la alarma no existe, devuelve una alarma con valores -1 y -1
        alarm = new Alarma(-1,-1);
        
    } else {
        if (result.moveToFirst()) {
            alarm = new Alarma(
            result.getInt(result.getColumnIndex(KEY_COL1)),
            result.getInt(result.getColumnIndex(KEY_COL2))
            );
        }
    }
    return alarm;
}

public List<Alarma> getAlarmas() {
    ArrayList<Alarma> alarms = new ArrayList()<Alarma>;
    Cursor result = db.query(DATABASE_TABLE,
    cols, null, null, null, null, KEY_ID);
    if (result.moveToFirst())
    do {
        alarms.add(new Alarma(
        result.getInt(result.getColumnIndex(KEY_COL1)),
        result.getInt(result.getColumnIndex(KEY_COL2))
        )
        );
    } while(result.moveToNext());
    return alarms;
}

Utilizando la clase DBHelper

Una vez tenemos creada la clase DBHelper el uso de la misma es bastante trivial. Basta con crear un objeto DBHelper y llamar a los métodos open() y close() antes y después de utilizar los métodos de uso que hayamos creado. Mi recomendación es llamar al método open() en los métodos onCreate() y onResume() de la actividad que vaya a utilizar la base de datos y close() en el método onPause().

public class miActividad extends Activity {
    
    private DBHelper BD;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        //Creamos y abrimos la base de datos
        BD=new DBHelper(this);
        BD.open();
        
        //Insertamos una nueva alarma con valores _id=1, alarma=1, evento=1
        BD.insertAlarma(1, 1, 1);
        
        //Modificamos la alarma anterior dejándola como _id=1, alarma=2, evento=3
        BD.updateAlarma(1, 2, 3);
        
        //Obtenemos la alarma creada anteriormente
        Alarma alarma = BD.getAlarma(1);
        
        //Borramos la alarma creada anteriormente con índice 1
        BD.removeAlarma(1)
        
        //Obtenemos un listado de todas las alarmas
        ArrayList<Alarma> alarmas = new ArrayList()<Alarma>;
        alarmas =(ArrayList<Alarma>) BD.getAlarmas();
        
    }
    
    @Override
    public void onPause() {
        super.onPause();
        BD.close();
    }
    @Override
    public void onResume() {
        super.onResume();
        BD.open();
    }

Si tenéis cualquier consulta, dejadla en un comentario.

Aquí os dejo un ejemplo algo más avanzado que seguro que os resultará de utilidad:

Código Fuente en GitHub

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

73 Respuestas

  1. Francis Sanchez dice:

    antes que nada gracias por compartir tus conocimientos con nosotros, pero tengo la siguiente pregunta, como podría hacer para copiar toda una base de datos Sqlite en una carpeta de la sd y que se guarde en formato scv o de perdidas en un archivo txt separado por comas

  2. Daniel Dominguez dice:

    Donde construyes el DBAdapter

  3. Alejo Carrasco dice:

    Gracias por el aporte en español, me sirvió mucho en mi proyecto, solo preguntarte una duda, hay alguna forma de Actualizar la base de datos una vez instalada la aplicación con un botón dentro de a misma aplicación, gracias un saludo

    • Miguel dice:

      La clave está en el método copyDataBase(). Es el que se ocupa de leer el fichero desde la carpeta del paquete de la aplicación y guardarlo donde corresponde. Si haces que se llame a ese método mediante un botón puedes hacer que se actualice. Además puedes modificar ese método para que obtenga la base de datos de otra fuente, como puede ser una API REST.

  4. Fernando Vega dice:

    Hola, tengo un problema con mi proyecto tengo una Base de Datos con varios registros que solo utilizo para consulta pero al realizar la primer consulta me indica que las tablas estan vacias. Si pudieran indicarme si hay algo que cambiar.

  5. Danny Coral dice:

    Y en android studio como seria esto?

  6. Enrique dice:

    hola queria saber como puedo relacionar las tablas de sqlite desde el SQLite Database Browser o no es necesario

  7. Albert dice:

    Hola en la clase principal pongo el
    Constructor BaseDatos bd=new BaseDatos(this);
    El problema es que me marca error en this dice que no puede ser aplicado.
    Alguna posible solucion.
    Le agradeceria.

  8. Pusman dice:

    Buenas! No sé si seguirá alguien pendiente de esta entrada, pero tengo una duda con la codificación de la tabla que me está volviendo loco…

    Creo mi tabla en con SQLite Database Browser, y la primera tabla que creo es la de android_metadata como apuntáis, poniendo como valor por defecto es_ES e insertando una línea con ese mismo valor.

    Después creo el resto de tablas que necesito, y muchas de ellas contienen texto con caracteres especiales (tildes, «ñ», etc.).

    Pues bien, a la hora de crear la BDD en tiempo de ejecución, con una clase que hereda de SQLiteOpenHelper, ME CAMBIA A en_US EL VALOR DE LA TABLA android_metadata y no puedo mostrar en la aplicación esos caracteres especiales.

    ¿Alguna idea de por qué se cambia ese valor? ¿Hay alguna configuración que se me esté escapando?

    (Para desarrollar utilizo el eclipse juno, no sé si será problema del eclipse o yo qué sé..)

    Muchas gracias, y un saludo!

  9. Cristian Rivillas dice:

    Saludos:

    Estoy incursionando en el proceso de las apps no se como podría desarrollar una app para android que realice una consulta en un archivo de Excel local?

    Buena noche
    Mil Gracias por sus profetas respuestas

  10. Manhiuco dice:

    Estoy usando Android Studio, en que parte de la estrutura del proyecto debo de copiar el archivo de la base de datos de sqlite (.db) ???

  11. Xpher dice:

    una consulta, estoy trantando de utilizar mi propia base de datos pero siempre crea una nueva base y no logro usar la base que he copiado en assets, alguien podría darme una mano?

  12. Alejandro dice:

    Solo un consejo en el metodo checkDataBase cambia la linea

    return checkDB != null ? true : false;

    por

    return checkDB != null;

    Hace exactamente lo mismo pero es mas entendible.

  13. Liz dice:

    Hola un favor, yo tengo una base de datos sqlite ya hecha y necesito llamar a cada registro desde java android de manera aleatoria.
    pero nose como llamar una tabla externa ya llena de datos desde java android, podrias ayudarme x favor??

    • Jesus Moran dice:

      Buenas, te envio el codigo que cree para hacer la consulta aleatoria, espero te sirva:

      public void mostrarDB() throws SQLException {
      //conecto con la base de datos
      DataBaseHelper BD = new DataBaseHelper(this);
      SQLiteDatabase db = BD.getWritableDatabase();
      //doy un valor aleatorio con el contenido de mi BD
      Random r = new Random();
      // 4 es el tope de mi tabla. Si hay 185 registro colocaria 185
      int et1 = r.nextInt(4);
      String cod;
      // el valor en el query me lo pide en cadena asi que lo cambio
      cod = Integer.toString(et1);
      try {
      BD.openDB();
      TextView text = (TextView) findViewById(R.id.frasesTXT);
      String[] columnas = {«columna1, columna2»};
      cursor = db.query(«NOMBRETABLA», columnas,»_id=»+cod, null,null,null,null,null);
      if (cursor.moveToFirst()){
      String vC1 = cursor.getString(0);
      String vC2 = cursor.getString(1);
      String txt = vC1 +» «+ vC2;
      text.setText(txt);
      }
      BD.close();

      } catch (SQLException e) {
      e.printStackTrace();
      }

      }

      Este codigo me funciona bastante bien. Aprovecho la oportunidad para solicitar informacion, he hecho el tutorial y todo funciona bien, el problema se da que la base de datos la copia (o por lo menos me hace creer que la copia) en la carpeta, pero al revisarla consigo puros registros vacios, es decir, no me copia los datos que ya he introducido. Puede ser error de permiso? como debo declararlo en el manifiesto?

  14. Jürgen dice:

    Hola muy buen tutorial ayuda bastante 😀 solo quiero dar una información relevante y que a mi me causo muchos conflictos en la linea 10 de el paso no. 4 inicias tu DB con DBAdapter(); esto se debe cambiar por el nombre de la clase que has creado para hacer la conexión, que en este ejemplo es DBHelper();, supongo que no es importancia pero a mi me creo muchos conflictos.
    Sobre lo demás no me queda ninguna duda todo excelente muchas gracias de verdad

  15. Omar dice:

    Cuando rescatas el valor de una variable de otra tabla; esta se ve con su _id.
    La pregunta es: ¿Como y dónde puedo hacer que esa _id se relacione con ejemplo su nombre, o si hay un método más sencillo donde pueda asignarle un valor String al resultado de cada _id.

  16. Rodolfo dice:

    Gracias por tu aporte, he seguido tu ejemplo para adecuarlo a mi aplicacion, pero cdo se copia la base de datos en la ruta por defecto de las bases de datos en el sistema Android y hago la consulta pertinente me dice que no encuentra la tabla que cree con anterioridad, si consulto por el plugins de SQLite para eclipse, ciertamente la tabla que debo consultar no se encuentra, agredecido de tu opinion

  17. Yeshua dice:

    Muy buen tutorial, una pregunta…En tu ejemplo solo tienes una tabla, supongo que para más tablas solo debo repetir el procedimiento para cada una, o me equivoco? por otro lado me sale error en DATABASE_TABLE porque como tengo varias tablas en la db que importe no se como distinguirlas. Gracias

  18. Luis dice:

    Consutla mirando el codigo netrunners creas un servico para hacer las tareas de insert, update, etc. Porque razón utilizas un servicio. O se que se gana o se pierde.

  19. Jean dice:

    Hola
    Tienes algun ejemplo de una base de datos sqlite relacional con la menos dos o tres tablas?

  20. Gabriel dice:

    No entiendo porque llama a BD=new DBAdapter(this); ¿Qué es DBAdapter?¿Donde se define? En el ejemplo descargable existe esa clase, pero en el que aparece en esta página no y por más que pruebo a cambiar nada funciona.

  21. Gabriel dice:

    Alarma es un ejemplo, como el que dice caramelos, coches o cualquier cosa. Si te fijas, es una de las columnas de la tabla.

  22. Willian dice:

    Para que sirven las alarmas, soy uevo en esto, y he entendido todo.pero lo que no entiendo que sentido o roll juegan las alarmas en las bases de datos, por favor si fueran muy amabls de aclarame el asundo o un link donde indique ese tema..de antemano gracias…

  23. Gabriel dice:

    Hola a todos a ver si alguien puede aclararme un poco, porque estoy hecho un lío. He empezado hace poco a programar y me he metido en el mundo Android. Llevo varios días desarrollando una aplicación y quiero que esta consulte una base de datos con 500 nombres que meto yo. Mi duda es, ¿tengo que meter a la fuerza un sqlite y poner los nombres con código? ¿puedo crear la BD en excel o Access y después pasarla a un formato que lea android? Estoy un poco perdido porque todo lo referente a sqlite habla de como construir la base de datos desde android pero no se como crearla fuera con un programa visual y luego introducirla en el programa. Un saludo y gracias

  24. DENIS dice:

    Echa un vistazo a una herramienta gratuita – Valentina Studio. Producto asombroso! OMI es el mejor gestor de SQLite para todas las plataformas. http://www.valentina-db.com/en/valentina-studio-overview

  25. Juan Carlos Pasache Anticona dice:

    Hola buenas noches, por favor quisiera saber como edito. sqlite editor en mi motorola que esta con el sistema de estados unidos. Ya que aqui en perú no funciona. Muchas gracias

  26. Felipe Hernandez Palafox dice:

    Felipe Hernandez Palafox :
    Hola buenos días, no es necesario que en el manifest este registrado solo es que crees la clase haciendo herencia de class tunombreclase extends SQLiteOpenHelper {}
    en el manifest solo debes de tener permisos como esto

  27. jillv dice:

    Che solo tengo un problema al Momento de Poner el return db.insert En Los metodos De insertar modificar y eliminar Alarmas me Marca Error Y No Me Reconoce El db Sabes que Podrá ser

  28. Javi dice:

    Olvídate de hacer el archivo manejador de las bases de datos esta aplicación que lo hace todo por vosotros!!

    https://play.google.com/store/apps/details?id=com.pixelsanz.dbcoder&feature=search_result#?t=W251bGwsMSwyLDEsImNvbS5waXhlbHNhbnouZGJjb2RlciJd

  29. Akira dice:

    Excelente aporte me está sirviendo mucho para practicar. Solo para complementar, como puedo agregar la funcionalidad de un spinner en el dialog, por ejemplo si quisiera marcar al cliente como «Familia», «Amigo», «compañero de trabajo», etc. 1000 Gracias

  30. ekaitz dice:

    buenas muy buen tuto me ha venido de lujo.
    una cosa cuando haces en la bd metadata locale es_ES se puede añadir mas idiomas a la BD? y de ser asi como se hace y como se meten y recojen datos de esta forma?? la verdad es que necesito tener una base de datos igual pero que si el idioma de la app es ingles use la BD en ingles y si es en castellano pos la que le corresponde en fin gracias por todo.

  31. alejandro dice:

    me pasa lo mismo. En el emulador va bien, en el tablet no funciuona. No me crea la tabla pq el error que me da es que no encuentra la table. Que permisos hacen falta o que otra causa puede haber?

    gracias

  32. eduardo dice:

    Hola,muchas gracias por el ejemplo es un de los mas entendibles
    una pregunta

    al crear la base de datos de esta manera los metodos
    oncreate y onupgrade no se utilizan?

    y la base de datos se copian cuando inicia la aplicación o
    cuando se llama al void createDataBase()

    estoy aprendiendo android y tenga varias dudas

    gracias

  33. Danny Alexader Trujillo dice:

    He aplicado este algoritmo, pero no se si he identificado que las bases de datos se creen, ademas como puedo saber si verdaderamente se crearon las bases de datos, tengo unas bases de datos que pesa cada una 5 mb tendría algún problema Gracias

  34. AngelH dice:

    Hola como están?

    Como había comentado anteriormente, mi aplicación en el emulador me funciona a la perfección llamando los datos de mi BD, pero cuando creo el .apk no me instala el archivo de BD en el dispositivo.

    Mis permisos son los siguientes en el Manifest :

    Si alguien por favor se ha encontrado con esto me hacen saber.

    Muchísimas gracias!!!

    • susi28 dice:

      A mi está pasando lo mismo. Me funciona bien en el emulador de android, pero al pasarlo a la tablet, no hay forma de que funcione, por favor q permisos hay q tener¿?¿?
      he puesto, el de WRITE.EXTERNAL_STORAGE, READ.EXTERNAL_STORAGE, PERSISTENT_ACTIVITY, nose cual mas probar.GARCIAS.

  35. Androide noob dice:

    Hola, a partir de este ejemplo he intentado hacer pruebas para manejar una base de datos. Mi problema es el siguiente: Una vez hago una busqueda en la BD, muestro en un listview los campos y utilizo un setOnItemClickListener para pasar a la siguiente lista que corresponde con otra busqueda en la BD segun el criterio pasado.
    En cada actividad realizo los metodos onStart y onStop, la aplicacion funciona sin errores pero en el Logcat salen errores de que no se cierra el Cursor (Finalizing a Cursor that has not been deactivated or closed.) No sale inmediatamente sino con un poco de retraso.

    ¿Que puedo hacer para solucionarlo?

    Gracias

    Un saludo

  36. Miguel S. Mendoza dice:

    De nada hombre. Cuando subáis la aplicación a Google Play poner un enlace por aqui para que le echemos un vistazo, 😉

  37. DMC dice:

    MUCHÍSIMAS GRACIAS! Llevaba varios días con ello y el problema es que no tenía claro lo del ciclo de vida (que es elemental… :S).

    Gracias por tu tutorial, un ejemplo buenísimo y recomendable para todo el que quiera probarlo.

    Seguriemos con el proyecto a ver si llegamos a buen puerto… Muchas gracias de nuevo por tu aporte y por tu respuesta prácticamente instantánea 😉

    Un saludo!

  38. Miguel S. Mendoza dice:

    Como suponía intentas meter datos en la base de datos antes de realizar la conexión a la misma. La conexión se realiza en el método onStart(), y el código de tu proyecto que inserta datos en la base de datos, está en onCreate(), que se ejecuta antes. Échale un ojo a http://developer.android.com/reference/android/app/Activity.html dónde se muestra el ciclo de vida de las Actividades y el orden en el que los métodos son llamados. La solución pasa por extraer el código de inserción de datos a un método y llamarlo justo antes de la llamada a loadSecciones() en el método onServiceConnected del objeto mConnection. Proyecto arreglado: https://www.dropbox.com/s/8txzv82zkr61qwh/DMC.zip

  39. DMC dice:

    Hola de nuevo amigo. No doy con ello, me estoy volviendo loco comprobando donde puede estar el error…

    Te paso el link del proyecto entero por si puedes echarlo un vistazo.
    https://dl.dropbox.com/u/13885050/proyectoDMC.rar

    Consiste en un parser sencillo de un XML y luego queremos meter lo que leemos en la base de datos (de momento solo estamos intentando meter un solo dato para probar).

    Gracias de antemano.

    Un saludo!

  40. Miguel S. Mendoza dice:

    Sin ver el código del proyecto lo único que te puedo decir es que en la línea 137 del fichero ParserActivity.java estás utilizando un objeto que no has inicializado. Sospecho que puede ser el objeto ‘dbAdapter’, pero no te lo aseguro. Utiliza el método Log.e(«TAG», ALGUNA VARIABLE.toString()) para comprobar el valor de las variables y objetos de esa línea. Antes de hacer consultas a la base de datos procura comprobar que ese objeto esté inicializado, ya que si no recuerdo mal cuando se inicializa, se inicializa también una variable booleana llamada mBound que indica que se ha realizado la conexión a la base de datos.

  41. DMC dice:

    Hola, estamos usando el código del ejemplo que tienes subido como base para interactuar con la base de datos de nuestra app.

    Queremos guardar un dato utilizando el método addClient, pasándole una String diréctamente, pero nos salen estos errores.

    11-23 19:13:18.036: W/System.err(19774): java.lang.NullPointerException
    11-23 19:13:18.036: W/System.err(19774): at hepapptology.david.parser.ParserActivity.addClient(ParserActivity.java:137)
    11-23 19:13:18.036: W/System.err(19774): at hepapptology.david.parser.ParserActivity.onCreate(ParserActivity.java:73)
    11-23 19:13:18.036: W/System.err(19774): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    11-23 19:13:18.036: W/System.err(19774): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
    11-23 19:13:18.046: W/System.err(19774): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
    11-23 19:13:18.046: W/System.err(19774): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
    11-23 19:13:18.046: W/System.err(19774): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
    11-23 19:13:18.046: W/System.err(19774): at android.os.Handler.dispatchMessage(Handler.java:99)
    11-23 19:13:18.046: W/System.err(19774): at android.os.Looper.loop(Looper.java:123)
    11-23 19:13:18.046: W/System.err(19774): at android.app.ActivityThread.main(ActivityThread.java:4627)
    11-23 19:13:18.046: W/System.err(19774): at java.lang.reflect.Method.invokeNative(Native Method)
    11-23 19:13:18.046: W/System.err(19774): at java.lang.reflect.Method.invoke(Method.java:521)
    11-23 19:13:18.046: W/System.err(19774): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    11-23 19:13:18.046: W/System.err(19774): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    11-23 19:13:18.046: W/System.err(19774): at dalvik.system.NativeStart.main(Native Method)

    Hemos revisado todo el código, y no encontramos el error. El caso es que nos funciona la aplicación, y nos muestra el contenido de la base de datos, pero no logramos escribir en ella. Él único cambio realizado ha sido quitar el context menu, y llamamos al método de añadir directamente.

    Muchas gracias.

    Un saludo!

  42. Miguel S. Mendoza dice:

    Buena puntualización, 😉

  43. davidjcd dice:

    Muy buen tutorial, me ha ayudado a mucho.
    De todas formas me gustaría puntualizar un detalle. No es necesario cambiar las claves primarias para que se llamen _id. El problema lo puede dar cuando usamos un CursorAdapter en la base de datos, pero eso se puede solucionar de otra manera.

    Por ejemplo, en una tabla donde la clave primaria sea codigo, el select podría hacerse así:

    SELECT codigo as _id, [codigo], valor1, valor2, … FROM tabla.

    Esto puede ser de ayuda cuando, por ejemplo, tenemos una clave primaria formada por dos campos juntos. En ese caso sólo uno de los campos se debe enteder como el _id que necesitamos.

  44. AngelH dice:

    Hola!!!

    Excelente Tutorial!!!, Cuando trato de probar un ejemplo que hice en la consola virtual me funciona muy bien, pero cuando creo el .apk y lo paso a mi dispositivo me cuelga la aplicación cuando trato de consultar la base de datos.

    Alguien le ha pasado esto?

    Saludos!

  45. Anónimo dice:

    @Walter Cordero
    ¿Has comprobado los permisos de la aplicación?

  46. Marcos dice:

    llevo un rato buscando como laburar con mi propia base de datos y hacerlo de la formas mas simple, sin tener que escribir lineas y lineas de java, con este ejemplo me diste una mano enorme… Muchas gracias por el Aporte!

  47. Walter Cordero dice:

    que tal amigo como esta fijate que me descargue el ejemplo del cual comentas, pero fijate que me esta tirando error en el archivo SQLiteActivity.java, no se si pudieras echarme la mano con esos errorsitos que estan saliendo, los errores salen en estos métodos:
    public void onClick(DialogInterface dialog, int id)
    public void onClick(DialogInterface dialog, int id)
    public void onClick(DialogInterface dialog, int id)
    onClick(DialogInterface dialog, int id)
    onClick(DialogInterface dialog, int id)
    onClick(DialogInterface dialog, int id)
    onServiceConnected(ComponentName className, IBinder service)
    onServiceDisconnected(ComponentName arg0)

    de antemano muchas gracias y muy buen aporte.

  48. John David dice:

    @Luz
    Luz, lograste solucioanr ese tema? Tengo el mismo error y pues soy nuevo en el tema y no estoy seguro qué pueda ser.

  49. La mayoría del código del tutorial lo saqué de otra aplicación más grande en la que necesitaba que la clase fuera serializable, pero no es obligatorio para este tutorial. Voy a quitarlo para no confundir. Gracias por el apunte, 😉
    De todas formas si quieres hacer una buena base de datos descárgate el código de ejemplo que aparece al final, ya que todavía no he tenido tiempo de modificar el tutorial, y ese código es bastante más eficiente.

  50. Dark Musician dice:

    Buenas noches. Quisiera saber por qué implementas la interface Serializable en tu clase Alarma, ¿es esto obligatorio?. Es que soy nuevo en Java no se si es necesario.

  51. @reddreik
    Estoy preparando una reestructuración del tutorial con un proyecto completo de ejemplo, dónde también creo el Adaptador de la Base de Datos como un Servicio accesible para otras aplicaciones. Espero tenerlo listo para este fin de semana.

  52. reddreik dice:

    Hola:

    Estoy tratando de usar tu coidgo como base para una aplicacion, pero cuando lo corro en el emulador me da error y debo cerrarlo, no se si puede enviarme el coidgo de la clase DBHelper, para comprarlo como lo hice y la preicpal donde se activa.

    muchas gracias.

  53. @Diego
    Este tutorial es precisamente para utilizar bases de datos externas que podamos distribuir de manera inicial dentro del proyecto. Lo que ocurre realmente al utilizar un fichero externo es que la aplicación crea su propia base de datos vacía y copia los contenidos del fichero, de tal forma que cualquier modificación que se haga en la base de datos con la aplicación ya no implicaría al fichero en sí, ya que toodas las consultas y modificaciones se harían en la base de datos propia de la aplicación.
    He añadido una captura de cómo quedaría el proyecto añadiendo el fichero de base de datos porque es posible que esa parte no quedara muy clara.
    Puedes utilizar cualquier fichero de SQLite, la extensión no es necesaria, lo único que tienes que tener en cuenta es que debe existir la tabla “android_metadata” y que la clave primaria de todas las tablas que vayas a utilizar se tiene que llamar ‘_id’.

  54. Diego dice:

    Muchachos, la info está excelente, soy novato en el tema y tengo una duda grande(para mi):

    Por lo general muchas de las aplicaciones existentes, tienen bases de datos con información inicial para el correcto funcionamiento de la app, me gustaría saber si tienen links o información donde me pueda documentar acerca de como distribuir estas bases de datos iniciales en los apk.

    Muchas gracias

  55. @nac13k
    En TEXT no hay restriccion de caracteres. Comprueba el modo en el que estas introduciendo los datos en la base de datos. Quizá estás cometiendo algún error en la concatenación a la hora de parsear las instrucciones INSERT.

  56. @Juan
    En el SQLite Database Browser, tienes que cambiar la codificación de caracteres de la base de datos. Actualmente debes de tenerlo en UTF. Para cambiarlo le das a «Edit->Preferences» y cambias la combo de «Database encoding» a «Latin», y así debería funcionar.

  57. nac13k dice:

    Buen dia, una duda alquien sabe por uqe cuando alamaceno una URL en un campo Text de sql, cuando hago la consulta «select URL from Tabla» me salen incompletas las url, salen hasat el http:// o http://www. pero de ahi en adelante no salen, tengo poca esxperiencia en sqlite solo habi utilizado mysql.

    espero alguien pueda ayudarme con esta duda.

    Gracias.

  58. Juan dice:

    Hola me gustaria que me ayudaras a saber como insertar acentos y caracteres raros en la base de datos, segui el tutorial al pie de la letra y funciona bien, pero a la hora de meter acentos o tildes los guarda como caracteres raros la base de datos, y al ser jalados por java e imprimirlos, los imprime igual que en la base de datos. De antemano muchas gracias!!!!!! =)

  59. @Ehison Perez
    No puedo pasarte el proyecto completo porque forma parte de un proyecto más grande. Sin embargo me has dado una idea de crear un ejemplo más pequeño y subirlo. Pero ahora no dispongo de mucho tiempo y no se cuando podré tenerlo a punto.
    De todas formas, el error que te puede estar dando en el teléfono puede venir de no meter el fichero correctamente en la carpeta «assets».
    El problema que tiene programar en android es que no es muy sencillo depurar la ejecución. Te recomiendo hacer lo siguiente:
    – En los lugares donde creas que puede estar viniendo el error (cath, etc.) coloca el siguiente código, personalizando los mensajes a tu gusto:
    Log.d(«DEBUG ANDROID», «Mensaje de depuración»);
    -En eclipse vas a «Window->Show View->Other…» y en la carpeta de Android verás «LogCat», le das a OK y se te mostrará una ventana dónde podrás ver todos los mensajes de debug de la aplicación, y te permitirá crear filtros. En este caso, y según el código que te he puesto, lo suyo es crear un filtro por «DEBUG ANDROID», y así podrás tener algo de información sobre lo que está sucediendo.

  60. @Cardiobeta
    No es necesario registrar la clase en el Manifest puesto que no es una Actividad que deba manejar la aplicación. Es tan solo una clase de ayuda que te permite acceder a la base de datos. En Android puedes crearte todas las clases auxiliares que necesites ya que no deja de ser Java.

  61. Ehison Perez dice:

    Buenas Tardes amigo el codigo parece estar muy bien armado pero siempre me da error cuando lo emulo en el telefono no se si me podrias pasar el codigo o el proyecto completo para verificarlo bien ya que me hace falata este parte para un proyecto de pasantias q estoy haciendo. Muchas Gracias espero tu ayuda

  62. Cardiobeta dice:

    Hola. Muy buen tutorial. El asunto es que como hago para registra en el Android Manifest la clase DBhelper creada. Gracias de antemano.

    • Felipe Hernandez Palafox dice:

      Hola buenos días, no es necesario que en el manifest este registrado solo es que crees la clase haciendo herencia de class tunombreclase extends SQLiteOpenHelper {}

      en el manifest solo debes de tener permisos como estos

  63. Perdona por haber tardado en responder. Vamos a ver:

    checkDB es null por la asignación anterior al bloque try catch. Si la base de datos no existe, se genera una excepción SQLiteException, y no se hace nada porque es capturado en ese mismo bloque try catch, por lo que si genera un error es normal.
    Si el error que te da no es SQLiteException el error puede venir por otro sitio.

  64. Luz dice:

    Hola, yo estaba siguiendo el tutorial en ingles, pero el tuyo me agrego algunas cosas que me faltaban, gracias =D
    Pero ahora tnego un problema:

    En el checkDataBase() en la linea:

    checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

    Se supone que si no existe solo debulve un null, que al final genera un false, y sigue el proceso, peeeero al llegar a esa linea me genera un error diciendome que no encuentra el path lo cual es obvio por que no existe, pero segun yo ese error no deberia generarse.

    No se si podrias ayudarme, te lo agradeceria muchisimo =)

  1. 15 febrero, 2013

    […] Otra forma de usar las bases de datos en android Comparte en:TwitterFacebookCorreo electrónicoGoogle +1Me gusta:Me gustaSe el primero en decir que […]