Un espacio para los entusiastas del web

12 com comentarios en total.
6 Jul 2009
16,816 Lecturas
Tags: Tecnologías móviles, , , , , y 2 más.

Guia Android: Avanzando con la base de datos

En el primer tutorial sobre Android hicimos el típico Hello World, explicando la estructura de Android, cómo funcionaba ese básico ejemplo. En este segundo tutorial vamos a meternos en muchos más detalles. Vamos a construir un bloc de notas para nuestro teléfono Android. Debido a que son más archivos y más líneas de código que en el primer ejercicio os he comprimido los archivos iniciales y finales en un archivo zip (Descargar). Asi siempre tenéis código dónde comparar por si no os funciona algo. Pero como siempre, es mejor que vayáis siguiendo el tutorial y veáis la evolución del código en vez de mirar directamente la solución.

Conexión a la base de datos

Una vez que habéis creado el proyecto Android seleccionando un proyecto existente (Notas), podéis ver la estructura de archivos. Hay ya algunos archivos creados pero el único que he dejado con información es /src/com.android.demo.notepad1/NotasDbAdapter.java. Este archivo se va a encargar de conectarse a la base de datos para que no tengamos que estar lidiando con esto en otras partes del código. Recordad que estamos en un esquema MVC. Este va a ser nuestro primer modelo. Miremos el código en general:

public class NotasDbAdapter {

    // variables varias
	...

    private static class DatabaseHelper extends SQLiteOpenHelper {

        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {...}

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {...}
    }

    /**
     * Constructor - pasa el contexto para poder abrir o crear la DB
     */
    public NotasDbAdapter(Context ctx) {...}

    /**
     * Abre la base de datos de notas. Si no puede abrirla, la crea. Si no se puede
     * lanza una excepcion
     */
    public NotasDbAdapter open() throws SQLException {...}

    public void close() {...}

    /**
     * Inserta una nueva nota con el t’tulo y el texto dados. Si se crea correctamente
     * devuelve el rowId, en caso contrario, devuelve -1 para indicar que ha habido
     * un error..
     */
    public long createNote(String title, String body) {...}

    /**
     * Borra la nota con el rowId dado
     */
    public boolean deleteNote(long rowId) {...}

    /**
     * Devuelve un Cursor apuntando a la lista de todas las notas
     */
    public Cursor fetchAllNotes() {...}

    /**
     * Devuelve un Cursor apuntando a la nota con el rowId dado
     */
    public Cursor fetchNote(long rowId) throws SQLException {...}

    /**
     * Actualiza la nota con los detalles dados.
     */
    public boolean updateNote(long rowId, String title, String body) {...}
}

Tenemos métodos para crear, actualizar, abrir y cerrar la base de datos. Y luego los métodos CRUD para crear una nueva nota, devolver su información (o la de varias notas), actualizarla y borrarla. Esta clase es muy importante ya que estará en todas vuestras apps de una forma u otra asi que miremos método a método.

    private static class DatabaseHelper extends SQLiteOpenHelper {

        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            // sentencia drop
            onCreate(db);
        }
    }

Esta clase auxiliar nos permitirá abrir la base de datos, crearla si no existe y actualizarla al lanzar una nueva versión. La sentencia SQL para crear es:

// sentencia create

 private static final String DATABASE_CREATE = "create table notes (_id integer primary key autoincrement," + "title text not null, body text not null);";

Cómo podéis haber observado ya antes, estamos utilizando la base de datos SQLite, es parecida a MySQL pero tiene pequeños detalles diferentes. Con esto ya tenemos creada la base de datos. Veamos el método para insertar notas:

   public long createNote(String title, String body) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_TITLE, title);
        initialValues.put(KEY_BODY, body);

        return mDb.insert(DATABASE_TABLE, null, initialValues);
    }

A través de la clase ContentValues guardamos la información con el método put y la insertamos. Para actualizar es casi igual pero usamos el método update en vez de insert. Hay que acordarse de indicar el rowId:

public boolean updateNote(long rowId, String title, String body) {
        ContentValues args = new ContentValues();
        args.put(KEY_TITLE, title);
        args.put(KEY_BODY, body);

        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
    }

El método borrar es muy obvio asi que pasamos a recuperar una nota de la base de datos:

    public Cursor fetchNote(long rowId) throws SQLException {

        Cursor mCursor =

                mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
                        KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
                        null, null, null, null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;

    }

