Sunteți pe pagina 1din 32

PRCTICA 1: USO DE SQLITE EN ANDROID

Objetivo
Desarrollar un conjunto de aplicaciones que permitan describir el funcionamiento del
almacenamiento de informacin en SQLite haciendo uso de Android.

Introduccin
SECCIN 1
En los siguientes puntos de esta prctica, se van a tratar de describir las distintas opciones de
acceso a datos que proporciona la plataforma y en cmo se pueden realizar las tareas ms
habituales dentro de este apartado.
La plataforma Android proporciona dos herramientas principales para el almacenamiento y
consulta de datos estructurados:

Bases de Datos SQLite


Content Providers
Esta prctica se centra en la primera opcin, SQLite, que abarcar todas las tareas relacionadas
con el almacenamiento de los datos propios de una aplicacin. El segundo de los mecanismos,
los Content Providers, que se trataran ms adelante, facilitar la tarea de hacer visibles esos datos
a otras aplicaciones y, de forma recproca, de permitir la consulta de datos publicados por terceros
desde una aplicacin.
SQLite es un motor de bases de datos muy popular en la actualidad para ofrecer caractersticas tan
interesantes como su pequeo tamao, no necesita servidor, precisa poca configuracin,
es transaccional y por supuesto ser de cdigo libre.
Android incorpora de serie todas las herramientas necesarias para la creacin y gestin de bases
de datos SQLite, y entre ellas una completa API para llevar a cabo de manera sencilla todas las
tareas necesarias. Sin embargo, en este primer artculo sobre bases de datos en Android se va a
entrar en mucho detalle con esta API. Por el momento se limitar a ver el cdigo necesario para
crear una base de datos, se insertar algn dato de prueba, y se ver cmo se puede comprobar
que todo funciona correctamente.
En Android, la forma tpica para crear, actualizar, y conectar con una base de datos SQLite ser a
travs de una clase auxiliar llamada SQLiteOpenHelper, o para ser ms exactos, de una clase
propia que derive de ella y que se debe personalizar para adaptarse a las necesidades concretas de
la aplicacin.

La clase SQLiteOpenHelper tiene tan slo un constructor, que normalmente no necesita


sobrescribirse, y dos mtodos abstractos, onCreate() y onUpgrade(), que se deber personalizar
con el cdigo necesario para crear la base de datos y para actualizar su estructura
respectivamente.
Como ejemplo, se crear una base de datos muy sencilla llamada BDUsuarios, con una sola tabla
llamada Usuarios que contendr slo dos campos: nombre y email. Para ello, se va a crear una
clase derivada de SQLiteOpenHelper que se llama UsuariosSQLiteHelper, donde se sobrescriben
los mtodos onCreate() y onUpgrade()para adaptarlos a la estructura de datos indicada:
packagenet.sgoliver.android.bd;
import
import
import
import

android.content.Context;
android.database.sqlite.SQLiteDatabase;
android.database.sqlite.SQLiteDatabase.CursorFactory;
android.database.sqlite.SQLiteOpenHelper;

public class UsuariosSQLiteHelper extends SQLiteOpenHelper {


//Sentencia SQL para crear la tabla de Usuarios
String sqlCreate = "CREATE TABLE Usuarios (codigo INTEGER, nombre TEXT)";
public UsuariosSQLiteHelper(Context contexto, String nombre,
Cursor Factoryfactory, int version) {
super(contexto, nombre, factory, version);
}
@Override
public void onCreate(SQLiteDatabasedb) {
//Se ejecuta la sentencia SQL de creacin de la tabla
db.execSQL(sqlCreate);
}
@Override
public void
//NOTA:
//
//
//

onUpgrade(SQLiteDatabasedb, intversionAnterior, intversionNueva) {


Por simplicidad del ejemplo aqu utilizamos directamente la opcin de
eliminar la tabla anterior y crearla de nuevo vaca con el nuevo formato.
Sin embargo lo normal ser que haya que migrar datos de la tabla antigua
a la nueva, por lo que este mtodo debera ser ms elaborado.

//Se elimina la versin anterior de la tabla


db.execSQL("DROP TABLE IF EXISTS Usuarios");
//Se crea la nueva versin de la tabla
db.execSQL(sqlCreate);
}
}

Lo primero que se hace es definir una variable llamado sqlCreate donde se almacena la
sentencia SQL para crear una tabla llamada Usuarios con los campos
alfanumricos nombre e email. Para ms informacin sobre SQLite se puede consultar
la documentacin oficial.
El
mtodo onCreate() ser
ejecutado
automticamente
por
la
clase UsuariosDBHelper cuando sea necesaria la creacin de la base de datos, es
decir, cuando an no exista. Las tareas tpicas que deben hacerse en este mtodo sern
la creacin de todas las tablas necesarias y la insercin de los datos iniciales si son

necesarios. En este caso, slo se va a crear la tabla Usuarios descrita anteriormente.


