Ejercicios
Última actualización
¿Te fue útil?
Última actualización
¿Te fue útil?
Vamos a leer y escribir en un archivo de texto. La escritura la haremos añadiendo al final del archivo, mientras que la lectura la haremos leyendo línea a línea.
Crear una nueva aplicación llamada "Fichero" cuya única actividad, la principal, mostrará un EditText
cuyo texto será recogido cada vez que se pulse un Button
que habrá debajo. Dicho texto será añadido a un archivo de texto llamado mytextfile.txt
. Para añadir texto a un archivo primero lo abriremos con
openFileOutput(FILENAME,Context.MODE_APPEND))
y después utilizaremos el método append(...)
de OutputStreamWriter
.
¿Cuándo abrimos el archivo? Recordemos que la actividad puede pasar a inactiva en cualquier momento y que puede no volver a recuperarse. ¿Cuándo nos conviene cerrar el archivo?
Debajo del campo de texto y del botón, vamos a añadir un TextEdit
que ocupe el resto de la pantalla. Lo haremos pulsable con el método setClickable(true)
y cada vez que se haga click sobre él, leeremos el archivo línea a línea y lo mostraremos entero.
En la teoría de esta sesión tenemos el esqueleto básico de un DataHelper para trabajar con SQLite. Se trata de un patrón de diseño que nos ayuda a acceder a nuestros datos encapsulando todo el manejo de la base de datos en el DataHelper
.
El DataHelper
utiliza a su vez otro patrón de diseño, el SQLiteOpenHelper
. Éste nos obliga a definir qué ocurre cuando la base de datos todavía no existe y debe ser creada, y qué ocurre si ya existe pero debe ser actualizada porque ha cambiado de versión. Así el SQLiteOpenHelper
que implementemos, en este caso MiOpenHelper
, nos devolverá siempre una base de datos separándonos de la lógica encargada de comprobar si la base de datos existe o no.
Crea una nueva clase llamada DataHelper
y copia el contenido del DataHelper de la teoría. Revisa el contenido de cada uno de sus métodos:
Comprueba el código de la clase interna MiOpenHelper
, en concreto al método onCreate(...)
y onUpgrade
. Idealmente el método onUpgrade
debería portar las tablas de la versión antigua a la versión nueva, copiando todos los datos. En este caso se elimina directamente la tabla que tenemos con la sentencia SQL "DROP TABLE IF EXISTS " + TABLE_NAME
y se vuelve a crear.
En el constructor del DataHelper
revisa como se obtiene el campo db
que acceso de escritura a la base de datos utilizando MiOpenHelper
. ¿Qué más cosas se hacen en este constructor?
¿Cómo funciona el método insert y qué devuelve como retorno?.
¿Qué realiza la función de borrado y qué devuelve como retorno? ¿para qué sirve el segundo y tercer parámetro de la función db.delete
?
Ahora podemos utilizar el DataHelper
para leer y escribir en base de datos de forma transparente desde cualquier actividad.
En el método onCreate
de la actividad principal prueba el borrado, inserción y listado de datos.
Comprueba por línea de comandos que la base de datos está creada. Te serán útiles los siguientes comandos:
Ahora vamos a cambiar en el DataHandler
el nombre de
la segunda columna, en lugar de nombre, se va a llamar nombres.
Ejecutamos la aplicación y comprobamos que sale con una excepción.
Se pide comprobar en el Log cuál ha sido el error. ¿Cómo lo podemos
solucionar?
Pista: según hemos programado el
DataHandler
y siguiendo el patrón de diseño deSQLiteOpenHelper
, podemos arreglar el problema tocando sólo una tecla.
Opcional:
Añade al helper la función para eliminar por nombre de usuario.
Añade al layout un spinner para que se pueda seleccionar qué usuario eliminar, y un botón para eliminarlo. Añade también un campo de texto para la introducción de nuevos usuarios, y un botón de inserción de nuevo usuario.
Vamos a implementar otra forma de acceder a la misma base de datos, siguiento esta vez el patrón de diseño ContentProvider
de Android. Seguiremos trabajando con el proyecto del ejercicio anterior.
Creamos una nueva clase llamada UsuariosProvider
que herede de ContentProvider
. Nos obligará a sobrecargar una serie de métodos abstractos. Antes de implementar la query
vamos a configurar el provider:
Añadimos algunos campos típicos de los content provider:
Vamos a acceder a la misma base de datos que el ejercicio anterior, pero no vamos a hacerlo a través del helper que tuvimos que implementar, sino que vamos a copiar de él el código que nos haga falta. Copia los los campos que definen el nombre de la base de datos, de la tabla, de las columnas, la versión, así como la referencia al contexto y a la base de datos. La sentencia compilada del insert ya no va a hacer falta. Inicializa los valores que haga falta en el constructor. Para inicializar la referencia a la base de datos vamos a utilizar, una vez más, MiOpenHelper
. Podemos copiarlo del helper del ejercicio anterior al UsuariosProvider
.
Implementa de forma apropiada el getType
para devolver un tipo MIME diferente según si se trata de una URI de una fila o de todas las filas. Para ello ayúdate del uriMatcher
.
Implementa el método query
. Simplemente se trata de devolver el cursor que obtenemos al hacer una query a la base de datos SQLite. Algunos de los parámetros que le pasaremos los recibimos como parámetros del método del provider. Los que no tengamos irán con valor null
.
Aunque no tenemos todos los métodos del UsuariosProvider
implementados, podemos probarlo. Para ello debemos registarlo en el AndroidManifest.xml
:
En Main
del ejercicio anterior se insertan una serie de valores con
el helper y se muestran en el campo de texto. Manteniendo este código, vamos a añadir
al campo de texto el resultado obtenido con la query
del UsuariosProvider
para comprobar que tanto el helper como el provider nos devuelven el mismo resultado.
¿Por qué conviene crear proveedores de contenidos?
Porque es la forma estándar que establece Android de acceder a contenidos.
Nos permite publicar los datos de nuestra aplicación para que los utilicen otras aplicaciones.
Nos permite leer y utilizar los datos que otras aplicaciones publican.
Posibilita notificar al ContentResolver
de los cambios ocurridos, por lo que componentes en la pantalla pueden refrescarse de forma automática.
Entre los proveedores de contenidos nativos nos encontramos el Browser
, CallLog
, ContactsContract
, MediaStore
, Settings
, UserDictionary
. En este ejercicio vamos a acceder a los contactos. Para reutilizar la tabla, vamos a copiar el proyecto anterior, ProveedorContenidos
y lo vamos a pegar con nuevo nombre, ProveedoresPropios
. Para cambiar el nombre de la aplicación tenemos que editar el recurso strings.xml
.
Necesitamos permisos para acceder a los contactos. Se añaden en el AndroidManifest.xml
:
Elimina las acciones de los eventos de inserción y borrado.
Cambia la query para que acceda a ContactsContract.Contacts.CONTENT_URI, así como la uri de notificación del cursor.
En el adapter
mapea los mismos campos de texto del anterior ejercicio (Id y Nombre) a las columnas new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME}
.
Para comprobar que funciona correctamente deberás introducir algunos números de teléfono desde la agenda de Android.
Opcional: Una vez que tengas el ID de un contacto, puedes acceder a sus números de teléfono que se encuentran en otra tabla, ContactsContract.Data
y necesitarías otro cursor diferente para recorrerlos.
Una forma mucho más directa de acceder desde una aplicación a los contactos es lanzando la actividad de los contactos nativa de Android.