Hacemos una query indicando que queremos un array de tres strings con los tres campos que queremos, y con la condición de rowId. El resto de los parámetros se usan si queremos hacer groupBy, having u orderBy. Después comprobamos que no está vacío y si es así movemos el cursor a la primera posición que apunta a la nota que queremos.

Insertando notas

Vamos a modificar el layout de la actividad inicial /res/layout/notepad_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="wrap_content"
    android:layout_height="wrap_content">

  <ListView android:id="@android:id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
  <TextView android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/no_notes"/>

</LinearLayout>

Tenemos dos elementos: una lista y un campo de texto. El TextView sólo se muestra si la lista está vacía. Android sabe esto gracias a empty, que está unido al valor de list. A través de android:id="@android:id/list" indicamos que queremos que esa lista se rellene con los valores de la variable list de la actividad.

Para mostrar la información que aparece en cada fila de la lista necesitamos crear un nuevo template. Creamos un nuevo archivo /src/layout/notes_row.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@+id/text1"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

En el campo de texto (TextView) vamos a mostrar solo el contenido de la variable text1 de la actividad. Antes de ir a la actividad mirad la clase R.java que os dije en el anterior tutorial que Android la manejaba automáticamente. Podéis ver cómo ha añadido el archivo nuevo y la variable text1.

Vayamos ahora con Notas.java, miremos su estructura:

public class Notas extends Activity {

    public void onCreate(Bundle savedInstanceState) {...}

    public boolean onCreateOptionsMenu(Menu menu) {...}

    public boolean onOptionsItemSelected(MenuItem item) {...}
}

onCreate() es el método principal de la actividad donde ejecutaremos todo nuestro código. onCreateOptionsMenu() creará el menú de opciones y onOptionsItemSelected() estará atento a qué botón del menú presionamos para ejecutar la acción correspondiente. Repito que es sólo sobre acciones sobre el menú, las acciones de otros botones o enlaces van en otros métodos, exactamente con Listeners, pero eso ya lo veremos más adelante.

Lo primero que vamos a hacer es convertir a Notas en una actividad de lista, para ellos hacemos que extienda a ListActivity:

public class Notas extends ListActivity

Una combinación de teclas muy útil para arreglar los imports de los paquetes es ctrl-shift-O en Windows o Linux, o cmd-shift-O en el Mac.

Queremos que en la pantalla principal de Notas muestre la lista de notas, para ello tiene que conectarse a la base de datos, coger la información y mostrarla en el layout que hemos hecho antes:

	private NotasDbAdapter mDbHelper;

	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.notepad_list);
        // new notas
        mDbHelper.open();
        fillData();
    }

Declaramos el objeto fuera para que esté disponible a todos los métodos, fijamos que el layout sea notepad_list (fijaros como referenciamos aquí al layout, no usamos urls o directorios, si no referencia mediante la clase R.java). Vamos a coger la información en un método privado para que quede todo más ordenado:

 private void fillData() {
	// Recuperamos todas las notas de la DB y creamos una lista Cursor
	c = mDbHelper.fetchAllNotes();
	startManagingCursor(c); 

	String[] from = new String[] { NotasDbAdapter.KEY_TITLE };
	int[] to = new int[] { R.id.text1 }; 

	/ Y creamos un adaptador array para que vaya mostrando las filas
	SimpleCursorAdapter notes =
		new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
	setListAdapter(notes);
}

Ya empezamos a ver más métodos internos de Android, os animo a entrar a la API de Android e ir viendo lo que hacen exactamente, es la mejor forma de aprender. En fillData() recuperamos todas las notas de la DB con el método fetchAllNotes que hicimos al principio, y luego creamos un adaptador que relaciona el campo del objeto que queremos (KEY_TITLE) con la variable text1 (otra vez referenciada por R.java) e indica que queremos que use el layout notes_row.xml que hemos creado antes. Por último avisa a ListActivity que notes va a ser la lista que queremos mostrar.