Para la creacin de la tabla se utilizar la sentencia SQL ya definida y se ejecutar contra
la base de datos utilizando el mtodo ms sencillo de los disponibles en la API de SQLite
proporcionada por Android, llamado execSQL(). Este mtodo se limita a ejecutar
directamente el cdigo SQL que se le pase como parmetro.
Por su parte, el mtodo onUpgrade() se lanzar automticamente cuando sea
necesaria una actualizacin de la estructura de la base de datos o una conversin de los
datos. Un ejemplo prctico: imagine que se publica una aplicacin que utiliza una tabla
con los camposusuario e email (llamada versin 1 de la base de datos). Ms
adelante, se amplia la funcionalidad de la aplicacin y se necesita que la tabla tambin
incluya un campo adicional como por ejemplo con la edad del usuario (versin 2 de la
base de datos). Pues bien, para que todo funcione correctamente, la primera vez que se
ejecute la versin ampliada de la aplicacin se necesitar modificar la estructura de la
tabla Usuarios para aadir el nuevo campo edad. Pues este tipo de cosas son las que
se encargar de hacer automticamente el mtodo onUpgrade() cuando se intente abrir
una versin concreta de la base de datos que an no exista. Para ello, como parmetros
recibe la versin actual de la base de datos en el sistema, y la nueva versin a la que se
quiere convertir. En funcin de esta pareja de datos se necesitar realizar unas acciones
u otras. En el caso del ejemplo se opta por la opcin ms sencilla: borrar la tabla actual y
volver a crearla con la nueva estructura, pero como se indica en los comentarios del
cdigo, lo habitual ser que se necesite algo ms de lgica para convertir la base de
datos de una versin a otra y por supuesto para conservar los datos registrados hasta el
momento.
Una vez definida la clase helper, la apertura de la base de datos desde la aplicacin
resulta ser algo de lo ms sencillo. Lo primero ser crear un objeto de la clase
UsuariosSQLiteHelper al que se pasar el contexto de la aplicacin (en el ejemplo
una referencia a la actividad principal), el nombre de la base de datos, un
objeto CursorFactory que tpicamente no ser necesario (en ese caso se pasar el
valor null), y por ltimo la versin de la base de datos que se necesita. La simple
creacin de este objeto puede tener varios efectos:

Si la base de datos ya existe y su versin actual coincide con la solicitada simplemente se realizar
la conexin con ella.
Si la base de datos existe pero su versin actual es anterior a la solicitada, se llamar
automticamente al mtodo onUpgrade() para convertir la base de datos a la nueva versin y se
conectar con la base de datos convertida.
Si la base de datos no existe, se llamar automticamente al mtodo onCreate() para crearla y se
conectar con la base de datos creada.
Una vez que se tiene una referencia al objeto UsuariosSQLiteHelper, se llamar a su mtodo
getReadableDatabase() o getWritableDatabase() para obtener una referencia a la base de datos,

dependiendo si slo se necesitan consultar los datos o tambin se necesitan realizar


modificaciones, respectivamente.
Ahora que ya se ha conseguido una referencia a la base de datos (objeto de tipo SQLiteDatabase)
ya se pueden realizar todas las acciones que se quieran sobre ella. Para este ejemplo se limitar a
insertar 5 registros de prueba, utilizando para ello el mtodo ya comentado execSQL() con las
sentencias INSERT correspondientes. Por ltimo se cerrar la conexin con la base de datos
llamando al mtodo close().
packagenet.sgoliver.android.bd;
import android.app.Activity;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
public class AndroidBaseDatos extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Abrimos la base de datos 'DBUsuarios' en modo escritura
UsuariosSQLiteHelperusdbh =
newUsuariosSQLiteHelper(this, "DBUsuarios", null, 1);
SQLiteDatabasedb = usdbh.getWritableDatabase();
//Si hemos abierto correctamente la base de datos
if(db != null)
{
//Insertamos 5 usuarios de ejemplo
for(int i=1; i<=5; i++)
{
//Generamos los datos
int codigo = i;
String nombre = "Usuario"+ i;
//Insertamos los datos en la tabla Usuarios
db.execSQL("INSERT INTO Usuarios (codigo, nombre) "+
"VALUES ("+ codigo + ", '"+ nombre +"')");
}
//Cerramos la base de datos
db.close();
}
}
}

En primer lugar se ver dnde se ha creado la base de datos. Todas las bases de datos SQLite
creadas por aplicaciones Android utilizando este mtodo se almacenan en la memoria del telfono
en un archivo con el mismo nombre de la base de datos situado en una ruta que sigue el siguiente
patrn:
/data/data/paquete.java.de.la.aplicacion/databases/nombre_base_datos

En el caso de este ejemplo, la base de datos se almacenara por tanto en la ruta siguiente:
/data/data/net.sgoliver.android.bd/databases/DBUsuarios
Para comprobar esto se puede hacer lo siguiente. Una vez ejecutada por primera vez desde Eclipse
la aplicacin de ejemplo sobre el emulador de Android (y por supuesto antes de cerrarlo) se puede
i a la pe spe tiva DDM DalvikDebug Monitor Server de E lipse y e la solapa File Explorer se
puede acceder al sistema de archivos del emulador, donde se puede buscar la ruta indicada de la
base de datos. Se puede ver esto en la siguiente imagen:

Con esto ya se comprobar al menos que el archivo de la base de datos se ha creado en la ruta
correcta. Ya slo queda comprobar que tanto las tablas creadas como los datos insertados
tambin se han incluido correctamente en la base de datos. Para ello se puede recurrir a dos
posibles mtodos:
1. Trasnferir la base de datos a la PC y consultarla con cualquier administrador de bases de datos
SQLite.
2. Acceder directamente a la consola de comandos del emulador de Android y utilizar los comandos
existentes para acceder y consultar la base de datos SQLite.
El primero de los mtodos es sencillo. El archivo de la base de datos puede ser transferido a la PC
utilizando el botn de descarga situado en la esquina superior derecha del explorador de archivos
(remarcado en rojo en la imagen anterior). Junto a este botn aparecen otros dos para hacer la
operacin contraria (copiar un archivo local al sistema de archivos del emulador) y para eliminar
archivos del emulador. Una vez descargado el archivo a nuestro sistema local, se puede utilizar

cualquier administrador de SQLite para abrir y consultar la base de datos, por


ejemplo SQLiteAdministrator (freeware).
El segundo mtodo utiliza una estrategia diferente. En vez de descargar la base de datos al sistema
local, es el usuario el que accede de forma remota al emulador a travs de su consola de
comandos (shell). Para ello, con el emulador de Android an abierto, se debe de abrir una consola
de MS-DOS y utilizar la utilidad adb.exe (AndroidDebug Bridge) situada en la carpeta platformtools del SDK de Android (por ejemplo c:\Users\Usuario\AppData\Local\Android\androidsdk\platform-tools\). En primer lugar se consultarn los identificadores de todos los emuladores
e eje u i
edia te el o a do adbdevices . Esto de e devolve u a i a i sta ia si slo se
tiene un emulador abierto, que en este aso pa ti ula se lla a emulator-5554 .
Tras conocer el identificador del emulador, se va a a ede a su shell edia te el o a do adb -s
identificador-del-emulador shell . U a vez o e tados, ya se puede acceder a la base de datos
utilizando el comando sqlite3 pasndole la ruta del archivo, para este eje plo sqlite3
/data/data/net.sgoliver.android.bd/databases/DBUsuarios . i todo ha ido ie , de e aparecer
el prompt de QLite sqlite> , lo ue i di a ue ya se puede escribir las consultas SQL necesarias
sobre la base de datos. Es posible comprobar que existe la tabla Usuarios y que se han insertado
los cinco registros de ejemplo. Para ello se har la siguie te o sulta: SELECT * FROM Usuarios; .
Si todo es correcto esta instruccin se debende devolver los cinco usuarios existentes en la tabla.
En la imagen siguiente se muestra todo el proceso descrito (click para ampliar):

Con esto ya se ha comprobado que la base de datos se ha creado correctamente, que se han
insertado todos los registros de ejemplo y que todo funciona segn se espera.

SECCIN 2
En la seccin anterior se vio cmo crear una base de datos para utilizarla desde la aplicacin
Android. En este segundo artculo de la serie se van a describir las posibles alternativas que
proporciona la API de Android a la hora de insertar, actualizar y eliminar registros de la base de
datos SQLite.
La API de SQLite de Android proporciona dos alternativas para realizar operaciones sobre la base
de datos que devuelven resultados (entre ellas la insercin/actualizacin/eliminacin de registros,
pero tambin la creacin de tablas, de ndices, etc).
El primero de ellos, es el mtodo execSQL() de la clase SQLiteDatabase. Este mtodo permite
ejecutar cualquier sentencia SQL sobre la base de datos, siempre que sta no devuelva resultados.
Para ello, simplemente se aportar como parmetro de entrada de este mtodo la cadena de
texto correspondiente con la sentencia SQL. Cuando se crea la base de datos en la parte anterior
ya se vio algn ejemplo de esto para insertar los registros de prueba. Otros ejemplos podran ser
los siguientes:
//Insertar un registro
db.execSQL("INSERT INTO Usuarios (codigo,nombre) VALUES (6,'usuariopru') ");
//Eliminar un registro
db.execSQL("DELETE FROM Usuarios WHERE codigo=6 ");
//Actualizar un registro
db.execSQL("UPDATE Usuarios SET nombre='usunuevo' WHERE codigo=6 ");

La segunda de las alternativas disponibles en la API de Android es utilizar los mtodos


