Actualizando una base de datos local desde un servidor remoto - Parte III (final)
En la
parte final de este artículo, vamos a crear un mecanismo que permita
descargar la base de datos alojada en el servidor remoto y alojarla
en una ruta local en nuestro smartphone.
Para ello
vamos a utilizar el Framework de desarrollo Titanium Mobile. La
ventaja es que prácticamente el mismo código nos va a servir para
desplegarlo en plataforma Apple o en plataforma Android con un mínimo
o casi ningún cambio.
Estructura
de la aplicación
La
aplicación en Titanium Mobile está compuesta principalmente por dos
archivos:
- app.js que es la aplicación de pruebas del mecanismo de actualización
- updatedb.js que es una biblioteca o librería que contiene el mecanismo de actualización
Para ambas
se necesita declarar el espacio de nombres (namespace) común myapp:
myapp = {}
Otro
aspecto importante es la naturaleza asincrónica de la actualización.
La librería comienza la actualización que en dependencia de la
conexión a Internet que tengamos, el tamaño de la base datos y la
potencia de nuestro smartphone demorará segundos más o menos y nos
notificará cuando este proceso termine.
La
librería updatedb.js
La
librería updatedb.js está compuesta por:
- Una estructura de datos de configuración que especifica datos como la url del servidor Web donde se va a alojar la base de datos, el nombre de la base de datos, el nombre del archivo de configuración, etc.
- Una función updatedb que permite la actualización de la base de datos local a partir de la base de datos remota y un conjunto de funciones auxiliares (helper functions)
Datos
de configuración de la librería
Dato
|
Descripción
|
url
|
URL del servidor Web donde hemos
alojado la base de datos
|
db
|
Nombre de la base de datos
|
cf
|
Nombre del archivo de
configuración que contiene una fecha en formato YYYYMMDD (ejemplo
20130226)
|
timeout
|
Tiempo de respuesta para el
servidor Web que hemos fijado en unos 10,000 milisegundos o 10
segundos por defecto
|
android
|
True indica que vamos a ejecutar
la aplicación en un smartphone Android, False indica que vamos a
ejecutarla en un smartphone de Apple
|
debug
|
En True indica si queremos
visualizar mensajes que nos ayuden a la puesta a punto. Una vez
lista para desplegar en Producción este campo debería ser False
|
debugcb
|
Debug Callback. Llama a esta
función cuando se produce una situación de depuración
|
updatecb
|
Update Callback. Llama a esta
función cuando termina la actualización de la base de datos
|
errorcb
|
Error Callback. Llama a esta
función cuando se produce un error catastrófico durante la
actualización
|
winx
|
Ventana principal de la aplicación
|
olddate
|
Fecha de la configuración local o
última actualización que registramos
|
newdate
|
Fecha de la configuración remota
|
La
función updatedb
Básicamente
la función de actualización de la base de datos:
myapp.dbu.actind =
Titanium.UI.createActivityIndicator({ height:25, width:25 }); // If the application is running in iOS if (!myapp.dbu.android){ // Setting the activity indicator style myapp.dbu.actind.style =
Titanium.UI.iPhone.ActivityIndicatorStyle.BIG; // Adding the indicator to the main window myapp.dbu.winx.add(myapp.dbu.actind); }
Crea un
indicador de actividad para darle al usuario feedback de que está
ocurriendo el proceso de actualización.
if (Titanium.Network.networkType !==
Titanium.Network.NETWORK_NONE){
// Get the remote config file with the date to update
myapp.dbu.getremoteconfig();
}
Si hay
conexión a Internet procesa el archivo de configuración remoto que
está alojado en el servidor Web para verificar si hay alguna
actualización.
var fcf = Ti.Filesystem.getFile(
Ti.Filesystem.applicationDataDirectory,myapp.dbu.cf);
// if there is not a configuration file
// in the application directory if (!fcf.exists()){ // It's the first time we need to update
// the database and no network connection var alertDialog = Titanium.UI.createAlertDialog({ title: 'WARNING!', message: 'You need an internet connection'+
'to update your application data!', buttonNames: ['OK'] }); // Show alert dialog alertDialog.show(); // Close application because
// there is not information or data to process
myapp.dbu.winx.close();
}
Si no hay conexión a Internet busca si hay un archivo de configuración local en nuestro smartphone. Si no existe, es la primera vez que se realiza la actualización por lo que terminamos con un mensaje de error ya que no es posible actualizar nuestra aplicación.
if (myapp.dbu.updatecb != null) { myapp.dbu.updatecb(); }
Si a pesar
de que no hay conexión, ya teníamos una actualización previa,
llama a la función updatecb() para que la aplicación acceda a la
base de datos.
Creando
la aplicación demo
Creamos
una aplicación en Titanium Mobile y añadimos la librería
updatedb.js a la carpeta Android en Recursos. A continuación,
borramos el contenido de app.js y añadimos lo siguiente:
// Background color Titanium.UI.setBackgroundColor('#000'); // Global namespace var myapp = {}; // Application main windows var win1 = Titanium.UI.createWindow({ title:'DemoDB', backgroundColor:'#fff', exitOnClose: true });
Lo primero
establece el color de fondo de la ventana de aplicación a negro.
Luego declaramos el espacio de nombres global y creamos una ventana a
la que pondremos el título ‘DemoDB’ con color de fondo blanco y
que cuando se cierre termine la ejecución de la aplicación.
Luego
escribimos la función que va acceder a nuestros datos una vez que
termine la actualización:
// Function to list database content var showdatabase = function() { // Open database var db = Ti.Database.open('bestres.sqlite3'); // Execute a query to get a recordset var restaurants =
db.execute('select name,area,style from restaurants'); var s = ""; // while there are records in the recordset while (restaurants.isValidRow()){ // Get the fields content s += "NAME= " + restaurants.fieldByName("name") + ",AREA= " + restaurants.fieldByName("area") + ",STYLE= " + restaurants.fieldByName("style") + ";"; // Navigate to the next record restaurants.next(); } // Close the recordset restaurants.close(); // Show the records content alert("DATABASE CONTENT => " + s); }
La función
abre la base de datos local sqlite3 local llamada besares.sqlite3 y
ejecuta una consulta que devuelve el nombre, area y estilo de los
restaurantes almacenados. Luego realiza un bucle mientras se reciban
filas de datos y compone una cadena de caracteres con la información,
cierra la conexión y muestra la cadena de caracteres formada en una
ventana de alerta (popup window).
En este
momento podríamos utilizar el resultado de la consulta para rellenar
una lista o un grid de nuestra aplicación con los datos
actualizados.
Por último
añadimos el siguiente código:
// Including library Ti.include('updatedb.js'); // Configuring database access myapp.dbu.url = 'http://ayalawilson.com/apps/demodb/'; myapp.dbu.db = 'bestres.sqlite3'; myapp.dbu.cf = 'bestrescf'; myapp.dbu.debug = true; myapp.dbu.updatecb = showdatabase; myapp.dbu.winx = win1; // Updating database myapp.dbu.updatedb(); // On resume event show database Ti.App.addEventListener('resume', function() { showdatabase(); }); // Open the application main window win1.open();
Incluimos
la librería updatedb.js y configuramos:
- La url de la carpeta en el servidor Web donde se encuentra la base de datos
- El nombre de la base de datos
- El nombre del archivo de configuración que contiene la fecha de actualización
- Ponemos a debug en true para ver mensajes de depuración
- Indicamos que el updatecb (Update Callback) será la función showdatabase() que hemos creado previamente
- Indicamos que la ventana de la aplicación será win1
A
continuación llamamos a la función que actualiza la base de datos e
indicamos un par de cosas más:
- Añadimos al evento ‘resume’ (cuando pase de estar minimizada a tener el foco de ejecución) ejecute la función showdatabase() para mostrarnos los datos
- Abrimos la ventana principal de la aplicación para comenzar su ejecución
Como
actualizar la base de datos remota en el servidor
- Sustituimos el archivo de la base de datos remota
- Actualizamos el archivo de configuración con la fecha actual
Como se
realiza la actualización local
Los
terminales móviles cuando arranca la aplicación van al servidor
Web e inspeccionan la fecha del archivo de configuración remoto. Si
la fecha remota es mayor que la fecha de configuración local de la
última actualización, se actualiza la base de datos local (borra la
base de datos local y descarga la base de datos remota) en todos los
terminales.
Si no hay conexión a Internet en el momento que arranca la aplicación pueden ocurrir dos cosas:
- Que exista la base de datos local (descargada en otro momento). En ese caso, la aplicación utiliza los datos locales ya descargados
- Que no exista la base de datos local (la aplicación nunca se ha iniciado). En esta caso nos presenta un mensaje de error y termina
Terminales
probados
- Apple iPhone 4S
- Samsung Galaxy SII con Android "Jelly Bean" 4.03
Recomendaciones
finales
Este
escenario de descarga de la base de datos local desde un servidor
remoto funciona muy bien para:
- Aplicaciones que necesitan operar con bases de datos en modo desconectado (offline), lo que permite que un usuario puede consultar la información deseada viajando por el metro o en el campo o en la carretera o en zonas de difícil o ninguna cobertura
- Bases de datos relativamente de pequeño tamaño para no consumir mucho ancho de banda con las descargas
- Bases de datos de solo lectura donde los usuarios solo consumen información, pero no aportan nada (ni comentarios, ni ratings, etc.)
- Actualizaciones poco frecuentes (los mejores restaurantes de una ciudad no cambian todas las semanas)
- La base de datos, al ser el núcleo de la información y no estar embebida en una carpeta de recursos de nuestra aplicación, permite que esta pueda actualizarse si tener que actualizar la aplicación completa
El
código del proyecto
El
proyecto está alojado en Google Code en
http://code.google.com/p/local-database-updates-from-remote-http-server/.
Sois totalmente libres de modificarlo y adaptarlo a vuestro gusto y
necesidades.
6 comentarios:
Gracias por la serie de posts, me parecen geniales y muy útiles!!!
Yo voy a iniciar un proyecto personal y buscaba algo así.
¿Es posible actualizar solo una tabla de la base de datos?
Gracias por leer. Actualizar solo una tabla tendria un enfoque parecido: nos traemos en un fichero plano, XML o JSON, los datos que queremos actualizar de una tabla especifica
Ok. Muchas gracias por la rapidez en responder, lo probaré.
Me genera un error en updateconfig
tambien me marca error en el SQL
hola, tengo una duda esas librerías se podrían instalar en eclipse?
No hace falta instalar nada en Eclipse. El propio IDE de Titanium esta basado en Eclipse, te acostumbraras de inmediato a utilizarlo.
Publicar un comentario