Con estas modificaciones ya podríamos ver las notas pero no tenemos ninguna asi que vamos a crear la actividad en un momento para que podamos probarlo más a fondo. En Notas.java añadamos el botón de añadir nota. Basta con llamar a la clase superior para crear el menu y añadir el botón de Add Item en la primera posición.

	public static final int INSERT_ID = Menu.FIRST;

	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        boolean result = super.onCreateOptionsMenu(menu);
        menu.add(0, INSERT_ID, 0, R.string.menu_insert);
        return result;
    }

Y añadimos otra variable de texto a strings.xml

	<string name="menu_insert">Add Item</string>

Perfecto, ahora hagamos que al hacer click en este nuevo botón ejecute la nueva actividad para mostrar el formulario. Para eso modificamos el método onOptionsItemSelected() también de Notas.java

	@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case INSERT_ID:
            createNote();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

Capturamos el Id de la opción del menú y si es la primera ejecutamos el método createNote(). En un primer paso vamos a hacer que inserte una nota con un título y texto fijos. En el siguiente paso ya crearemos el formulario:

    private void createNote() {
        String noteName = "Note " + mNoteNumber++;
        mDbHelper.createNote(noteName, "");
        fillData();
    }

La razón de llamar a fillData() de nuevo es para que recargue la lista una vez que se ha terminado de ejecutar el evento de hacer click en la opción del menú Add Item.

Es hora de ver en acción lo que estamos viendo. Comprueba que no hay errores en ningún archivo, arregla los imports y ejecuta como un proyecto de Android. Si das a menu podrás añadir una nota e irás viendo como se crea una nota nueva cada vez que le das. Enhorabuena, hemos conseguido comunicarnos correctamente con la base de datos.

Paginas: 1 2

Javier Fernandez EscribanoJavier Fernandez Escribano para Maestros del Web.
Agrega tu comentario | Enlace permanente al artículo

Síguenos en: @maestros | Fan page

Comentarios

  1. Muy bueno y muy completo. Voy a ver si me sale. Sigo con afan tus tutoriales. Gracias

    Responder
  2. Lo tengo que probar, y mis felicitaciones por esta iniciativa.
    Animo y saludos.

    Responder
  3. muchas gracias a los 2! Ya me contaréis como os va

    Responder
  4. Creo que de este tutorial al anterior hay un salto demasiado grande para los que no tenemos mucha idea podamos pillarlo.

    Creo que sería interesante ir algo más despacio. Simplemente primero creando botones y darles utilidad, añadir listas y darles utilidad, etc… e incluso coger la aplicación Hola Mundo y que vaya mejorando y vaya sirviendo para cosas y podamos ver cada cosa para que sirve.

    En fin, es solo una opinión.
    Tal vez tu idea es ir algo más rápido y centrarte más en la gente que tiene algo de nivel en la programación en general.

    Saludos y gracias.

    Responder
  5. Huy, por fin algo en serio en nuestro idioma!
    Muchas gracias viejo te invito a seguir con esto! Ya tengo todo instalado y configurado. Lei la primera introduccion y palpe esta asi que ma;ana me pongo a seguir este curso y te cuento. Seguramente tendre muchas cosas que preguntar….
    Saludos ;)

    Responder
  6. Angel38

    Muchas gracias,

    Me ha servido mucho para entender el funcionamiento de Android.

    Responder
  7. gustavo

    Estaria mas que bueno que hicieras un video, ya que es complicado seguir los pasos de este modo.. Tengo 15 años y la verdad que no entiendo un pepino, recien acabo de hacer la app que dice el nombre de la aplicacion, le cambie la imagen apra que aparesca en el menu, y le agregue un texto abajo.. Por favvor necesito ayuda muchas Gracias!.

    Responder
  8. Mauro

    Muchas gracias, espero que tengas exito en tu master, abrazo desde Buenos Aires

    Responder
  9. Excelente tutorial! después de muchos intentos, con este tutorial pude tener una base de datos “comunitaria” que la pueden compartir todas las Actividades!

    Muchas Gracias! :D

    Responder

Deja tu Comentario

Maestros del Web se reserva el derecho de moderación de los comentarios. Evita utilizar palabras soeces, ataques directos, descalificativos, insultos, de lo contrario tu comentario será eliminado.



Acerca de
Maestros del Web nace cuando intentamos traducir Webmaster al Español. Nacimos orientados al diseño y desarrollo web. Hoy somos un espacio de apoyo para los entusiastas que participan en proyectos en la red.
Leer más de Maestros del Web