insert(), update() y delete() proporcionados tambin con la clase SQLiteDatabase. Estos mtodos
permiten realizar las tareas de insercin, actualizacin y eliminacin de registros de una forma
algo ms paramtrica que execSQL(), separando tablas, valores y condiciones en parmetros
independientes de estos mtodos.
Se empieza por el mtodo insert() para insertar nuevos registros en la base de datos. Este mtodo
recibe tres parmetros, el primero de ellos ser el nombre de la tabla, el tercero sern los valores
del registro a insertar, y el segundo se obviar por el momento ya que tan slo se hace necesario
en casos muy puntuales (por ejemplo para poder insertar registros completamente vacos), en
cualquier otro caso se pasar con valor null este segundo parmetro.
Los valores a insertar se pasarn como elementos de una coleccin de tipo ContentValues. Esta
coleccin es de tipo diccionario, donde se almacenarn parejas de clave-valor, donde la clave ser
el nombre de cada campo y el valor ser el dato correspondiente a insertar en dicho campo. Vase
un ejemplo:

//Creamos el registro a insertar como objeto ContentValues


ContentValues nuevoRegistro = new ContentValues();
nuevoRegistro.put("codigo", "6");
nuevoRegistro.put("nombre","usuariopru");
//Insertamos el registro en la base de datos
db.insert("Usuarios", null, nuevoRegistro);

Los mtodos update() y delete() se utilizarn de forma muy parecida a sta, con la salvedad de que
recibirn un parmetro adicional con la condicin WHERE de la sentencia SQL. Por ejemplo, para
actualizar el nombre del usuario con un cdigo determinado se har lo siguiente:
//Establecemos los campos-valores a actualizar
ContentValues valores = new ContentValues();
valores.put("nombre","usunuevo");
//Actualizamos el registro en la base de datos
db.update("Usuarios", valores, "codigo=6", null);

Como se puede ver, como tercer parmetro del mtodo update() se pasa directamente la
condicin del UPDATE tal como se hara en la clusula WHERE en una sentencia SQL normal.
El mtodo delete() se utilizara de forma anloga. Por ejemplo para eliminar el registro del usuario
con cdigo determinado se hara lo siguiente:
//Eliminamos el registro del usuario '6'
db.delete("Usuarios", "codigo=6", null);

Como se ve, se vuelve a pasar como primer parmetro el nombre de la tabla y en segundo lugar la
condicin WHERE. Por supuesto, si no se necesita ninguna condicin, se podra dejar como null en
este parmetro (lo que eliminara todos los registros de la tabla).
Un ltimo detalle sobre estos mtodos. Tanto en el caso de execSQL() como en los casos de
update() o delete() se pueden utilizar argumentos dentro de las condiciones de la sentencia SQL.
stos no son ms que partes variables de la sentencia SQL que se aportarn en un array de valores
aparte, con lo que se evitar pasar por la situacin tpica en la que se tiene que construir una
sentencia SQL concatenando cadenas de texto y variables para formar el comando SQL final. Estos
argumentos SQL se indica o el s olo ?, y los valores de dichos argumentos deben pasarse
en el array en el mismo orden que aparecen en la sentencia SQL. As, por ejemplo, se pueden
escribir instrucciones como la siguiente:
//Eliminar un registro con execSQL(), utilizando argumentos
String[] args = newString[]{"usuario1"};
db.execSQL("DELETE FROM Usuarios WHERE nombre=?", args);
//Actualizar dos registros con update(), utilizando argumentos
ContentValues valores = newContentValues();
valores.put("nombre","usunuevo");

String[] args = newString[]{"usuario1", "usuario2"};


db.update("Usuarios", valores, "nombre=? OR nombre=?", args);

Esta forma de pasar a la sentencia SQL determinados datos variables puede ayudar adems a
escribir cdigo ms limpio y evitar posibles errores.
En esta parte se ha continuado con la aplicacin de ejemplo del apartado anterior, a la que he
aadido dos cuadros de texto para poder introducir el cdigo y nombre de un usuario y tres
botones para insertar, actualizar o eliminar dicha informacin.

SECCIN 3
En la parte anterior se vieron todas las opciones disponibles a la hora de insertar, actualizar y
eliminar datos de una base de datos SQLite en Android. En esta seccin se van a describir la ltima
de las tareas importantes de tratamiento de datos que quedan por ver, la seleccin y recuperacin
de datos.
De forma anloga a lo que se vio para las sentencias de modificacin de datos, se van a tener dos
opciones principales para recuperar registros de una base de datos SQLite en Android. La primera
de ellas utilizando directamente un comando de seleccin SQL, y como segunda opcin utilizando
un mtodo especfico donde se parametriza la consulta a la base de datos.
Para la primera opcin se utilizar el mtodo rawQuery() de la clase SQLiteDatabase. Este mtodo
recibe directamente como parmetro un comando SQL completo, donde indicamos los campos a
recuperar y los criterios de seleccin. El resultado de la consulta se obtendr en forma de cursor,
que posteriormente se podr recorrer para procesar los registros recuperados. Sirva la siguiente
consulta a modo de ejemplo:
Cursor c = db.rawQuery(" SELECT codigo,nombre FROM Usuarios WHERE nombre='usu1' ", null);

Como en el caso de los mtodos de modificacin de datos, tambin se puede aadir a este
mtodo una lista de argumentos variables que se hayan indicado en el comando SQL con el
s olo ?, po eje plo as:
String[] args = newString[] {"usu1"};
Cursor c = db.rawQuery(" SELECT codigo,nombre FROM Usuarios WHERE nombre=? ", args);

Ms adelante en esta seccin se vera cmo se puede manipular el objeto Cursor para recuperar
los datos obtenidos.
Como segunda opcin para recuperar datos se puede utilizar el mtodo query() de la clase
SQLiteDatabase. Este mtodo recibe varios parmetros: el nombre de la tabla, un array con los
nombre de campos a recuperar, la clusula WHERE, un array con los argumentos variables
incluidos en el WHERE (si los hay, null en caso contrario), la clusula GROUP BY si existe, la
clusula HAVING si existe, y por ltimo la clusula ORDER BY si existe. Opcionalmente, se puede
incluir un parmetro al final ms indicando el nmero mximo de registros que se quiera que
devuelva la consulta. Vase el ejemplo anterior utilizando el mtodo query():
String[] campos = newString[] {"codigo", "nombre"};
String[] args = newString[] {"usu1"};
Cursor c = db.query("Usuarios", campos, "usuario=?", args, null, null, null);

Como se observa, los resultados se devuelven nuevamente en un objeto Cursor que se debern
recorrer para procesar los datos obtenidos.

Para recorrer y manipular el cursor devuelto por cualquiera de los dos mtodos mencionados se
tienen a disposicin varios mtodos de la clase Cursor, entre los que destacan dos de los
dedicados a recorrer el cursor de forma secuencial y en orden natural:

moveToFirst(): mueve el puntero del cursor al primer registro devuelto.


moveToNext(): mueve el puntero del cursor al siguiente registro devuelto.
Los mtodos moveToFirst() y moveToNext() devuelven TRUE en este de haber realizado el
movimiento correspondiente del puntero sin errores, es decir, siempre que exista un primer
registro o un registro siguiente, respectivamente.
Una vez posicionados en cada registro se puede utilizar cualquiera de los
mtodosgetXXX(ndice_columna) existentes para cada tipo de dato para recuperar el dato de cada
campo del registro actual del cursor. As, si se quiere recuperar por ejemplo la segunda columna
del registro actual, y sta contiene un campo alfanumrico, se har la llamada getString(1) [NOTA:
los ndices comienzan por 0 (cero), por lo que la segunda columna tiene ndice 1], en caso de
contener un dato de tipo real llamaramos a getDouble(1), y de forma anloga para todos los tipos
de datos existentes.
Con todo esto en cuenta, se puede ver cmo se podran recorrer el cursor devuelto por el ejemplo
anterior:
String[] campos = new String[] {"codigo", "nombre"};
String[] args = new String[] {"usu1"};
Cursor c = db.query("Usuarios", campos, "nombre=?", args, null, null, null);
//Nos aseguramos de que existe al menos un registro
if(c.moveToFirst()) {
//Recorremos el cursor hasta que no haya ms registros
do{
String codigo= c.getString(0);
String nombre = c.getString(1);
} while(c.moveToNext());
}

Adems de los mtodos comentados de la clase Cursor existen muchos ms que nos pueden ser
tiles en muchas ocasiones. Por ejemplo, getCount() indicar el nmero total de registros
devueltos en el cursor, getColumnName(i) devuelve el nombre de la columna con ndice i,
moveToPosition(i) mueve el apuntador del cursor al registro con ndice i, etc. Se puede consultar la
lista completa de mtodos disponibles en la clase Cursor en la documentacin oficial de Android.
En este parte se ha seguido ampliando la aplicacin de ejemplo anterior para aadir la posibilidad
de recuperar todos los registros de la tabla Usuarios pulsando un nuevo botn de consulta.

Con esto, se terminan la serie de artculos bsicos dedicados a las tareas de mantenimiento de
datos en aplicaciones Android mediante bases de datos SQLite.

EJEMPLO 2

CDIGO DEL ARCHIVO MainActivity.java


package com.cic.example.androidbd;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity
{
private EditText textBox1;
private EditText textBox2;
String nombre;
String email;
boolean almacenar=false;
AdaptadorBD database=new AdaptadorBD(this);
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textBox1 = (EditText) findViewById (R.id.name);
textBox2 = (EditText) findViewById (R.id.email);
final Button saveBtn = (Button) findViewById (R.id.button1);
saveBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
nombre=textBox1.getText().toString();
email=textBox2.getText().toString();
//SQLiteDatabase db=database.getWritableDatabase();

Toast.makeText(getBaseContext(), "SE PROCEDE A ALMACENAR LOS DATOS " + nombre + " "+ email,
Toast.LENGTH_SHORT).show();
database.abrir();
long id=database.insertarContacto(nombre, email);
database.cerrar();
Toast.makeText(getBaseContext(), "SE HAN ALMACENADO LOS DATOS", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}

CDIGO DEL ARCHIVO AdaptadorBD.java


package com.cic.example.androidbd;
import java.sql.SQLException;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class AdaptadorBD extends SQLiteOpenHelper
{
public static final String KEY_IDFILA="id";
public static final String KEY_NOMBRE="nombre";
public static final String KEY_EMAIL="email";
private static final String TAG="AdaptadorBD";
private static final String NOMBRE_BASEDATOS="MiBD";
private static final String TABLA_BASEDATOS="contactos";
private static final int VERSION_BASEDATOS=1;
private static final String CREAR_BASEDATOS="create table contactos (_id integer primary key autoincrement, nombre text, email
text);";
private SQLiteDatabase db;
public AdaptadorBD(Context context)
{
super(context,NOMBRE_BASEDATOS,null,VERSION_BASEDATOS);
}
@Override
public void onCreate(SQLiteDatabase arg0) {
// TODO Auto-generated method stub
arg0.execSQL(CREAR_BASEDATOS);
System.out.println ("Se crea la base de datos");
}
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
Log.w(TAG, "ACTUALIZANDO BASE DE DATOS VERSION"+arg1+" A "+ arg2 + ", LO QUE DESTRUIR TODOS LOS DATOS
ANTERIORES");
arg0.execSQL("DROP TABLE IF EXISTS contactos");
onCreate(arg0);
}

public AdaptadorBD abrir()


{
db=this.getWritableDatabase();
return this;
}
public void cerrar()
{
this.close();
}
public long insertarContacto(String nombre, String email)
{
ContentValues valoresIniciales=new ContentValues();
valoresIniciales.put(KEY_NOMBRE, nombre);
valoresIniciales.put(KEY_EMAIL, email);
return db.insert(TABLA_BASEDATOS, null, valoresIniciales);
}
public boolean borrarContacto(long idFila)
{
return db.delete(TABLA_BASEDATOS, KEY_IDFILA + "=" + idFila, null)>0;
}
public Cursor obtenerTodosLosContactos()
{
return db.query(TABLA_BASEDATOS, new String[] {KEY_IDFILA, KEY_NOMBRE,KEY_EMAIL}, null, null, null,null,null);
}
public Cursor obtenerContacto(long idFila) throws SQLiteException
{
Cursor mCursor = db.query(true, TABLA_BASEDATOS, new String[]{
KEY_IDFILA, KEY_NOMBRE, KEY_EMAIL }, KEY_IDFILA + "=" + idFila,
null, null, null, null, null);
if (mCursor != null)
{
mCursor.moveToFirst();
}
return mCursor;
}
}

El archivo Activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+ id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="@string/hello_world"
tools:context=".MainActivity" />
<EditText
android:id="@+ id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+ id/textView1"

android:layout_marginTop="31dp"
android:ems="10" >
<requestFocus />
</EditText>
<TextView
android:id="@+ id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+ id/textView1"
android:text="Nombre del usuario" />
<EditText
android:id="@+ id/email"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+ id/name"
android:layout_marginTop="46dp"
android:ems="10" />
<TextView
android:id="@+ id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+ id/name"
android:layout_marginTop="14dp"
android:text="Correo Electrnico" />
<Button
android:id="@+ id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+ id/email"
android:layout_marginTop="24dp"
android:text="GRABAR" />

</RelativeLayout>

El archivo manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cic.example.androidbd"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"

android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.cic.example.androidbd.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

El resultado final del programa antes comentado es de la forma:

EJERCICIO DE ALMACENAMIENTO DE DATOS


Para este caso se realizar el diseo de un pequeo proyecto que parte de la generacin de
diferentes activities para logra posteriormente el enlace con la base de datos de SQLite.

Para este caso se har uso del componente de diseo grfico. Dentro de ella es posible observar
muchas propiedades referentes a la interfaz grfica.

Se procede a reemplazar el ttulo que aparece por omisin al crear la aplicacin, para ello se
selecciona el ttulo correspondiente y se busca dentro de las propiedades del mismo la opcin de
Text, la cual permite modificar el contenido o bien agregar una nueva variable al archivo
Strings.xml. Dicha opcin ya se encuentra direccionada a la varible de XML hello_world, en este
caso, se proceder a crear una nueva variable para este componente, seleccionado el botn de
New String.

Tras lo cual aparece la siguiente ventana

Lo anterior permite agregar esa cadena al archivo Strings.xml, se procede a hacer ms grande el
texto 20sp(medida tipo pixel con cierta proporcin). Para poder centrar el componente se
selecciona la opcin de Gravity.

Se proceder a agregar una etiqueta (TextView) y un componente para permitir que se introduzca
el texto (AutoCompleteTextView).

Se elimina el contenido del texto del TextView, en la opcin Text. Se procede a asignar el texto de
Ttulo al TextView creado. Para poder obtenerla se resumen en la siguiente tabla las variables que
se recomienda que la aplicacin debe de tener:
COMPONENTE
TextView(1)
TextView(2)
TextView(3)
AutoCompleteTextView(1, 2 y 3)

COMPONENTE
Button 1
Button 2

Text
CANCELAR
AGREAGR

Text
Ttulo
Autor
ISBN

Nombre
variable
cancel
add

Nombre variable
title
author
isbn

Text size
20sp
20sp
20sp

Text size

Text style

On Click

20dp
20dp

bold
bold

onAddClick
onCancelClick

Text style
bold
bold
bold

Id

Padding
5sp
5sp
5sp

width
130
130

Se procede a agregar 2 botones a la aplicacin, los cuales sern usados sin identificadores, puesto
que se har uso de un mtodo para verificar su funcionamiento. El cdigo final de esta Activity de
acuerdo al formato de XML es de la forma:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/AddNewBook"
android:textSize="20sp" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView2"
android:layout_below="@+id/textView2"
android:layout_marginTop="15dp"
android:text="@string/title"
android:textSize="20sp"
android:textStyle="bold" />
<AutoCompleteTextView
android:id="@+id/BookTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/textView1"
android:layout_alignBottom="@+id/textView1"
android:layout_alignParentRight="true"
android:ems="10" >
<requestFocus />
</AutoCompleteTextView>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button1"
android:layout_alignBottom="@+id/button1"
android:layout_toRightOf="@+id/button1"
android:onClick="onAddClick"
android:padding="5dp"
android:text="@string/add"
android:textSize="20sp"
android:textStyle="bold"
android:width="130dp" />
<AutoCompleteTextView
android:id="@+id/BookAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/BookTitle"

android:layout_marginTop="54dp"
android:layout_toRightOf="@+id/textView1"
android:ems="10" />
<AutoCompleteTextView
android:id="@+id/BookISBN"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/textView1"
android:ems="10" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView4"
android:layout_below="@+id/BookISBN"
android:layout_marginLeft="22dp"
android:layout_marginTop="55dp"
android:onClick="onCancelClick"
android:padding="5dp"
android:text="@string/cancel"
android:textSize="20sp"
android:textStyle="bold"
android:width="130dp" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/button1"
android:layout_alignLeft="@+id/textView3"
android:padding="5dp"
android:text="@string/isbn"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/BookAuthor"
android:layout_alignParentLeft="true"
android:padding="5dp"
android:text="@string/author"
android:textSize="20sp"
android:textStyle="bold" />
</RelativeLayout>

A continuacin se procede a crear una segunda Activity de o


la Activity principal de la forma:

esults para ser llamada por

El cdigo de esta nueva Activity se muestra a continuacin, no olvidar agregar dos lneas en el
archivo Strings.xml a las que hace alusin el cdigo de esta nueva Activity.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:focusableInTouchMode="false"
android:textSize="25sp"
android:padding="10sp"
android:gravity="center"
android:text="@string/result"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textStyle="bold"
android:focusableInTouchMode="false"
android:textSize="20sp"
android:padding="10sp"
android:gravity="center"
android:text=""
android:id="@+id/resultadoText"
/>
</LinearLayout>

El archivo Strings.xml queda de la forma:


<?xml version="1.0" encoding="utf-8"?>
<resources>
<string
<string
<string
<string
<string
<string
<string
<string
<string

name="app_name">BDLibros</string>
name="action_settings">Settings</string>
name="hello_world">Hello world!</string>
name="AddNewBook">AGREGAR UN NUEVO LIBRO</string>
name="title">TTULO</string>
name="author">AUTOR</string>
name="isbn">ISBN</string>
name="cancel">CANCELAR</string>
name="add">AGREGAR</string>

<string name="result">RESULTADO</string>
<string name="resultadoOk">INSERCIN EXITOSA DEL LIBRO</string>
<string name="cancelOp">OPERACIN CANCELADA</string>
</resources>

Para poder relacionar las Activities se tiene que agregar una entrada del tipo Intent en el archivo
AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cic.example.bdlibros"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"

android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.cic.example.bdlibros.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Result"
android:label="@string/result">
</activity>
</application>
</manifest>

Posteriormente se agrega el archivo Result.java en donde se define a la clase Result.

El contenido de este archivo es el siguiente

public class Result extends Activity


{
@Override
public void onCreate(Bundle savedInstance)
{
super.onCreate (savedInstance);
setContentView (R.layout.results);
TextView resultText = (TextView) findViewById(R.id.resultadoText);
Bundle bundle = getIntent().getExtras();
if (bundle.getString("CANCEL") != null)
{
resultText.setText (getString(R.string.cancelOp));
}
else
{
String bookTitle = bundle.getString ("BookTitle");
String bookAuthor=bundle.getString ("BookAuthor");
String bookISBN = bundle.getString ("BookISBN");
resultText.setText (getString (R.string.resultadoOk)+ " " + bookTitle+ " " +
bookAuthor+ " " +bookISBN);
}
}
}

Posteriormente se modificar el archivo principal de la aplicacin para crear la gestin de las


acciones del usuario sobre la aplicacin.
package com.cic.example.bdlibros;
import
import
import
import
import
import
import

android.os.Bundle;
android.app.Activity;
android.content.ComponentName;
android.content.Intent;
android.view.Menu;
android.view.View;
android.widget.AutoCompleteTextView;

public class MainActivity extends Activity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onAddClick (View
{
AutoCompleteTextView
(R.id.BookTitle);
AutoCompleteTextView
(R.id.BookAuthor);
AutoCompleteTextView

Button)
bookTitle = (AutoCompleteTextView) findViewById
bookAuthor = (AutoCompleteTextView) findViewById
bookISBN = (AutoCompleteTextView) findViewById (R.id.BookISBN);

Intent intent = new Intent();


intent.setClass (this,Result.class);
intent.putExtra ("BookTitle",bookTitle.getText().toString());
intent.putExtra ("BookAuthor",bookAuthor.getText().toString());
intent.putExtra ("BookISBN",bookISBN.getText().toString());
startActivity (intent);
}
public void onCancelClick(View botton)
{

Intent intent=new Intent();


intent.setComponent (new ComponentName(this,Result.class));
intent.putExtra ("CANCEL","CANCEL");
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}

Ejecutar la aplicacin y verificar su funcionamiento.


GUARDANDO DATOS EN SQLite
Se crear una clase para gestionar la base de datos en SQLite que extiende a SQLiteOpenHelper,
que permite gestionar la problemtica de creacin y actualizacin de versiones de SQLite. La base
de datos est almacenada en un archivo. Si la base no existe, se crea, no se requiere de un
administrador de bases de datos para gestionarla. El mtodo Helper ayuda a la gestin de la base
de datos. La primera vez que se manda a llamar a esta clase si no existe el archivo se manda a
llamar al mtodo onCreate, en donde debe de ponerse las lneas para la creacin de la base de
datos, ndices; entre otras cosas.
Se crea pues una nueva clase que contendr a esta clase

El mtodo onUpgrade sirve cuando se requieran tener nuevas actualizaciones de la base de datos
por medio del software, quedando la base de datos anterior sin usar. Si se arranca una versin del
programa con una nueva versin de la base de datos, ltimo parmetro en la llamada al mtodo
super de la clase heredada de SQLiteHelper, se ejecuta este mtodo.
Ahora se unificarn los cdigos de la gestin de la base de datos con el cdigo antes creado sobre
la aplicacin de libros.

package com.cic.example.bdlibros;
import
import
import
import

android.content.Context;
android.database.sqlite.SQLiteDatabase;
android.database.sqlite.SQLiteDatabase.CursorFactory;
android.database.sqlite.SQLiteOpenHelper;

public class DatabaseHelper


{
static final String
static final String
static final String
static final String

extends SQLiteOpenHelper
DATABASE_NAME ="library.db";
TITLE="title";
AUTHOR="author";
ISBN="isbn";

public DatabaseHelper(Context context, String name, CursorFactory factory,


int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL ("CREATE TABLE books (_id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT,
author TEXT, isbn TEXT);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
android.util.Log.w ("books","actualizndo la base de datos, lo cual destruir todos
los datos aneriores");
db.execSQL ("DROP TABLE IF EXISTS books");
onCreate (db);
}
}

Para ello se crea un mtodo en el archivo Result.java el cual se modificar como:

package com.cic.example.bdlibros;
import
import
import
import

android.app.Activity;
android.content.ContentValues;
android.database.sqlite.SQLiteDatabase;
android.os.Bundle;

import android.widget.TextView;
public class Result extends Activity
{
@Override
public void onCreate(Bundle savedInstance)
{
super.onCreate (savedInstance);
setContentView (R.layout.results);
TextView resultText = (TextView) findViewById(R.id.resultadoText);
Bundle bundle = getIntent().getExtras();
if (bundle.getString("CANCEL") != null)
{
resultText.setText (getString(R.string.cancelOp));
}
else
{
String bookTitle = bundle.getString ("BookTitle");
String bookAuthor=bundle.getString ("BookAuthor");
String bookISBN = bundle.getString ("BookISBN");
insertBook(bookTitle,bookAuthor,bookISBN);
resultText.setText (getString (R.string.resultadoOk)+ " " + bookTitle+ " " +
bookAuthor+ " " +bookISBN);
}
}
private void insertBook (String title, String author, String isbn)
{
DatabaseHelper databaseHelper = new DatabaseHelper(this,
DatabaseHelper.DATABASE_NAME, null, 1);
SQLiteDatabase db =databaseHelper.getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put (DatabaseHelper.TITLE,title);
cv.put (DatabaseHelper.AUTHOR,title);
cv.put (DatabaseHelper.ISBN,title);
db.insert ("books",DatabaseHelper.TITLE,cv);
db.close();
}
}

Tras lo anterior se puede ejecutar el programa, llenar los datos y verificar si se ha almacenado la
informacin en el repositorio correspondiente. La siguiente grfica muestra la ejecucin del
programa.

Ahora se verifica a travs de la vista del DDMS incorporado en Eclipse la informacin almacenada
en el sistema de archivos correspondiente.

Este archivo puede ser llevado al sistema del host donde se encuentra ejecutando el emulador o
bien puede entrar al modo de consola del sistema para poder hacer uso de la consola de acceso a
Linux para poder visualizar su contenido.

S-ar putea să vă placă și