Aplicación móvil para proporcionar información sensible a la ubicación(contexto) 14 de julio de 2013

Tamaño: px
Comenzar la demostración a partir de la página:

Download "Aplicación móvil para proporcionar información sensible a la ubicación(contexto) 14 de julio de 2013"

Transcripción

1

2 Contenido Resumen... 6 Introducción... 7 Qué es Android?... 7 Entorno de desarrollo Android Descargar la biblioteca JDK de Java Descargar el programa Android SDK Actualización de las APIs con SDK Manager Configurar la dirección de la carpeta SDK en Eclipse Configurar un dispositivo virtual de Android Estructura de un proyecto Android Carpeta /src/ Carpeta /res/ Carpeta /gen/ Carpeta /assets/ Fichero AndroidManifest.xml Componentes de una aplicación Android Activity View Service Content Provider Broadcast Receiver Widget Intent Desarrollo de una aplicación sencilla Bases de datos Bases de datos según la variabilidad de los datos almacenados Bases de datos según el contenido Manejador de base de datos SQLite Instalación del entorno de desarrollo SQLite

3 Ejemplo de desarrollo de bases de datos con SQLite...34 SQLite en Android...36 Mantenimiento de base de datos en SQLite Consultas y recuperación de registros en SQLite Código QR ZXing ("Zebra Crossing") Uso de Zxing en una aplicación Android Desarrollo Planeación Diseño...63 Implementación Prerrequisitos (archivos necesarios) uamdb.db Generación de la aplicación Inserción de las imágenes Decodificador QR Inserción de la base de datos Utilidades Layouts (Interfaces de la aplicación) main.xml qr.xml schedule.xml building.xml...83 floor.xml...83 room.xml sala.xml cubículo.xml laboratorio.xml profesor.xml teacher.xml

4 grupos.xml uea.xml Recursos para los layouts custom_row_horario.xml custom_row_grupo.xml Clases abstractas para los registros de la base de datos Edificio.java Piso.java Sala.java TipoSala.java Profesor.java SalaProfesor.java UEA.java Grupo.java Horario.java Estudiante.java GrupoLista.java Utilidades de las clases GrupoAdapter.java HorarioAdapter.java HorarioSalaAdapter.java Bases de datos DBHelper.java Intents Main.java FrmBuilding.java FrmFloor.java FrmRoomList.java FrmRoom.java FrmProfesor.java

5 FrmTeacherList.java FrmUEA.java FrmGrupos.java FrmSchedule.java FrmQR.java Permisos (AndroidManifest.xml) Resultados Discusión Conclusiones

6 Resumen En este documento se da a conocer la realización de una aplicación móvil sobre la plataforma Android, el cuál manejará información en una base de datos referente a la localización, cubículos, laboratorios, salas, profesores y algunas Unidades de Enseñanza - Aprendizaje que se imparten en la carrera de Licenciatura en Computación en la Universidad Autónoma Metropolitana Unidad Iztapalapa (UAM-I). Mediante la aplicación lo que logra es dar información sensible a la ubicación para los usuarios, mediante la lectura de un código especial QR, implementados en lugares previamente estudiados. Esta información se encuentra almacenado en el dispositivo móvil en una base de datos propia de la aplicación. En el diseño e implementación de la aplicación, se involucraron varias pruebas, las cuales fueron: Pruebas de integración de distintas ventanas en Android Generación e integración de una base de datos Consultas en la base de datos interna por medio de la aplicación Consulta de información almacenada en un código QR por medio de una aplicación Integración de la lectura de códigos QR para ejecutar eventos de consulta de la base de datos de la aplicación final. Realización de una presentación del producto prototipo a los usuarios finales, los cuales opinaron sobre la usabilidad de la aplicación. Dichas pruebas fueron realizadas tomando en cuenta la información referente al Área de Redes y Telecomunicaciones de la Universidad. Como primer versión de la aplicación, se desarrolló la base de información con un programa externo, para luego incorporarlo a la aplicación para su consulta. Debido a factores no controlables al desarrollo, se omitió la manipulación de la base de datos directamente en la aplicación, teniendo que actualizar la información con un sistema externo, para después incorporarlo manualmente por medio del entorno de desarrollo de la aplicación. 6

7 Introducción Qué es Android? Android es un sistema operativo basado en Linux, diseñado principalmente para móviles con pantalla táctil como teléfonos inteligentes o tabletas, inicialmente desarrollados por Android, Inc., que Google respaldó económicamente y más tarde compró en Android fue desvelado en 2007 junto la fundación del Open Handset Alliance: un consorcio de compañías de hardware, software y telecomunicaciones para avanzar en los estándares abiertos de los dispositivos móviles. Tiene una gran comunidad de desarrolladores escribiendo aplicaciones para extender la funcionalidad de los dispositivos. A la fecha, se han sobrepasado las aplicaciones (de las cuales, dos tercios son gratuitas) disponibles para la tienda de aplicaciones oficial de Android: Google Play, sin tener en cuenta aplicaciones de otras tiendas no oficiales para Android, como pueden ser la App Store de Amazon o la tienda de aplicaciones Samsung Apps de Samsung. Google Play es la tienda de aplicaciones en línea administrada por Google, aunque existe la posibilidad de obtener software externamente. Los programas están escritos en el lenguaje de programación Java. No obstante, no es un sistema operativo libre de malware, aunque la mayoría de ello es descargado de sitios de terceros. Entorno de desarrollo Android Para poder realizar una aplicación en Android, requerimos describir los pasos básicos para disponer en nuestra computadora, el entorno y herramientas necesarias. A continuación enumeraremos los pasos necesarios de instalación y configuración, además de proporcionar los enlaces requeridos de las herramientas. 1. Descargar la biblioteca JDK de Java Para empezar a desarrollar aplicaciones en Android, requerimos del JDK de Java, con la versión 6 o superior. Esto es necesario pues parte de la programación de las aplicaciones se realizan en lenguaje Java, y el entorno de desarrollo lo requiere. El enlace para descargar el JDK para Windows es el siguiente: En nuestro caso, descargamos la versión 7u25, pues es la más reciente ofrecida por la página de Oracle 7

8 1. En seguida instalamos el archivo descargado en nuestra computadora. 2. Descargar el programa Android SDK Como últimamente Google ha visto un gran avance en el desarrollo de aplicaciones en Android, siendo un sistema operativo preferido por la comunidad de desarrolladores, se ha dispuesto a entregar un paquete con lo necesario para poder desarrollar estas aplicaciones de la manera más simple posible. Nos dirigimos a la siguiente página para descargar Android SDK: El SDK incluye un set comprensible de herramientas de desarrollo. Este incluye un depurador de errores, bibliotecas, un emulador basado en QEMU, documentación, códigos de ejemplo, y tutoriales 2.

9 Una vez descargado el SDK que se proporciona en una carpeta comprimida, extraemos el contenido a una ubicación deseada. El directorio contiene las siguientes carpetas: eclipse. En él se encuentra un ejecutable que abre el IDE de Eclipse, configurado especialmente para el desarrollo de aplicaciones de Android. SDK. En esta carpeta se encuentra todas las bibliotecas y documentación de Android. SDK Manager. Este ejecutable es un administrador de paquetes necesarios para desarrollar sobre distintas versiones del API de Android. Estas APIs son paquetes con características específicas que son soportadas por las distintas generaciones de dispositivos móviles y tabletas. 3. Actualización de las APIs con SDK Manager Al ejecutar por primera vez el SDK Manager, tendrá como APIs descargadas las versiones más recientes que se tienen registrados en las bases de datos de Google. Desde aquí podemos seleccionar las APIs respectivas para la versión a la cual vamos a desarrollar. Cabe mencionar que actualmente la versión más utilizada es la 4.1 (Jelly Bean), quien acaba de superar recientemente al uso de las versiones 3.0 (Honeycomb) y 4.0 (Ice Cream Sandwich). En este caso, es preferencia del desarrollador o la petición de los directivos la versión en la que se piensa desarrollar la aplicación. Se tiene que considerar en el desarrollo de las aplicaciones, que desde la versión 3.0 en adelante, se cuenta con un soporte de compatibilidad en el desarrollo para dispositivos grandes, es decir, tabletas. 9

10 Ahora bien, si se tiene algo de tiempo libre, se puede descargar todas las APIs disponibles, los cuales ocuparían una capacidad de 6.9 GB. 4. Configurar la dirección de la carpeta SDK en Eclipse Ya descargadas las APIs de Android, debemos de darle a conocer al IDE Eclipse donde se encuentran dichas bibliotecas para que puedan ser usadas en el desarrollo de la aplicación. Para lograr esto se deben de llevar a cabo los siguientes pasos: 1. Abrimos el IDE Eclipse. Este se encuentra dentro de la carpeta./adt-bundlewindows-x86_64/eclipse/, como se muestra en la siguiente imagen: Predeterminadamente, Eclipse nos muestra la siguiente ventana emergente, donde se van a guardar todos nuestros proyectos. El usuario puede seleccionar la ubicación que le dará a sus archivos, pero nosotros dejaremos la dirección que viene por defecto. 2. En la barra de menú, seleccionamos la opción Window/Preferences. 10

11 3. En la ventana emergente "Preferences", seleccionamos la opción Android y presionamos el botón Browse..., para ubicar la carpeta sdk, que también se encuentra en./adt-bundle-windows-x86_ Una vez ubicada la carpeta, presionan el botón Apply y después OK. 11

12 Listo. Ya tenemos configurado el IDE Eclipse para el desarrollo de aplicaciones. 5. Configurar un dispositivo virtual de Android En el momento en el que se requiere probar y corregir errores de las aplicaciones, no se requiere hacerlo necesariamente sobre un dispositivo físico. El SDK cuenta con una herramienta de virtualización del sistema operativo Android, el cuál puede crear los dispositivos virtuales necesarios para llevar a cabo estas tareas. Para crear un dispositivo virtual debemos de llevar a cabo los siguientes pasos: 1. Dentro de Eclipse, seleccionamos de la barra de menú, la opción Window/Android Virtual Device Manager, el cual nos despliega la siguiente ventana: 2. En la etiqueta Android Virtual Devices, presionamos el botón New... para abrir el formulario para crear la nueva máquina virtual. 12

13 3. En el formulario, escribimos el nombre de la máquina virtual, y seleccionamos el tamaño de la pantalla, versión de Android que contendrá el dispositivo virtual, el tipo de CPU con el que cuenta el dispositivo, si existe teclado físico, si se despliegan controles de hardware, como el volumen y control de la interfaz, cuanta memoria RAM tiene soportada, así como el tamaño de pila de la máquina virtual, capacidad de almacenamiento interno y si cuenta con una memoria externa (también virtual), además de algunas opciones más de la emulación. Una vez establecido los parámetros, presionamos el botón aceptar para crear el dispositivo virtual. 4. Para ejecutarlo, simplemente seleccionamos la máquina virtual y presionamos el botón Start..., y en la ventana emergente, presionamos Launch. 13

14 En este caso ejecuté un dispositivo virtual que asemeja ser una tableta. NOTA: En algunas ocasiones, al estar desarrollando nuestras aplicaciones, se puede presentar una dificultad cuando se quiere ejecutar una máquina virtual, mostrándonos un 14

15 mensaje de error en el que se describe que no es posible correr el dispositivo virtual. Para poder corregir el error, tenemos que hacer lo siguiente: 1. Abrir la carpeta en donde se encuentran nuestros códigos desarrollados y nuestro IDE, que en nuestro caso se encuentran en la unidad E: 2. Copiamos la carpeta ".android" 3. Nos dirigimos a la carpeta del usuario 4. Borramos la carpeta ".android" que se encuentra en esta carpeta, y pegamos la que habíamos copiado anteriormente. Con esto se soluciona este problema, y las ejecuciones de los dispositivos virtuales Android se iniciarán sin ningún problema. Estructura de un proyecto Android Para empezar a comprender cómo se construye una aplicación Android vamos a echar un vistazo a la estructura general de un proyecto tipo 3. Cuando creamos un nuevo proyecto Android en Eclipse se genera automáticamente la estructura de carpetas necesaria para poder generar posteriormente la aplicación. Esta 15

16 estructura será común a cualquier aplicación, independientemente de su tamaño y complejidad. En la siguiente imagen vemos los elementos creados inicialmente para un nuevo proyecto Android: En los siguientes apartados describiremos los elementos principales de esta estructura. Carpeta /src/ Contiene todo el código fuente de la aplicación, código de la interfaz gráfica, clases auxiliares, etc. Inicialmente, Eclipse creará por nosotros el código básico de la pantalla (Activity) principal de la aplicación, siempre bajo la estructura del paquete java definido. Carpeta /res/ Contiene todos los ficheros de recursos necesarios para el proyecto: imágenes, vídeos, cadenas de texto, etc. Los diferentes tipos de recursos de deberán distribuir entre las siguientes carpetas: 16

17 Como ejemplo, para un proyecto nuevo Android, se crean los siguientes recursos para la aplicación: Carpeta /gen/ Contiene una serie de elementos de código generados automáticamente al compilar el proyecto. Cada vez que generamos nuestro proyecto, la maquinaria de compilación de Android genera por nosotros una serie de ficheros fuente en java dirigidos al control de los recursos de la aplicación. 17

18 El más importante es el que se puede observar en la imagen, el fichero R.java, y la clase R. Esta clase R contendrá en todo momento una serie de constantes con los ID de todos los recursos de la aplicación incluidos en la carpeta /res/, de forma que podamos acceder fácilmente a estos recursos desde nuestro código a través de este dato. Así, por ejemplo, la constante R.drawable.icon contendrá el ID de la imagen icon.png contenida en la carpeta /res/drawable/. Veamos como ejemplo la clase R creada por defecto para un proyecto nuevo: package net.sgoliver; public final class R { public static final class attr { public static final class drawable { public static final int icon=0x7f020000; public static final class layout { public static final int main=0x7f030000; public static final class string { public static final int app_name=0x7f040001; public static final int hello=0x7f040000; Carpeta /assets/ Contiene todos los demás ficheros auxiliares necesarios para la aplicación (y que se incluirán en su propio paquete), como por ejemplo ficheros de configuración, de datos, etc. La diferencia entre los recursos incluidos en la carpeta /res/raw/ y los incluidos en la carpeta /assets/ es que para los primeros se generará un ID en la clase R y se deberá acceder a ellos con los diferentes métodos de acceso a recursos. Para los segundos sin embargo no se 18

19 generarán ID y se podrá acceder a ellos por su ruta como a cualquier otro fichero del sistema. Usaremos uno u otro según las necesidades de nuestra aplicación. Fichero AndroidManifest.xml Contiene la definición en XML de los aspectos principales de la aplicación, como por ejemplo su identificación (nombre, versión, ícono,...), sus componentes (pantallas, mensajes,...), o los permisos necesarios para su ejecución. Veremos más adelante más detalles de este fichero. En el siguiente apartado veremos los componentes software principales con los que podemos construir una aplicación Android. Componentes de una aplicación Android En el apartado anterior vimos la estructura de un proyecto Android y aprendimos dónde colocar cada uno de los elementos que componen una aplicación, tanto elementos de software como recursos gráficos o de datos. En éste nuevo post vamos a centrarnos específicamente en los primeros, es decir, veremos los distintos tipos de componentes de software con los que podremos construir una aplicación Android. En Java o.net estamos acostumbrados a manejar conceptos como ventana, control, eventos o servicios como los elementos básicos en la construcción de una aplicación. Pues bien, en Android vamos a disponer de esos mismos elementos básicos aunque con un pequeño cambio en la terminología y el enfoque. Repasemos los componentes principales que pueden formar parte de una aplicación Android (Por claridad, y para evitar confusiones al consultar documentación en inglés, intentaré traducir lo menos posible los nombres originales de los componentes). Activity Las actividades (activities) representan el componente principal de la interfaz gráfica de una aplicación Android. Se puede pensar en una actividad como el elemento análogo a una ventana en cualquier otro lenguaje visual. View Los objetos view son los componentes básicos con los que se construye la interfaz gráfica de la aplicación, análogo por ejemplo a los controles de Java o.net. De inicio, Android pone a nuestra disposición una gran cantidad de controles básicos, como cuadros de texto, botones, listas desplegables o imágenes, aunque también existe la posibilidad de extender la funcionalidad de estos controles básicos o crear nuestros propios controles personalizados. 19

20 Service Los servicios son componentes sin interfaz gráfica que se ejecutan en segundo plano. En concepto, son exactamente iguales a los servicios presentes en cualquier otro sistema operativo. Los servicios pueden realizar cualquier tipo de acciones, por ejemplo actualizar datos, lanzar notificaciones, o incluso mostrar elementos visuales (p.ej. activities) si se necesita en algún momento la interacción con del usuario. Content Provider Un content provider es el mecanismo que se ha definido en Android para compartir datos entre aplicaciones. Mediante estos componentes es posible compartir determinados datos de nuestra aplicación sin mostrar detalles sobre su almacenamiento interno, su estructura, o su implementación. De la misma forma, nuestra aplicación podrá acceder a los datos de otra a través de los content provider que se hayan definido. Broadcast Receiver Un broadcast receiver es un componente destinado a detectar y reaccionar ante determinados mensajes o eventos globales generados por el sistema (por ejemplo: Batería baja, SMS recibido, Tarjeta SD insertada,...) o por otras aplicaciones (cualquier aplicación puede generar mensajes (intents, en terminología Android) broadcast, es decir, no dirigidos a una aplicación concreta sino a cualquiera que quiera escucharlo). Widget Los widgets son elementos visuales, normalmente interactivos, que pueden mostrarse en la pantalla principal (home screen) del dispositivo Android y recibir actualizaciones periódicas. Permiten mostrar información de la aplicación al usuario directamente sobre la pantalla principal. Intent Un intent es el elemento básico de comunicación entre los distintos componentes Android que hemos descrito anteriormente. Se pueden entender como los mensajes o peticiones que son enviados entre los distintos componentes de una aplicación o entre distintas aplicaciones. Mediante un intent se puede mostrar una actividad desde cualquier otra, iniciar un servicio, enviar un mensaje broadcast, iniciar otra aplicación, etc. En el siguiente apartado empezaremos ya a ver algo de código, analizando al detalle una aplicación sencilla. Desarrollo de una aplicación sencilla Después de instalar nuestro entorno de desarrollo para Android y comentar la estructura básica de un proyecto y los diferentes componentes software que podemos utilizar ya es hora de empezar a escribir algo de código. 20

21 La aplicación que se realizará es un simple hola mundo, pero con un poco más de características, que dará como resultado un mejor entendimiento del código y el proceso de creación de la aplicación. La aplicación contará con 2 pantallas, por un lado la primer pantalla solicitará un nombre al usuario, y la segunda pantalla se mostrará un mensaje personalizado para el usuario. Para desarrollar esta aplicación debemos de seguir los siguientes pasos: 1. En el entorno de desarrollo, seleccionamos en la barra de menús, File/New/Android Application Proyect. 21

22 2. En la ventana emergente, seleccionamos el nombre de la aplicación, el cual se llamará Hola Usuario, el nombre del proyecto, y el paquete predeterminado en donde se guardará el código fuente. Aquí también seleccionamos el target mínimo requerido, como ejemplo la versión 2.1. También seleccionamos el target máximo al que va dirigido que es en este caso Android en su versión 4.2. Además, podemos seleccionar un tema en específico para darle una consistencia con respecto a la apariencia de la aplicación. Al finalizar de llenar los campos requeridos, seleccionamos la opción Next. 3. En la siguiente ventana, podemos seleccionar o no si queremos agregar un ícono personalizado a nuestra aplicación, además de crear un Activity nuevo. Marcamos las casillas como viene en la siguiente imagen, y presionamos Next. 22

23 4. En la siguiente ventana, nos muestra las opciones acerca de la apariencia general de la aplicación. Dependiendo del mínimo requerido de la versión de Android, aparecerán soportes para distintos tamaños de pantallas, o efectos que aparecieron en versiones más actuales. Presionamos la opción Next. 23

24 5. En la última pantalla del formulario de creación del proyecto, seleccionamos el nombre de la clase principal, así como el nombre del layout principal. Un layout es la interfaz en donde se colocan todos los componentes que se requieren ver en la pantalla. Por medio de los activities podemos dibujarlos en la pantalla del dispositivo, además de agregar los procesos que se requieren cuando se realiza alguna acción en específico, como presionar un botón o demás. Ya para terminar de crear el proyecto, presionamos finalmente el botón Finish. Como ya vimos, esto nos genera la estructura de carpetas del proyecto y todos los ficheros necesarios para un Hola Mundo básico, es decir, una sola pantalla en donde se muestra únicamente un mensaje fijo. Lo primero que vamos a hacer es diseñar la pantalla principal de nuestra aplicación, modificando la que el programa ha generado por defecto. 6. Abrimos el archivo main.xml (HolaUsuario/res/layout/)en donde se encuentra el conjunto de controles que vamos a requerir. En el reemplazamos el código generado por defecto por el siguiente código: 24

25 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content"/> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputtype="text"></edittext> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" </LinearLayout> En este XML se definen los elementos visuales que componen la interfaz de nuestra pantalla principal y se especifican todas sus propiedades. No nos detendremos mucho por ahora en cada detalle, pero expliquemos un poco lo que vemos en el fichero. Lo primero que nos encontramos es un elemento LinearLayout. Los layout son elementos no visibles que determinan cómo se van a distribuir en el espacio los controles que incluyamos en su interior. Los programadores java, y más concretamente de Swing, conocerán este concepto perfectamente. En este caso, un LinearLayout distribuirá los controles uno tras otro y en la orientación que indique su propiedad android:orientation. Dentro del layout hemos incluido 3 controles: una etiqueta (TextView), un cuadro de texto (EditText), y un botón (Button). En todos ellos hemos establecido las siguientes propiedades: android:id. ID del control, con el que podremos identificarlo más tarde en nuestro código. Vemos que el identificador lo escribimos precedido Esto tendrá 25

26 como efecto que al compilarse el proyecto se genere automáticamente una nueva constante en la clase R para dicho control. android:text. Texto del control. En Android, el texto de un control se puede especificar directamente, o bien utilizar alguna de las cadenas de texto definidas en los recursos del proyecto (fichero strings.xml (HolaUsuario/res/values/)), en cuyo caso indicaremos su identificador precedido del <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">hola Usuario</string> <string name="hello_world">hello world!</string> <string name="menu_settings">settings</string> <string name="nombre">escribe tu nombre: </string> <string name="hola">hola </string> </resources> android:layout_height y android:layout_width. Dimensiones del control con respecto al layout que lo contiene. Esta propiedad tomará normalmente los valores wrap_content para indicar que las dimensiones del control se ajustarán al contenido del mismo, o bien fill_parent para indicar que el ancho o el alto del control se ajustará al ancho o alto del layout contenedor respectivamente. 7. Con esto ya tenemos definida la presentación visual de nuestra ventana principal de la aplicación. De igual forma definiremos la interfaz de la segunda pantalla, creando un nuevo fichero llamado frmmensaje.xml, y añadiendo esta vez tan solo una etiqueta (TextView) para mostrar el mensaje personalizado al usuario. Veamos cómo quedaría nuestra segunda pantalla: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/txtmensaje" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text=""></textview> 26

27 </LinearLayout> Una vez definida la interfaz de las pantallas de la aplicación deberemos implementar la lógica de la misma. Como ya hemos comentado, la lógica de la aplicación se definirá en ficheros java independientes. Para la pantalla principal ya tenemos creado un fichero por defecto llamado Main.java. Empecemos por comentar su código por defecto: package uam.pi1.holausuario; import android.os.bundle; import android.app.activity; public class Main extends Activity protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); Como ya vimos en un apartado anterior, las diferentes pantallas de una aplicación Android se definen mediante objetos de tipo Activity. Por tanto, lo primero que encontramos en nuestro fichero java es la definición de una nueva clase HolaUsuario que extiende a Activity. El único método que sobrescribiremos de esta clase será el método OnCreate, llamado cuando se crea por primera vez la actividad. En este método lo único que encontramos en principio, además de la llamada a su implementación en la clase padre, es la llamada al método setcontentview(r.layout.main). Con esta llamada estaremos indicando a Android que debe establecer como interfaz gráfica de esta actividad la definida en el recurso R.layout.main, que no es más que la que hemos especificado en el fichero /res/layout/main.xml. Una vez más vemos la utilidad de las diferentes constantes de recursos creadas automáticamente en la clase R al compilar el proyecto En principio vamos a crear una nueva actividad para la segunda pantalla de la aplicación análoga a ésta primera, para lo que crearemos una nueva clase FrmMensaje que extienda de Activity y que implemente el método oncreate indicando que utilice la interfaz definida en R.layout.frmmensaje. package com.shell.holausuario; import android.os.bundle; 27

28 import android.widget.textview; import android.app.activity; public class FrmMensaje extends Activity public void oncreate (Bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.frmmensaje); Como vemos, el código incluido por defecto en estas clases lo único que hace es generar la interfaz de la actividad. A partir de aquí nosotros tendremos que incluir el resto de la lógica de la aplicación. 9. Empezamos con la actividad principal Main, obteniendo una referencia a los diferentes controles de la interfaz que necesitemos manipular, en nuestro caso sólo el cuadro de texto y el botón. Para ello utilizaremos el método findviewbyid() indicando el ID de cada control, definidos como siempre en la clase R: final EditText txtnombre = (EditText)findViewById(R.id.TxtNombre); final Button btnhola = (Button)findViewById(R.id.BtnHola); 10. Una vez tenemos acceso a los diferentes controles, ya sólo nos queda implementar las acciones a tomar cuando pulsemos el botón de la pantalla. Para ello implementaremos el evento onclick de dicho botón. btnhola.setonclicklistener(new OnClickListener() public void onclick(view arg0) { Intent intent = new Intent(HolaUsuario.this, FrmMensaje.class); Bundle bundle = new Bundle(); bundle.putstring("nombre", txtnombre.gettext().tostring()); intent.putextras(bundle); startactivity(intent); ); Como ya indicamos en el apartado anterior, la comunicación entre los distintos componentes y aplicaciones en Android se realiza mediante intents, por lo que el primer paso será crear un objeto de este tipo. Existen varias variantes del constructor de la clase Intent, cada una de ellas dirigida a unas determinadas acciones, pero en nuestro caso 28

29 particular vamos a utilizar el intent para llamar a una actividad desde otra de la misma aplicación, para lo que pasaremos al constructor una referencia a la propia actividad llamadora (HolaUsuario.this), y la clase de la actividad llamada (FrmMensaje.class). Si quisiéramos tan sólo mostrar una nueva actividad ya tan sólo nos quedaría llamar a startactivity() pasándole como parámetro el intent creado. Pero en nuestro ejemplo queremos también pasarle cierta información a la actividad, concretamente el nombre que introduzca el usuario en el cuadro de texto. Para hacer esto vamos a crear un objeto Bundle, que puede contener una lista de pares clave-valor con toda la información a pasar entre las actividades. En nuestro caso sólo añadiremos un dato de tipo String mediante el método putstring(clave, valor). Tras esto añadiremos la información al intent mediante el método putextras(bundle). 11. Finalizada la actividad principal de la aplicación pasamos ya a la secundaria. Comenzaremos de forma análoga a la anterior, ampliando el método oncreate obteniendo las referencias a los objetos que manipularemos, esta vez sólo la etiqueta de texto. Tras esto viene lo más interesante, debemos recuperar la información pasada desde la actividad principal y asignarla como texto de la etiqueta. Para ello accederemos en primer lugar al intent que ha originado la actividad actual mediante el método getintent() y recuperaremos su información asociada (objeto Bundle) mediante el método getextras(). Hecho esto tan sólo nos queda construir el texto de la etiqueta mediante su método settext(texto) y recuperando el valor de nuestra clave almacenada en el objeto Bundle mediante getstring(clave). package com.shell.holausuario; import android.os.bundle; import android.widget.textview; import android.app.activity; public class FrmMensaje extends Activity public void oncreate (Bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.frmmensaje); TextView txtmensaje = (TextView)findViewById(R.id.TxtMensaje); Bundle bundle = getintent().getextras(); txtmensaje.settext("hola " + bundle.getstring("nombre")); 29

30 Con esto hemos concluido la lógica de las dos pantallas de nuestra aplicación y tan sólo nos queda un paso importante para finalizar nuestro desarrollo. Como ya indicamos en alguna ocasión, toda aplicación Android utiliza un fichero especial en formato XML (AndroidManifest.xml) para definir, entre otras cosas, los diferentes elementos que la componen. Por tanto, todas las actividades de nuestra aplicación deben quedar convenientemente recogidas en este fichero. La actividad principal ya debe aparecer puesto que se creó de forma automática al crear el nuevo proyecto Android, por lo que debemos añadir tan sólo la segunda. Para este ejemplo nos limitaremos a incluir la actividad en el XML, más adelante veremos que opciones adicionales podemos especificar. <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=" package="com.shell.holausuario" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="7" android:targetsdkversion="17" /> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name="com.shell.holausuario.main" 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="com.shell.holausuario.frmmensaje"> </activity> 30

31 </application> </manifest> Si todo se ha desarrollado completamente bien, podemos ver el resultado final ejecutando el programa en nuestro dispositivo virtual. Bases de datos Una base de datos un conjunto de datos pertenecientes a un mismo contexto y almacenados sistemáticamente para su posterior uso. En este sentido, una biblioteca puede considerarse una base de datos compuesta en su mayoría por documentos y textos impresos en papel e indexados para su consulta. Actualmente, y debido al desarrollo tecnológico de campos como la informática y la electrónica, la mayoría de las bases de datos están en formato digital. Existen programas denominados sistemas gestores de bases de datos, abreviado SGBD, que permiten almacenar y posteriormente acceder a los datos de forma rápida y estructurada. Las propiedades de estos SGBD, así como su utilización y administración, se estudian dentro del ámbito de la informática. Las aplicaciones más usuales son para la gestión de empresas e instituciones públicas. También son ampliamente utilizadas en entornos científicos con el objeto de almacenar la información experimental. Las bases de datos pueden clasificarse de varias maneras, de acuerdo al contexto que se esté manejando, la utilidad de las mismas o las necesidades que satisfagan. Bases de datos según la variabilidad de los datos almacenados Bases de datos estáticas.- Son bases de datos de sólo lectura, utilizadas primordialmente para almacenar datos históricos que posteriormente se pueden utilizar para estudiar el 31

32 comportamiento de un conjunto de datos a través del tiempo, realizar proyecciones, tomar decisiones y realizar análisis de datos para inteligencia empresarial. Bases de datos dinámicas.- Éstas son bases de datos donde la información almacenada se modifica con el tiempo, permitiendo operaciones como actualización, borrado y adición de datos, además de las operaciones fundamentales de consulta. Un ejemplo de esto puede ser la base de datos utilizada en un sistema de información de un supermercado, una farmacia, un videoclub o una empresa. Bases de datos según el contenido Bases de datos bibliográficas.- Sólo contienen un subrogante (representante) de la fuente primaria, que permite localizarla. Un registro típico de una base de datos bibliográfica contiene información sobre el autor, fecha de publicación, editorial, título, edición, de una determinada publicación, etc. Puede contener un resumen o extracto de la publicación original, pero nunca el texto completo, porque si no, estaríamos en presencia de una base de datos a texto completo (o de fuentes primarias ver más abajo). Como su nombre lo indica, el contenido son cifras o números. Por ejemplo, una colección de resultados de análisis de laboratorio, entre otras. Bases de datos de texto completo.- Almacenan las fuentes primarias, como por ejemplo, todo el contenido de todas las ediciones de una colección de revistas científicas. Directorios.- Un ejemplo son las guías telefónicas en formato electrónico. Además de la clasificación por la función de las bases de datos, éstas también se pueden clasificar de acuerdo a su modelo de administración de datos. Algunos modelos con frecuencia utilizados en las bases de datos: Bases de datos jerárquicas Base de datos de red Bases de datos transaccionales Bases de datos relacionales Bases de datos multidimensionales Bases de datos orientadas a objetos Bases de datos documentales Bases de datos deductivas Manejador de base de datos SQLite SQLite es un sistema de gestión de bases de datos relacional compatible con ACID, contenida en una relativamente pequeña escrita en C. SQLite es un proyecto de dominio público creado por D. Richard Hipp 5. 32

33 A diferencia de los sistema de gestión de bases de datos cliente-servidor, el motor de SQLite no es un proceso independiente con el que el programa principal se comunica. En lugar de eso, la biblioteca SQLite se enlaza con el programa pasando a ser parte integral del mismo. El programa utiliza la funcionalidad de SQLite a través de llamadas simples a subrutinas y funciones. Esto reduce la latencia en el acceso a la base de datos, debido a que las llamadas a funciones son más eficientes que la comunicación entre procesos. El conjunto de la base de datos (definiciones, tablas, índices, y los propios datos), son guardados como un sólo fichero estándar en la máquina host. Este diseño simple se logra bloqueando todo el fichero de base de datos al principio de cada transacción. La biblioteca implementa la mayor parte del estándar SQL-92, incluyendo transacciones de base de datos atómicas, consistencia de base de datos, aislamiento, y durabilidad, triggers y la mayor parte de las consultas complejas 6. SQLite usa un sistema de tipos inusual. En lugar de asignar un tipo a una columna como en la mayor parte de los sistemas de bases de datos SQL, los tipos se asignan a los valores individuales. Por ejemplo, se puede insertar una cadena de caracteres en una columna de tipo entero (a pesar de que SQLite tratará en primera instancia de convertir la cadena en un entero). Algunos usuarios consideran esto como una innovación que hace que la base de datos sea mucho más útil, sobre todo al ser utilizada desde un lenguaje de scripting de tipos dinámicos. Otros usuarios lo ven como un gran inconveniente, ya que la técnica no es portable a otras bases de datos SQL. SQLite no trataba de transformar los datos al tipo de la columna hasta la versión 3. Varios procesos o hilos pueden acceder a la misma base de datos sin problemas. Varios accesos de lectura pueden ser servidos en paralelo. Un acceso de escritura sólo puede ser servido si no se está sirviendo ningún otro acceso concurrentemente. En caso contrario, el acceso de escritura falla devolviendo un código de error (o puede automáticamente reintentarse hasta que expira un tiempo de expiración configurable). Esta situación de acceso concurrente podría cambiar cuando se está trabajando con tablas temporales. Sin embargo, podría producirse un interbloqueo debido al multihilo. Este punto fue tratado en la versión 3.3.4, desarrollada el 11 de febrero de Existe un programa independiente de nombre SQLite que puede ser utilizado para consultar y gestionar los ficheros de base de datos SQLite. También sirve como ejemplo para la escritura de aplicaciones utilizando la biblioteca SQLite. Instalación del entorno de desarrollo SQLite Para poder administrar una base de datos con SQLite, se debe de descargar el software de la página oficial ( 33

34 Como se requiere desarrollar en Windows 7, nos dirigimos al apartado de Binarios pre compilados de Windows, y seleccionamos la opción sqlite-shell-win32-x zip, el cual contiene el manejador de la base de datos por línea de comandos. Esta versión es compatible con SQLite y anteriores. El archivo de compresión zip tiene almacenado un ejecutable el cual podemos extraer en cualquier directorio de preferencia. Para nuestra comodidad, lo insertamos en la unidad E: (donde tenemos los directorios de desarrollo de la aplicación e interfaces de desarrollo), dentro de la carpeta "SQLite", que creamos para ese propósito. Ejemplo de desarrollo de bases de datos con SQLite Para poder empezar a desarrollar bases de datos por línea de comandos, simplemente ejecutamos la aplicación "sqlite3.exe", el cual nos despliega una ventana de línea de comandos, en el cual se pueden empezar a ejecutar instrucciones SQL. Otra forma de ejecutar el programa, es abriendo una línea de comandos (cmd) y escribiendo la dirección completa en donde se encuentra el ejecutable. También podemos pasar un parámetro al ejecutable, escribiendo la instrucción "sqlite3.exe" seguido por el nombre del archivo que contiene la base de datos SQLite. Si este no existe, uno nuevo es creado 34

35 automáticamente. En el programa "sqlite3", uno puede escribir sentencias SQL (terminando con punto y coma), presiona "Enter" y el comando SQL se ejecutará. Por ejemplo, para crear una nueva base de datos llamada "ex1" con una tabla sencilla "tbl1" se tiene que hacer lo siguiente: Mayormente, SQLite3 solo lee líneas de entrada y pasan a la biblioteca de SQLite para su ejecución, pero si la entrada empieza con un punto ".", entonces esa línea es capturada e interpretada por el mismo programa SQLite. Estos comandos son usados típicamente para cambiar el formato de la salida de las consultas, o para ejecutar sentencias de consultas pre cargadas. Para enlistar los comandos de punto disponibles, se puede ingresar ".help" en cualquier momento. Por ejemplo: 35

36 Para más comandos se puede visitar la página oficial en donde se puede encontrar toda la documentación disponible con respecto a este manejador de bases de datos. SQLite en Android Android incorpora de serie todas las herramientas necesarias para la creación y gestión 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 apartado sobre bases de datos en Android no vamos a entrar en mucho detalle con esta API. Por el momento nos limitaremos a ver el código necesario para crear una base de datos, insertaremos algún dato de prueba, y veremos cómo podemos comprobar que todo funciona correctamente. En Android, la forma típica para crear, actualizar, y conectar con una base de datos SQLite será a través de una clase auxiliar llamada SQLiteOpenHelper, o para ser más exactos, de una clase propia que derive de ella y que debemos personalizar para adaptarnos a las necesidades concretas de nuestra aplicación 7. La clase SQLiteOpenHelper tiene tan sólo un constructor, que normalmente no necesitaremos sobrescribir, y dos métodos abstractos, oncreate() y onupgrade(), que 36

37 deberemos personalizar con el código necesario para crear nuestra base de datos y para actualizar su estructura respectivamente 8. Como ejemplo, nosotros vamos a crear una base de datos muy sencilla llamada BDUsuarios, con una sola tabla llamada Usuarios que contendrá sólo dos campos: nombre e . Para ellos, vamos a crear una clase derivada de SQLiteOpenHelper que llamaremos UsuariosSQLiteHelper, donde sobrescribiremos los métodos oncreate() y onupgrade() para adaptarlos a la estructura de datos indicada: package net.sgoliver.android; import android.content.context; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqlitedatabase.cursorfactory; import 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, CursorFactory factory, int version) { super(contexto, nombre, factory, public void oncreate(sqlitedatabase db) { //Se ejecuta la sentencia SQL de creación de la tabla public void onupgrade(sqlitedatabase db, int versionanterior, int versionnueva) { //NOTA: Por simplicidad del ejemplo aquí utilizamos directamente //la opción de eliminar la tabla anterior y crearla de nuevo //vacía 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 método debería //ser más elaborado. //Se elimina la versión anterior de la tabla db.execsql("drop TABLE IF EXISTS Usuarios"); //Se crea la nueva versión de la tabla db.execsql(sqlcreate); 37

38 Lo primero que hacemos es definir una variable llamado sqlcreate donde almacenamos la sentencia SQL para crear una tabla llamada Usuarios con los campos alfanuméricos nombre e . NOTA: No es objetivo de este tutorial describir la sintaxis del lenguaje SQL ni las particularidades del motor de base de datos SQLite, por lo que no entraré a describir las sentencias SQL utilizadas. Para más información sobre SQLite puedes consultar la documentación oficial o empezar por leer una pequeña introducción que hice en este mismo blog cuando traté el tema de utilizar SQLite desde aplicaciones.net El método oncreate() será ejecutado automáticamente por nuestra clase UsuariosDBHelper cuando sea necesaria la creación de la base de datos, es decir, cuando aún no exista. Las tareas típicas que deben hacerse en este método serán la creación de todas las tablas necesarias y la inserción de los datos iniciales si son necesarios. En nuestro caso, sólo vamos a crear la tabla Usuarios descrita anteriormente. Para la creación de la tabla utilizaremos la sentencia SQL ya definida y la ejecutaremos contra la base de datos utilizando el método más sencillo de los disponibles en la API de SQLite proporcionada por Android, llamado execsql(). Este método se limita a ejecutar directamente el código SQL que le pasemos como parámetro. Por su parte, el método onupgrade() se lanzará automáticamente cuando sea necesaria una actualización de la estructura de la base de datos o una conversión de los datos. Un ejemplo práctico: imaginemos que publicamos una aplicación que utiliza una tabla con los campos usuario e (llamémoslo versión 1 de la base de datos). Más adelante, ampliamos la funcionalidad de nuestra aplicación y necesitamos que la tabla también incluya un campo adicional por ejemplo con la edad del usuario (versión 2 de nuestra base de datos). Pues bien, para que todo funcione correctamente, la primera vez que ejecutemos la versión ampliada de la aplicación necesitaremos modificar la estructura de la tabla Usuarios para añadir el nuevo campo edad. Pues este tipo de cosas son las que se encargará de hacer automáticamente el método onupgrade() cuando intentemos abrir una versión concreta de la base de datos que aún no exista. Para ello, como parámetros recibe la versión actual de la base de datos en el sistema, y la nueva versión a la que se quiere convertir. En función de esta pareja de datos necesitaremos realizar unas acciones u otras. En nuestro caso de ejemplo optamos por la opción más sencilla: borrar la tabla actual y volver a crearla con la nueva estructura, pero como se indica en los comentarios del código, lo habitual será que necesitemos algo más de lógica para convertir la base de datos de una versión a otra y por supuesto para conservar los datos registrados hasta el momento. Una vez definida nuestra clase helper, la apertura de la base de datos desde nuestra aplicación resulta ser algo de lo más sencillo. Lo primero será crear un objeto de la clase 38

39 UsuariosSQLiteHelper al que pasaremos el contexto de la aplicación (en el ejemplo una referencia a la actividad principal), el nombre de la base de datos, un objeto CursorFactory que típicamente no será necesario (en ese caso pasaremos el valor null), y por último la versión de la base de datos que necesitamos. La simple creación de este objeto puede tener varios efectos: Si la base de datos ya existe y su versión actual coincide con la solicitada simplemente se realizará la conexión con ella. Si la base de datos existe pero su versión actual es anterior a la solicitada, se llamará automáticamente al método onupgrade() para convertir la base de datos a la nueva versión y se conectará con la base de datos convertida. Si la base de datos no existe, se llamará automáticamente al método oncreate() para crearla y se conectará con la base de datos creada. Si la base de datos ya existe y su versión actual coincide con la solicitada simplemente se realizará la conexión con ella. Si la base de datos existe pero su versión actual es anterior a la solicitada, se llamará automáticamente al método onupgrade() para convertir la base de datos a la nueva versión y se conectará con la base de datos convertida. Si la base de datos no existe, se llamará automáticamente al método oncreate() para crearla y se conectará con la base de datos creada. package net.sgoliver.android; import android.app.activity; import android.database.sqlite.sqlitedatabase; import android.os.bundle; public class AndroidBaseDatos extends Activity public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); //Abrimos la base de datos 'DBUsuarios' en modo escritura UsuariosSQLiteHelper usdbh = new UsuariosSQLiteHelper(this, "DBUsuarios", null, 1); SQLiteDatabase db = usdbh.getwritabledatabase(); //Si hemos abierto correctamente la base de datos if(db!= null) { 39

40 //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(); Vale, y ahora qué? dónde está la base de datos que acabamos de crear? cómo podemos comprobar que todo ha ido bien y que los registros se han insertado correctamente? Vayamos por partes. En primer lugar veamos dónde se ha creado nuestra base de datos. Todas las bases de datos SQLite creadas por aplicaciones Android se almacenan en la memoria del teléfono en un fichero con el mismo nombre de la base de datos situado en una ruta que sigue el siguiente patrón: /data/data/paquete.java.de.la.aplicacion/databases/nombre_base_datos En el caso de nuestro ejemplo, la base de datos se almacenaría por tanto en la ruta siguiente: /data/data/net.sgoliver.android/databases/dbusuarios Para comprobar esto podemos hacer lo siguiente. Una vez ejecutada por primera vez desde Eclipse la aplicación de ejemplo sobre el emulador de Android (y por supuesto antes de cerrarlo) podemos ir a la perspectiva DDMS (Dalvik Debug Monitor Server) de Eclipse y en la solapa File Explorer podremos acceder al sistema de archivos del emulador, donde podremos buscar la ruta indicada de la base de datos. Podemos ver esto en la siguiente imagen: 40

41 Con esto ya comprobamos al menos que el fichero de nuestra base de datos se ha creado en la ruta correcta. Ya sólo nos queda comprobar que tanto las tablas creadas como los datos insertados también se han incluido correctamente en la base de datos. Para ello podemos recurrir a dos posibles métodos: 1. Transferir la base de datos a nuestro 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 métodos es sencillo. El fichero de la base de datos podemos transferirlo a nuestro PC utilizando el botón de descarga situado en la esquina superior derecha del explorador de archivos (remarcado en rojo en la imagen anterior). Junto a este botón aparecen otros dos para hacer la operación contraria (copiar un fichero local al sistema de archivos del emulador) y para eliminar ficheros del emulador. Una vez descargado el fichero a nuestro sistema local, podemos utilizar cualquier administrador de SQLite para abrir y consultar la base de datos, por ejemplo SQLite Administrator (freeware). El segundo método utiliza una estrategia diferente. En vez de descargar la base de datos a nuestro sistema local, somos nosotros los que accedemos de forma remota al emulador a través de su consola de comandos (shell). Para ello, con el emulador de Android aún abierto debemos abrir una consola de MS-DOS y utilizar la utilidad adb.exe (Android Debug Bridge) situada en la carpeta platform-tools del SDK de Android (en mi caso: c:\android- sdkwindows\platform-tools\). En primer lugar consultaremos los identificadores de todos los emuladores en ejecución mediante el comando adb devices. Esto nos debe devolver una única instancia si sólo tenemos un emulador abierto, que en mi caso particular se llama emulator Tras conocer el identificador de nuestro emulador, vamos a acceder a su shell mediante el comando adb -s identificador-del-emulador shell. Una vez conectados, ya podemos 41

42 acceder a nuestra base de datos utilizando el comando sqlite3 pasándole la ruta del fichero, para nuestro ejemplo sqlite3 /data/data/net.sgoliver.android/ databases/dbusuarios. Si todo ha ido bien, debe aparecernos el prompt de SQLite sqlite>, lo que nos indicará que ya podemos escribir las consultas SQL necesarias sobre nuestra base de datos. Nosotros vamos a comprobar que existe la tabla Usuarios y que se han insertado los cinco registros de ejemplo. Para ello haremos la siguiente consulta: SELECT * FROM Usuarios;. Si todo es correcto esta instrucción debe devolvernos los cinco usuarios existentes en la tabla. En la imagen siguiente se muestra todo el proceso descrito: Con esto ya hemos comprobado que nuestra base de datos se ha creado correctamente, que se han insertado todos los registros de ejemplo y que todo funciona según se espera. En los siguientes apartados comentaremos las distintas posibilidades que tenemos a la hora de manipular los datos de la base de datos (insertar, eliminar y modificar datos) y cómo podemos realizar consultas sobre los mismos, ya que [como siempre] tendremos varias opciones disponibles. Mantenimiento de base de datos en SQLite La API de SQLite de Android proporciona dos alternativas para realizar operaciones sobre la base de datos que no devuelven resultados (entre ellas la inserción/actualización/eliminación de registros, pero también la creación de tablas, de índices, etc). El primero de ellos, que ya comentamos brevemente en el apartado anterior, es el método execsql() de la clase SQLiteDatabase. Este método permite ejecutar cualquier sentencia SQL sobre la base de datos, siempre que ésta no devuelva resultados. Para ello, simplemente aportaremos como parámetro de entrada de este método la cadena de texto correspondiente con la sentencia SQL. Cuando creamos la base de datos en el post anterior ya vimos algún ejemplo de esto para insertar los registros de prueba. Otros ejemplos podrían ser los siguientes: 42

43 //Insertar un registro db.execsql("insert INTO Usuarios (usuario, ) VALUES "); //Eliminar un registro db.execsql("delete FROM Usuarios WHERE usuario='usu1' "); //Actualizar un registro db.execsql("update Usuarios SET WHERE usuario='usu1' "); La segunda de las alternativas disponibles en la API de Android es utilizar los métodos insert(), update() y delete() proporcionados también con la clase SQLiteDatabase. Estos métodos permiten realizar las tareas de inserción, actualización y eliminación de registros de una forma algo más paramétrica que execsql(), separando tablas, valores y condiciones en parámetros independientes de estos métodos. Empecemos por el método insert() para insertar nuevos registros en la base de datos. Este método recibe tres parámetros, el primero de ellos será el nombre de la tabla, el tercero serán los valores del registro a insertar, y el segundo lo obviaremos por el momento ya que tan sólo se hace necesario en casos muy puntuales (por ejemplo para poder insertar registros completamente vacíos), en cualquier otro caso pasaremos con valor NULL este segundo parámetro. Los valores a insertar los pasaremos como elementos de una colección de tipo ContentValues. Esta colección es de tipo diccionario, donde almacenaremos 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. Veamos un ejemplo: //Creamos el registro a insertar como objeto ContentValues ContentValues nuevoregistro = new ContentValues(); nuevoregistro.put("usuario", "usu10"); nuevoregistro.put(" ","usu10@ .com"); //Insertamos el registro en la base de datos db.insert("usuarios", null, nuevoregistro); Los métodos update() y delete() se utilizarán de forma muy parecida a ésta, con la salvedad de que recibirán un parámetro adicional con la condición WHERE de la sentencia SQL. Por ejemplo, para actualizar el del usuario de nombre usu1 haríamos lo siguiente: //Establecemos los campos-valores a actualizar ContentValues valores = new ContentValues(); valores.put(" ","usu1_nuevo@ .com"); 43

44 //Actualizamos el registro en la base de datos db.update("usuarios", valores, "usuario='usu1'"); Como podemos ver, como tercer parámetro del método update() pasamos directamente la condición del UPDATE tal como lo haríamos en la cláusula WHERE en una sentencia SQL normal. El método delete() se utilizaría de forma análoga. Por ejemplo para eliminar el registro del usuario usu2 haríamos lo siguiente: //Eliminamos el registro del usuario 'usu2' db.delete("usuarios", "usuario='usu2'"); Como vemos, volvemos a pasar como primer parámetro el nombre de la tabla y en segundo lugar la condición WHERE. Por supuesto, si no necesitáramos ninguna condición, podríamos dejar como null en este parámetro. Un último detalle sobre estos métodos. Tanto en el caso de execsql() como en los casos de update() o delete() podemos utilizar argumentos dentro de las condiciones de la sentencia SQL. Esto no son más que partes variables de la sentencia SQL que aportaremos en un array de valores aparte, lo que nos evitará pasar por la situación típica en la que tenemos que construir una sentencia SQL concatenando cadenas de texto y variables para formar el comando SQL final. Estos argumentos SQL se indicarán con el símbolo?, y los valores de dichos argumentos deben pasarse en el array en el mismo orden que aparecen en la sentencia SQL. Así, por ejemplo, podemos escribir instrucciones como la siguiente: //Eliminar un registro con execsql(), utilizando argumentos String[] args = new String[]{"usu1"; db.execsql("delete FROM Usuarios WHERE usuario=?", args); //Actualizar dos registros con update(), utilizando argumentos ContentValues valores = new ContentValues(); valores.put(" ","usu1_nuevo@ .com"); String[] args = new String[]{"usu1", "usu2"; db.update("usuarios", valores, "usuario=? OR usuario=?", args); Esta forma de pasar a la sentencia SQL determinados datos variables puede ayudarnos además a escribir código más limpio y evitar posibles errores. En el siguiente apartado veremos cómo consultar la base de datos para recuperar registros según un determinado criterio. Consultas y recuperación de registros en SQLite De forma análoga a lo que vimos para las sentencias de modificación de datos, vamos a tener dos opciones principales para recuperar registros de una base de datos SQLite en Android. 44

45 La primera de ellas utilizando directamente un comando de selección SQL, y como segunda opción utilizando un método específico donde parametrizaremos la consulta a la base de datos. Para la primera opción utilizaremos el método rawquery() de la clase SQLiteDatabase. Este método recibe directamente como parámetro un comando SQL completo, donde indicamos los campos a recuperar y los criterios de selección. El resultado de la consulta lo obtendremos en forma de cursor, que posteriormente podremos recorrer para procesar los registros recuperados. Sirva la siguiente consulta a modo de ejemplo: Cursor c = db.rawquery(" SELECT usuario, FROM Usuarios WHERE usuario='usu1' "); Como en el caso de los métodos de modificación de datos, también podemos añadir a este método una lista de argumentos variables que hayamos indicado en el comando SQL con el símbolo?, por ejemplo así: String[] args = new String[] {"usu1"; Cursor c = db.rawquery(" SELECT usuario, FROM Usuarios WHERE usuario=? ", args); Más adelante en este apartado veremos cómo podemos manipular el objeto Cursor para recuperar los datos obtenidos. Como segunda opción para recuperar datos podemos utilizar el método query() de la clase SQLiteDatabase. Este método recibe varios parámetros: el nombre de la tabla, un array con los nombre de campos a recuperar, la cláusula WHERE, un array con los argumentos variables incluidos en el WHERE (si los hay, null en caso contrario), la cláusula GROUP BY si existe, la cláusula HAVING si existe, y por último la cláusula ORDER BY si existe. Opcionalmente, se puede incluir un parámetro al final más indicando el número máximo de registros que queremos que nos devuelva la consulta. Veamos el mismo ejemplo anterior utilizando el método query(): String[] campos = new String[] {"usuario", " "; String[] args = new String[] {"usu1"; Cursor c = db.query("usuarios", campos, "usuario=?", args, null, null, null); Como vemos, los resultados se devuelven nuevamente en un objeto Cursor que deberemos recorrer para procesar los datos obtenidos. 45

46 Para recorrer y manipular el cursor devuelto por cualquiera de los dos métodos mencionados tenemos a nuestra disposición varios métodos de la clase Cursor, entre los que destacamos 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 métodos movetofirst() y movetonext() devuelven TRUE en caso 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 podremos utilizar cualquiera de los métodos getxxx(índice_columna) existentes para cada tipo de dato para recuperar el dato de cada campo del registro actual del cursor. Así, si queremos recuperar por ejemplo la segunda columna del registro actual, y ésta contiene un campo alfanumérico, haremos la llamada getstring(1) [NOTA: los índices comienzan por 0, por lo que la segunda columna tiene índice 1], en caso de contener un dato de tipo real llamaríamos a getdouble(1), y de forma análoga para todos los tipos de datos existentes. Con todo esto en cuenta, veamos cómo podríamos recorrer el cursor devuelto por el ejemplo anterior: String[] campos = new String[] {"usuario", " "; String[] args = new String[] {"usu1"; Cursor c = db.query("usuarios", campos, "usuario=?", args, null, null, null); //Nos aseguramos de que existe al menos un registro if (c.movetofirst()) { //Recorremos el cursor hasta que no haya más registros do { String usuario = c.getstring(0); String = c.getstring(1); while(c.movetonext()); Además de los métodos comentados de la clase Cursor existen muchos más que nos pueden ser útiles en muchas ocasiones. Por ejemplo, getcount() te dirá el número total de registros devueltos en el cursor, getcolumnname(i) devuelve el nombre de la columna con índice i, movetoposition(i) mueve el puntero del cursor al registro con índice i, etc. Podéis consultar la lista completa de métodos disponibles en la clase Cursor en la documentación oficial de Android. Código QR Un código QR (quick response code o código de respuesta rápida) es un módulo útil para almacenar información en una matriz de puntos o un código de barras bidimensional creado 46

47 por la compañía japonesa Denso Wave, subsidiaria de Toyota, en Se caracteriza por los tres cuadrados que se encuentran en las esquinas y que permiten detectar la posición del código al lector. La sigla «QR» se deriva de la frase inglesa Quick Response (Respuesta Rápida en español), pues los creadores (Joaco Retes,Euge Damm y E.Pared) aspiran a que el código permita que su contenido se lea a alta velocidad. Los códigos QR son muy comunes en Japón y de hecho son el código bidimensional más popular en ese país 9. Un detalle importante sobre el código QR es que, a diferencia de otros formatos de códigos de barras bidimensionales como el BIDI, su código es abierto y sus derechos de patente (propiedad de Denso Wave) no son ejercidos. ZXing ("Zebra Crossing") ZXing (pronunciado "zebra crossing"), es una biblioteca de procesamiento de imágenes de barras 1D-2D de software libre multi-formato, implementado en Java, con presencia en otros lenguajes. Se encuentra enfocado en el uso en cámaras de dispositivos móviles para escanear y decodificar códigos de barras en el dispositivo, sin comunicación con algún servidor. Sin embargo, el proyecto puede ser utilizado para codificar y decodificar graficas de barras tanto en computadoras de escritorio y servidores. Este soporta los siguientes formatos 10 : UPC-A and UPC-E EAN-8 and EAN-13 Code 39 Code 93 Code 128 ITF Codabar RSS-14 (Todas las variantes) RSS Expanded (muchas variantes) QR Code Data Matrix Aztec (calidad "beta") PDF 417 (calidad "alfa") Esta biblioteca está dividida en muchos componentes que están soportadas activamente: core: LA biblioteca de decodificación de imagen y codigo de prueba. javase: Código de cliente especifico J2SE. zxingorg: La fuente detrás de zxing.org/w. zxing.appspot.com: LA fuente detrás del generador de código de barras en base web. android: Cliente Android, llamado Barcode Scanner. 47

48 androidtest: Aplicación de pruebas de Android. android-integration: Soporta la integración con Barcode Scanner vía Intent. Uso de Zxing en una aplicación Android Como ejemplo de utilización de la tecnología de lectura de códigos QR, realizaremos una pequeña aplicación que nos muestre la información que recupera la lectura de estos códigos. En esta aplicación, pondremos un botón de inicio de escaneo, para que se despliegue el uso de la cámara de escaneo, y cuando reconozca un código QR, la aplicación mostrará el mensaje que se encuentra en dicho QR 11. Para ello requerimos realizar los siguientes pasos: 1. En el dispositivo en donde se van a hacer las pruebas, requerimos instalar la aplicación "Barcode Scanner", que se encuentra en la tienda de aplicaciones de Android. 2. Requerimos de un archivo JAR pre-construido, que se encuentra en los recursos compilados del repositorio de liberación Maven, donde se encuentran los archivos compilados más recientes 12. ( 48

49 3. En nuestro entorno de desarrollo Android ADT, creamos un nuevo proyecto de aplicación Android. 4. Escribimos el nombre de la aplicación, nombre del proyecto y nombre del paquete que contendrá nuestros archivos de desarrollo; así como también seleccionar la versión del dispositivo a la cual va dirigida la aplicación. En este caso seleccionamos como requerimiento mínimo la versión de API 7, correspondiente a la versión 2.1 de Android (Eclair). 49

50 5. En la siguiente pantalla, seleccionamos estas opciones y presionamos siguiente. 6. Seleccionamos una imagen que represente el icono de la aplicación. En nuestro caso encontramos esta imagen que representa de algún modo el objetivo de la aplicación. 50

51 7. En la siguiente pantalla, seleccionamos una actividad en blanco, ya que es la más sencilla de manipular. 8. En la última pantalla, escribimos el nombre del Actvity y el nombre del Layout de este modo: 51

52 9. Una vez creado el proyecto, seleccionamos con el botón secundario la carpeta del proyecto y seleccionamos la opción Build Path/Configure Build Path 10. En "Java Build Path", en la etiqueta "Libraries", presionamos la opción "Add Externals JARs ". 11. Buscamos y seleccionamos el archivo core-2.2.jar que descargamos anteriormente. Seleccionamos la opción OK. 52

53 12. Ya que tenemos las bibliotecas necesarias, pasaremos a generar las interfaces que requerimos en la aplicación. Primero requerimos modificar el archivo "strings.xml", que contendrá las cadenas necesarias para presentar en la aplicación, la cual tendrá el siguiente código: <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">decodificador QR</string> <string name="action_settings">settings</string> <string name="btnscan">iniciar Escaneo</string> <string name="frmmensaje">mensaje:</string> </resources> 53

54 En este archivo, agregamos las cadenas "btnscan" y "frmmensaje", las cuales requeriremos para las interfaces de la aplicación. 13. Ahora abrimos el archivo main.xml, y escribimos el código correspondiente: <RelativeLayout xmlns:android=" xmlns: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=".main" > <Button android:id="@+id/btnscan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:layout_margintop="50dp" android:text="@string/btnscan" /> </RelativeLayout> 54

55 En la interfaz, agregamos un botón con identificador "btnscan", el cual se ubica en el centro de la pantalla, a 50dp de la parte superior de toda la interfaz. 14. Como siguiente paso, creamos en la misma carpeta el archivo mensaje.xml, el cual contendrá el siguiente código: 55

56 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:layout_margintop="50dp" android:textappearance="?android:attr/textappearancelarge" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_alignparentright="true" 56

57 android:layout_margintop="20dp" android:gravity="center" /> </RelativeLayout> En esta interfaz, agregamos un título que muestra el contenido "Mensaje", además de un cuadro de texto con identificador "mensaje", el cual recibirá el contenido de la lectura de un código QR. 15. Una vez realizado esto, tendremos que realizar los procedimientos necesarios para los objetos de nuestras pantallas. Para esto, primero procedemos a crear una nueva clase llamada FrmMensaje.java: 57

58 16. Ahora modificamos el archivo Main.java, el cual contendrá el siguiente código: package uam.pi2.decodificadorqr; import android.os.bundle; import android.app.activity; import android.content.intent; import android.view.gravity; import android.view.view; import android.view.view.onclicklistener; import android.widget.button; import android.widget.toast; public class Main extends Activity protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); 58

59 final Button scan = (Button)findViewById(R.id.btnScan); scan.setonclicklistener(new OnClickListener() public void onclick(view v) { Intent intent = new Intent("com.google.zxing.client.android.SCAN"); intent.putextra("scan_mode", "QR_VALUE"); startactivityforresult(intent, 0); ); public void onactivityresult(int requestcode, int resultcode, Intent intent) { if (requestcode == 0) { if (resultcode == RESULT_OK) { Intent frmmensaje = new Intent(this, FrmMensaje.class); Bundle bundle = new Bundle(); bundle.putstring("mensaje", intent.getstringextra("scan_result")); frmmensaje.putextras(bundle); startactivity(frmmensaje); else if (resultcode == RESULT_CANCELED) { Toast toast = Toast.makeText(this, "Escaneo de código cancelado", Toast.LENGTH_SHORT); toast.setgravity(gravity.top, 25, 400); toast.show(); 17. Como siguiente paso, modificaremos el archivo FrmMensaje.java, agregando el siguiente código: package uam.pi2.decodificadorqr; import android.app.activity; import android.os.bundle; import android.widget.textview; public class FrmMensaje extends Activity public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); 59

60 setcontentview(r.layout.mensaje); TextView txtmensaje = (TextView)findViewById(R.id.mensaje); Bundle bundle = getintent().getextras(); txtmensaje.settext(bundle.getstring("mensaje")); 18. Por último paso, abrimos el archivo AndroidManifest.xml, y agregamos el siguiente código para otorgarle a la aplicación los permisos necesarios para abrir las interfaces y ejecutar los procesos requeridos por la misma. <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=" package="uam.pi2.decodificadorqr" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="7" android:targetsdkversion="17" /> <uses-permission android:name="android.permission.camera" /> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity 60

61 android:name="uam.pi2.decodificadorqr.main" > <intent-filter> <action android:name="android.intent.action.main" /> /> <category android:name="android.intent.category.launcher" </intent-filter> </activity> <activity android:name="uam.pi2.decodificadorqr.frmmensaje"> </activity> </application> </manifest> Habiendo realizado todos estos pasos, solo se requiere realizar las pruebas pertinentes en el dispositivo. 61

62 Desarrollo Planeación En este proyecto se planteó llevar a cabo la realización de una aplicación móvil, el cual permitirá al usuario obtener información sensible a la ubicación tanto por medio de la lectura de códigos especiales QR, como por la navegación dentro de la misma aplicación en las diferentes interfaces. Esta aplicación debería cumplir con las siguientes características: Ser intuitiva: Tanto la navegación como la obtención de la información debe ser clara. Ligera: La instalación y ejecución de la aplicación no repercute en la comodidad de manipulación por parte del usuario. Centralizada: Muestra la información requerida al momento. Actualizable: La información podría ser manipulada para mantenerse al día con respecto a la realidad, dando cabida la posibilidad de tener distintas versiones de la aplicación, mejorándose. La información sería almacenada en una base de datos, la cual puede ser manipulada en el exterior, para otorgar al usuario la posibilidad de actualizar la información de la aplicación por medio de una conexión a un servidor. 62

63 Diseño En un primer acercamiento con los miembros del equipo, así como de los asesores, se realizó una investigación sobre las tecnologías requeridas para el desarrollo del proyecto, así como el alcance que se piensa obtener en la primera versión de la aplicación. Se acordó realizar la aplicación con el objetivo de ejecutarse sobre una tableta, por la comodidad de poder mostrar la suficiente información necesaria en un espacio suficiente. La conexión de la aplicación con la base de datos no se llevó a cabo debido al tiempo de desarrollo, pero se tomo la decisión de realizar la base de datos de la aplicación con una herramienta externa (SQLite) y después agregarla a la aplicación para su posterior consulta. El sistema operativo elegido por el equipo fue Android, ya que cuenta con una gran biblioteca de desarrollo que nos sirvió en el desarrollo, además de la compatibilidad de poder instalar el entorno de desarrollo en las computadoras en las que se realizó la programación de la aplicación. Ya que se eligió el SO Android, implicó que la base de datos por programar tendría que ser desarrollado en SQLite3, ya que dicho manejador de base de datos se encuentra añadido por defecto dentro de cualquier dispositivo Android, por tener la característica de ser muy ligera y no requerir demasiadas peticiones de ejecución del procesador, ahorrando la batería del dispositivo. 63

64 Como el entorno de desarrollo en Android se basa en parte por el lenguaje Java, requerimos de instalar la biblioteca de desarrollo JAVA JDK. Para la tecnología de lectura de códigos QR, el equipo investigó una biblioteca de software libre llamado ZXing (pronunciado "Zebra Crossing"), que es una biblioteca de procesamiento de imágenes de barras 1D-2D de software libre multiformato, implementado en Java, con presencia en otros lenguajes. Se encuentra enfocado en el uso en cámaras de dispositivos móviles para escanear y decodificar códigos de barras en el dispositivo, sin comunicación con algún servidor, dándole portabilidad a la aplicación de la cual requiera esta tecnología. Cabe mencionar que el proyecto puede ser utilizado para codificar y decodificar gráficas de barras en computadoras de escritorio y en servidores. Una vez entendido el desarrollo de aplicaciones en Android con las tecnologías pertinentes, el equipo de desarrollo se dio a la tarea de analizar la información que podría ser interesante mostrar con la aplicación. Se pensó en mostrar información relevante del área de investigación de los asesores (Área de Redes y Telecomunicaciones). Para esto se analizaron las siguientes propuestas de información que nos fueron útiles: 1. Ubicación de la oficina de un profesor. 2. Salón asignado para un grupo de determinada Unidad de Enseñanza-Aprendizaje (UEA). 3. Información de determinado piso de un edificio. 4. Encargado de un laboratorio. 5. Grupos abiertos de determinada UEA. 6. Horario de clases de un estudiante. 7. Salas que se encuentran en un edificio. 8. Profesores que se encuentran en un cubículo. 9. UEAs que se imparten en un salón. 10. Oficinas de determinada área de concentración. El equipo estableció los datos que podrían ser de utilidad en la base de datos, generando el modelo de entidad - relación de la misma. Después se generó el código necesario para la creación de la base de datos y los registros de ejemplo, que fueron tomados haciendo una investigación de campo en las instalaciones de la universidad, tomando la información real que era relevante para el proyecto. Esta información se tomo en la mayoría en el Área de Redes y Telecomunicaciones de la universidad, en la que se obtuvieron datos sobre: Profesores Aulas Laboratorios Oficinas 64

65 Unidades de Enseñanza-Aprendizaje en las que el equipo de desarrollo se encontraban cursando, para agregarlos a los horarios de la aplicación. Como siguiente tarea, se revisó el tema con respecto a la información que contendrían los códigos QR que se piensan usar para la consulta de la información en la aplicación a desarrollar, generando unos diagramas en donde los participantes pensaron la forma en la que se podría solucionar dicha problemática 13. Una vez establecido el contenido de los códigos QR, accedimos a una herramienta de desarrollo de códigos QR gratuito en línea, en donde se generaron algunos ejemplos que se pudieran requerir. Después de generar los códigos, se empezó a desarrollar un diseño del esqueleto de la aplicación. Se abordaron temas como el diagrama de navegación y pantallas. 65

66 66

67 Implementación Ya teniendo todo el diseño en cuenta, el equipo se dispuso a desarrollar la aplicación, llevando el desarrollo en el siguiente orden: Prerrequisitos (archivos necesarios) Se tomaron fotografías en la unidad, que nos servirían en la apariencia de la aplicación, dando un ambiente más amigable al usuario. También se descargó la biblioteca de lectura de códigos QR ZXing, de la página oficial. Además, se desarrolló la base de datos con respecto a los requerimientos y al diseño antes establecidos con el entorno de desarrollo por línea de comandos SQLite, así como algunas consultas en código SQL, para la utilización en la aplicación, generando el archivo uamdb.db, que se ingresaría más adelante a los archivos requeridos dentro de la aplicación. 67

68 uamdb.db /* Creacion de las tablas */ CREATE TABLE edificio ( _id INTEGER PRIMARY KEY AUTOINCREMENT, letra TEXT NOT NULL, descripcion TEXT ); CREATE TABLE piso ( _id INTEGER PRIMARY KEY AUTOINCREMENT, numpiso INTEGER NOT NULL, descripcion TEXT, idedificio INTEGER, FOREIGN KEY (idedificio) REFERENCES edificio (_id) ); CREATE TABLE tiposala ( _id INTEGER PRIMARY KEY AUTOINCREMENT, tipo TEXT NOT NULL ); CREATE TABLE sala ( _id INTEGER PRIMARY KEY, numsala INTEGER NOT NULL, descripcion TEXT, idpiso INTEGER, idtiposala INTEGER, FOREIGN KEY (idpiso) REFERENCES piso (_id), FOREIGN KEY (idtiposala) REFERENCES tiposala (_id) ); CREATE TABLE profesor ( _id INTEGER PRIMARY KEY AUTOINCREMENT, nombre TEXT NOT NULL, apellidos TEXT NOT NULL, TEXT NOT NULL, descripcion TEXT ); CREATE TABLE salaprofesor ( _id INTEGER PRIMARY KEY AUTOINCREMENT, idprofesor INTEGER, idsala INTEGER, 68

69 ); relacion TEXT NOT NULL, FOREIGN KEY (idprofesor) REFERENCES profesor (_id), FOREIGN KEY (idsala) REFERENCES sala (_id) CREATE TABLE uea ( _id INTEGER PRIMARY KEY, nombre TEXT NOT NULL ); CREATE TABLE grupo ( _id INTEGER PRIMARY KEY AUTOINCREMENT, grupo TEXT NOT NULL, iduea INTEGER, idprofesor INTEGER, FOREIGN KEY (iduea) REFERENCES uea (_id), FOREIGN KEY (idprofesor) REFERENCES profesor (_id) ); CREATE TABLE horario ( _id INTEGER PRIMARY KEY AUTOINCREMENT, idsala INTEGER, idgrupo INTEGER, inicio CURRENT_TIME NOT NULL, --HH:MM:SS fin CURRENT_TIME NOT NULL, dia TEXT NOT NULL, FOREIGN KEY (idsala) REFERENCES sala (_id), FOREIGN KEY (idgrupo) REFERENCES grupo (_id) ); CREATE TABLE estudiante ( _id INTEGER PRIMARY KEY AUTOINCREMENT, idgrupo INTEGER NOT NULL, FOREIGN KEY (idgrupo) REFERENCES grupo (_id) ); /* Inserción de los registros de ejemplo */ INSERT INTO edificio (letra, descripcion) VALUES ('B','Aulas, Fuego Nuevo, Coordinacion de Sistemas Escolares'), ('C','Aulas, Auditorios, Salas de audiovisuales'), ('D','Aulas, Oficinas del CELEX, Proteccion Civil'), ('E','Aulas, Auitorios'), ('H','Division de Ciencias Sociales y Humanidades'), ('T','Division de Ciencias Basicas e Ingenieria'), ('AT','Division de Ciencias Basicas e Ingenieria') ; 69

70 INSERT INTO uea (_id, nombre) VALUES ( , 'Introduccion a la Programacion en Administracion'), ( , 'Proyecto de Investigacion II'), ( , 'Redes de Telecomunicaciones'), ( , 'Administracion General') ; INSERT INTO profesor (nombre, apellidos, , descripcion) VALUES ('Oscar', 'Avila Mejia', 'spminds@yahoo.com.mx', 'Profesor del Departamento de Ingenieria Electrica'), ('Reyna Carolina', 'Medina Ramirez', 'cmed@xanum.uam.mx', 'Jefe del Area de Redes y Telecomunicaciones'), ('Antonio', 'Barba Alvarez', 'abal@xanum.uam.mx', 'Profesor del Departamento de Economia'), ('Jose Luis', 'Quiroz Fabian', 'jlqf@gxanum.uam.mx', 'Profesor del Area de Computacion y Sistemas'), ('Miguel', 'Lopez Guerrero', 'milo@xanum.uam.mx', 'Coordinador de la carrera de Ingenieria Electronica'), ('Ricardo', 'Marcelin Jimenez', 'calu@xanum.uam.mx', 'Profesor del Departamento de ingenieria Electrica') ; INSERT INTO tiposala (tipo) VALUES ('Cubiculo'), ('Aula'), ('Oficina'), ('Laboratorio'), ('Sala de conferencias'), ('Auditorio') ; INSERT INTO piso (idedificio, numpiso, descripcion) VALUES ((SELECT e._id FROM edificio e WHERE e.letra = 'T'), 3, 'Area de Redes y Telecomunicaciones, Cubiculos de profesores'), ((SELECT e._id FROM edificio e WHERE e.letra = 'B'), 0, 'Coordinacion de Sistemas Escolares, Teatro del Fuego Nuevo'), ((SELECT e._id FROM edificio e WHERE e.letra = 'B'), 1, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'B'), 2, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'B'), 3, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'C'), 0, 'Auditorios OMECOATECALLI y CECOATECALLI, Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'C'), 1, 'Aulas'), 70

71 ; ((SELECT e._id FROM edificio e WHERE e.letra = 'C'), 2, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'D'), 0, 'Prestamo de equipo, Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'D'), 1, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'D'), 2, 'Aulas, CELEX'), ((SELECT e._id FROM edificio e WHERE e.letra = 'E'), 0, 'Aulas, Auditorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'E'), 1, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'E'), 2, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'E'), 3, 'Aulas'), ((SELECT e._id FROM edificio e WHERE e.letra = 'T'), 0, 'Laboratorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'T'), 1, 'Area de Computacion, Laboratorios, Cubiculos de profesores'), ((SELECT e._id FROM edificio e WHERE e.letra = 'T'), 2, 'Laboratorios, Cubiculos de profesores'), ((SELECT e._id FROM edificio e WHERE e.letra = 'AT'), 0, 'Salas de Conferencia, Laboratorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'AT'), 1, 'Laboratorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'AT'), 2, 'Cubiculos de profesores, Laboratorios'), ((SELECT e._id FROM edificio e WHERE e.letra = 'AT'), 3, 'Cubiculos de profesores'), ((SELECT e._id FROM edificio e WHERE e.letra = 'H'), 0, 'Cubiculos de profesores') INSERT INTO grupo (grupo, iduea, idprofesor) VALUES ('CL08', , (SELECT p._id FROM profesor p WHERE p.apellidos = 'Medina Ramirez' )), ('CK51', , (SELECT p._id FROM profesor p WHERE p.apellidos = 'Avila Mejia' )), ('HA03', , (SELECT p._id FROM profesor p WHERE p.apellidos = 'Barba Alvarez' )), ('CE01', , (SELECT p._id FROM profesor p WHERE p.apellidos = 'Quiroz Fabian' )) ; INSERT INTO sala (numsala, descripcion, idpiso, idtiposala) VALUES (9, 'Cubiculo del Area de Redes y Telecomunicaciones', 71

72 (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'T' AND p.numpiso = 3), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Cubiculo')), (15, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'C' AND p.numpiso = 2), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Aula')), (5, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'D' AND p.numpiso = 1), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Aula')), (7, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'D' AND p.numpiso = 1), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Aula')), (5, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'E' AND p.numpiso = 2), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Aula')), (15, 'Salon de clases', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'E' AND p.numpiso = 2), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Aula')), (47, 'Cubiculo del Area de Computacion y Sistemas', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'T' AND p.numpiso = 1), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Cubiculo')), (69, 'Cubiculo del Area de Computacion en Paralelo', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'T' AND p.numpiso = 1), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Cubiculo')), (24, 'Laboratorio de Ingenieria de Software (LIS)', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'T' AND p.numpiso = 3), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Laboratorio')), (5, 'Laboratorio de Computo (CEUAMI)', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio 72

73 ; WHERE e.letra = 'AT' AND p.numpiso = 1), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Laboratorio')), (9, 'Laboratorio de Electronica', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'AT' AND p.numpiso = 1), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Laboratorio')), (20, 'Laboratorio de Computo', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'AT' AND p.numpiso = 2), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Laboratorio')), (35, 'Cubiculo Area de Economia', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'H' AND p.numpiso = 0), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Cubiculo')), (26, 'Laboratorio de Analisis de Rendimiento y Teleservicios (ARTe)', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'T' AND p.numpiso = 3), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Laboratorio')), (3, 'Cubiculo de Departamento de Ingenieria Electrica', (SELECT p._id FROM piso p INNER JOIN edificio e ON e._id = p.idedificio WHERE e.letra = 'T' AND p.numpiso = 3), (SELECT t._id FROM tiposala t WHERE t.tipo = 'Cubiculo')) INSERT INTO salaprofesor (idprofesor, idsala, relacion) VALUES ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Medina Ramirez'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'T' AND p.numpiso = 3 AND s.numsala = 9), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Lopez Guerrero'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'T' AND p.numpiso = 3 AND s.numsala = 9), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Quiroz Fabian'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'T' AND p.numpiso = 1 AND s.numsala = 69), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Quiroz Fabian'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e 73

74 ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'T' AND p.numpiso = 1 AND s.numsala = 69), 'Encargado'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Barba Alvarez'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'H' AND p.numpiso = 0 AND s.numsala = 35), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Avila Mejia'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'E' AND p.numpiso = 2 AND s.numsala = 15), 'Cubiculo'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Marcelin Jimenez'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'T' AND p.numpiso = 3 AND s.numsala = 26), 'Encargado'), ((SELECT p._id FROM profesor p WHERE p.apellidos = 'Marcelin Jimenez'), (SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'T' AND p.numpiso = 3 AND s.numsala = 3), 'Cubiculo') ; INSERT INTO horario (idsala, idgrupo, inicio, fin, dia) VALUES ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'C' AND p.numpiso = 2 AND s.numsala = 15), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'CK51'), '18:00:00', '19:30:00', 'miercoles'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'C' AND p.numpiso = 2 AND s.numsala = 15), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'CK51'), '18:00:00', '19:30:00', 'lunes'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'AT' AND p.numpiso = 1 AND s.numsala = 9), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'CK51'), '18:00:00', '21:00:00', 'jueves'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e 74

75 ; ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'D' AND p.numpiso = 1 AND s.numsala = 5), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'HA03'), '12:00:00', '14:00:00', 'lunes'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'D' AND p.numpiso = 1 AND s.numsala = 5), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'HA03'), '12:00:00', '14:00:00', 'miercoles'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'D' AND p.numpiso = 1 AND s.numsala = 5), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'HA03'), '12:00:00', '14:00:00', 'viernes'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'C' AND p.numpiso = 2 AND s.numsala = 15), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'CE01'), '12:30:00', '15:00:00', 'lunes'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'D' AND p.numpiso = 1 AND s.numsala = 7), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'CE01'), '12:30:00', '14:30:00', 'miercoles'), ((SELECT s._id FROM sala s INNER JOIN piso p INNER JOIN edificio e ON e._id = p.idedificio AND p._id = s.idpiso WHERE e.letra = 'AT' AND p.numpiso = 1 AND s.numsala = 5), (SELECT g._id FROM grupo g WHERE g.iduea = AND g.grupo = 'CE01'), '12:00:00', '14:00:00', 'viernes') INSERT INTO estudiante (idgrupo) VALUES ((SELECT g._id FROM uea u INNER JOIN grupo g ON u._id = g.iduea WHERE u._id = AND g.grupo = 'CK51')), ((SELECT g._id FROM uea u INNER JOIN grupo g ON u._id = g.iduea WHERE u._id = AND g.grupo = 'CL08')), ((SELECT g._id FROM uea u INNER JOIN grupo g ON u._id = g.iduea WHERE u._id = AND g.grupo = 'HA03')) ; 75

76 Generación de la aplicación En el entorno de desarrollo Android ADT, se creó un nuevo proyecto de aplicación Android, llamado UAM QR App, que contendría los archivos fuente de la aplicación a desarrollar. Inserción de las imágenes Se agregaron a las carpetas "res/drawlable-*/" las imágenes que nos servirían para dar una mejor apariencia a la aplicación. Los nombres de los archivos deben de respetar una nomenclatura que contengan caracteres [a-z0-9_.]. 76

77 Decodificador QR También se agregó la biblioteca de lectura de códigos QR, descargando el archivo core.jar, y agregándolo a la lista de bibliotecas disponible en la aplicación. Para hacer esto, seleccionamos con el botón secundario la carpeta del proyecto y seleccionamos la opción "Build Path/Configure Build Path ". En "Java Build Path", en la etiqueta "Libraries", presionamos la opción "Add Externals JARs ". Buscamos y seleccionamos el archivo descargado y pulsamos OK. Inserción de la base de datos Agregamos el archivo de la base de datos uamdb.db en la carpeta assets. 77

78 Utilidades Modificamos el archivo strings.xml, con el siguiente código: <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">uam QR App</string> <string name="action_settings">settings</string> <string name="edificios">edificios</string> <string name="pisos">pisos</string> <string name="salas">salas</string> <string name="ueas">ueas</string> <string name="grupos">grupos</string> <string name="uam">universidad Autónoma Metropolitana</string> <string name="qr">lectura de código QR</string> <string name="uea">lista de UEAs</string> <string name="horario">horario</string> <string name="profesor">profesores</string> <string name="headiduea">id</string> <string name="headuea">uea</string> <string name="headgrupo">grupo</string> <string name="headlunes">lun</string> <string name="headmartes">mar</string> <string name="headmiercoles">mie</string> <string name="headjueves">jue</string> <string name="headviernes">vie</string> <string name="labelencargado">encargado</string> <string name="headprofesor">profesor</string> </resources> 78

79 Layouts (Interfaces de la aplicación) En la carpeta "res/layout/" del proyecto, se generaron los archivos XML que contendrían el código fuente de las interfaces que se iban a presentar en la aplicación. main.xml <RelativeLayout xmlns:android=" xmlns: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=".main" > <ImageButton android:id="@+id/ueabutton" android:layout_width="120dp" android:layout_height="120dp" android:layout_aligntop="@+id/qrbutton" android:layout_toleftof="@+id/qrbutton" android:contentdescription="@string/uea" android:src="@drawable/uea" /> <ImageButton android:id="@+id/schedulebutton" android:layout_width="120dp" android:layout_height="120dp" android:layout_aligntop="@+id/ueabutton" android:layout_toleftof="@+id/ueabutton" android:contentdescription="@string/horario" android:src="@drawable/schedule" /> <ImageButton android:id="@+id/buildingbutton" android:layout_width="120dp" android:layout_height="120dp" android:layout_aligntop="@+id/qrbutton" android:layout_torightof="@+id/qrbutton" android:contentdescription="@string/edificios" android:src="@drawable/building" /> <ImageView android:id="@+id/fotosalon" android:layout_width="match_parent" 79

80 android:layout_height="wrap_content" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:layout_margintop="20dp" android:clickable="false" /> <ImageButton android:layout_width="120dp" android:layout_height="120dp" /> <ImageButton android:layout_width="120dp" android:layout_height="120dp" android:layout_alignparentbottom="true" android:layout_centerhorizontal="true" android:layout_marginbottom="72dp" /> </RelativeLayout> qr.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:layout_margintop="50dp" android:textappearance="?android:attr/textappearancelarge" /> <TextView 80

81 android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:layout_margintop="48dp" /> </RelativeLayout> schedule.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_alignparentright="true" android:layout_alignparenttop="true" android:layout_marginleft="20dp" android:layout_marginright="20dp" android:layout_margintop="20dp" android:stretchcolumns="*" > <TableRow> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" > 81

82 <TextView /> <TextView android:layout_span="3" /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> </TableLayout> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> 82

83 </RelativeLayout> building.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> <ImageView android:layout_width="match_parent" android:layout_height="300dp" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:layout_marginleft="20dp" android:layout_marginright="20dp" android:layout_margintop="20dp" /> </RelativeLayout> floor.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:layout_width="match_parent" android:layout_height="wrap_content" 83

84 android:layout_margintop="20dp" > </ListView> <ImageView android:layout_width="400dp" android:layout_height="300dp" android:layout_alignparentright="true" android:layout_alignparenttop="true" android:layout_marginright="20dp" android:layout_margintop="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_marginleft="20dp" android:textappearance="?android:attr/textappearancelarge" android:textsize="150sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginright="20dp" android:layout_margintop="20dp" android:text="" /> </RelativeLayout> room.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" 84

85 android:layout_height="match_parent" > <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> <ImageView android:layout_width="400dp" android:layout_height="300dp" android:layout_alignparentright="true" android:layout_alignparenttop="true" android:layout_marginright="20dp" android:layout_margintop="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_marginleft="20dp" android:textappearance="?android:attr/textappearancelarge" android:textsize="150sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginright="20dp" android:layout_margintop="20dp" android:text="" /> </RelativeLayout> 85

86 sala.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:layout_width="350dp" android:layout_height="270dp" android:layout_alignparentright="true" android:layout_alignparenttop="true" android:layout_marginright="20dp" android:layout_margintop="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_marginleft="20dp" android:text="" android:textappearance="?android:attr/textappearancelarge" android:textsize="100sp" /> <TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" android:stretchcolumns="*" > <TableRow> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> 86

87 <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView /> <TextView android:layout_span="3" /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> </TableLayout> <ListView 87

88 android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="20dp" android:text="" android:textappearance="?android:attr/textappearancemedium" /> </RelativeLayout> cubículo.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:layout_width="350dp" android:layout_height="270dp" android:layout_alignparentright="true" android:layout_alignparenttop="true" android:layout_marginright="20dp" android:layout_margintop="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" 88

89 android:layout_marginleft="20dp" android:text="" android:textappearance="?android:attr/textappearancelarge" android:textsize="100sp" /> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="20dp" android:text="" android:textappearance="?android:attr/textappearancemedium" /> </RelativeLayout> laboratorio.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:layout_width="350dp" android:layout_height="270dp" android:layout_alignparentright="true" android:layout_alignparenttop="true" android:layout_marginright="20dp" android:layout_margintop="20dp" /> <TextView android:layout_width="wrap_content" 89

90 android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_marginleft="20dp" android:text="" android:textappearance="?android:attr/textappearancelarge" android:textsize="100sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="20dp" android:text="" android:textappearance="?android:attr/textappearancemedium" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="20dp" android:textappearance="?android:attr/textappearancelarge" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginleft="20dp" android:text="" android:textappearance="?android:attr/textappearancemedium" /> <TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" 90

91 android:stretchcolumns="*" > <TableRow> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView /> <TextView android:layout_span="3" /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView 91

92 /> <TextView /> </TableRow> </TableLayout> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> </RelativeLayout> profesor.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" android:layout_alignparenttop="true" android:layout_marginleft="30dp" android:layout_marginright="30dp" android:layout_margintop="30dp" android:textappearance="?android:attr/textappearancelarge" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentright="true" 92

93 android:layout_marginright="30dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="20dp" /> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> </RelativeLayout> teacher.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:layout_width="match_parent" 93

94 android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> <ImageView android:layout_width="match_parent" android:layout_height="300dp" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:layout_marginleft="20dp" android:layout_marginright="20dp" android:layout_margintop="20dp" /> </RelativeLayout> grupos.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:layout_width="400dp" android:layout_height="300dp" android:layout_alignparentright="true" android:layout_alignparenttop="true" android:layout_marginright="20dp" android:layout_margintop="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentleft="true" 94

95 android:layout_marginleft="20dp" android:layout_marginright="20dp" android:text="" android:textappearance="?android:attr/textappearancelarge" /> <TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" android:stretchcolumns="*" > <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView /> <TextView android:layout_span="3" /> <TextView /> <TextView /> <TextView /> 95

96 <TextView /> <TextView /> </TableRow> </TableLayout> <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> </RelativeLayout> uea.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="20dp" > </ListView> <ImageView android:layout_width="match_parent" android:layout_height="300dp" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:layout_marginleft="20dp" android:layout_marginright="20dp" android:layout_margintop="20dp" 96

97 /> </RelativeLayout> Recursos para los layouts Se generaron 2 interfaces especiales (custom_row_grupo.xml, custom_row_horario.xml), para poder presentar la información enlistada para cada grupo de la UEA, así como también para cada elemento de la lista del horario del usuario. custom_row_horario.xml <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchcolumns="*" > <TableRow> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:id="@+id/tablerow1" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/iduea" /> <TextView android:id="@+id/uea" android:layout_span="3" /> <TextView android:id="@+id/grupo" /> <TextView android:id="@+id/lunes" /> <TextView android:id="@+id/martes" /> <TextView android:id="@+id/miercoles" /> <TextView android:id="@+id/jueves" /> <TextView android:id="@+id/viernes" /> </TableRow> 97

98 </TableLayout> custom_row_grupo.xml <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchcolumns="*"> <TableRow > <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> <TableRow android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView /> <TextView android:layout_span="3" /> <TextView /> <TextView /> <TextView /> <TextView /> <TextView /> </TableRow> </TableLayout> Clases abstractas para los registros de la base de datos Para una correcta manipulación de los datos de la base de datos, se generaron las clases respectivas. En ellas contienen atributos intrínsecos a los registros o consultas, así como los métodos necesarios para su creación, lectura y modificación de sus atributos. Con estas herramientas construidas, se procedió a generar el archivo DBHelper.java, el cual contiene 98

99 todos los procedimientos necesarios para la creación y consulta de la base de datos generada anteriormente. Edificio.java package uam.pi.uamqrapp; public class Edificio { private int id; private String letra; private String descripcion; Edificio() { this.id = 0; this.letra = new String(""); this.descripcion = new String(""); public Edificio(int id, String letra, String descripcion) { this.id = id; this.letra = new String(letra); this.descripcion = new String(descripcion); public int getid() { return this.id; public String getletra() { return this.letra; public String getdescripcion() { return this.descripcion; Piso.java package uam.pi.uamqrapp; public class Piso { private int id; private int numpiso; private String descripcion; 99

100 private int idedificio; public Piso() { this.id = 0; this.numpiso = 0; this.descripcion = new String(""); this.idedificio = 0; { public Piso(int id, int numpiso, String descripcion, int idedificio) this.id = id; this.numpiso = numpiso; this.descripcion = new String(descripcion); this.idedificio = idedificio; public int getid() { return this.id; public int getnumpiso() { return this.numpiso; public String getdescripcion() { return this.descripcion; public int getidedificio() { return this.idedificio; Sala.java package uam.pi.uamqrapp; public class Sala { private int id; private int numsala; private String descripcion; private int idpiso; private int idtipo; public Sala() { 100

101 this.id = 0; this.numsala = 0; this.descripcion = new String(""); this.idpiso = 0; this.idtipo = 0; public Sala(int id, int numsala, String descripcion, int idpiso, int idtipo) { this.id = id; this.numsala = numsala; this.descripcion = new String(descripcion); this.idpiso = idpiso; this.idtipo = idtipo; public int getid() { return this.id; public int getnumsala() { return this.numsala; public String getdescripcion() { return this.descripcion; public int getidpiso() { return this.idpiso; public int getidtipo() { return this.idtipo; TipoSala.java package uam.pi.uamqrapp; public class TipoSala { private int id; private String tipo; public TipoSala() { this.id = 0; 101

102 this.tipo = new String(""); public TipoSala (int id, String tipo) { this.id = id; this.tipo = tipo; public int getid() { return this.id; public String gettipo() { return this.tipo; Profesor.java package uam.pi.uamqrapp; public class Profesor { private int id; private String nombre; private String apellidos; private String ; private String descripcion; public Profesor() { this.id = 0; this.nombre = new String(""); this.apellidos = new String(""); this. = new String(""); this.descripcion = new String(""); public Profesor(int id, String nombre, String apellidos, String , String descripcion) { this.id = id; this.nombre = nombre; this.apellidos = apellidos; this. = ; this.descripcion = descripcion; public int getid() { return this.id; 102

103 public String getnombre() { return this.nombre; public String getapellidos() { return this.apellidos; public String get () { return this. ; public String getdescripcion() { return this.descripcion; SalaProfesor.java package uam.pi.uamqrapp; public class SalaProfesor { private int id; private int idprofesor; private int idsala; private String relacion; public SalaProfesor() { this.id = 0; this.idprofesor = 0; this.idsala = 0; this.relacion = new String(""); public SalaProfesor(int id, int idprofesor, int idsala, String relacion) { this.id = id; this.idprofesor = idprofesor; this.idsala = idsala; this.relacion = new String(relacion); public int getid() { 103

104 return this.id; public int getidprofesor() { return this.idprofesor; public int getidsala() { return this.idsala; public String getrelacion() { return this.relacion; UEA.java package uam.pi.uamqrapp; public class UEA { private int id; private String nombre; public UEA() { this.id = 0; this.nombre = new String(""); public UEA (int id, String nombre) { this.id = id; this.nombre = nombre; public int getid() { return this.id; public String getnombre() { return this.nombre; 104

105 Grupo.java package uam.pi.uamqrapp; public class Grupo { private int id; private int iduea; private int idprofesor; public Grupo() { this.id = 0; this.iduea = 0; this.idprofesor = 0; public Grupo(int id, int iduea, int idprofesor) { this.id = id; this.iduea = iduea; this.idprofesor = idprofesor; public int getid() { return this.id; public int getiduea() { return this.iduea; public int getidprofesor() { return this.idprofesor; Horario.java package uam.pi.uamqrapp; public class Horario { private int iduea; private String grupo; private String uea; private String lunes; private String martes; private String miercoles; private String jueves; 105

106 private String viernes; public Horario () { this.iduea = 0; this.grupo = new String(""); this.uea = new String(""); this.lunes = new String(""); this.martes = new String(""); this.miercoles = new String(""); this.jueves = new String(""); this.viernes = new String(""); public int getiduea () { return this.iduea; public String getgrupo () { return this.grupo; public String getuea () { return this.uea; public String getlunes () { return this.lunes; public String getmartes () { return this.martes; public String getmiercoles () { return this.miercoles; public String getjueves () { return this.jueves; public String getviernes () { return this.viernes; public void setiduea (int iduea) { this.iduea = iduea; 106

107 public void setgrupo (String grupo) { this.grupo = grupo; public void setuea (String uea) { this.uea = uea; public void setlunes (String lunes) { this.lunes = lunes; public void setmartes (String martes) { this.martes = martes; public void setmiercoles (String miercoles) { this.miercoles = miercoles; public void setjueves (String jueves) { this.jueves = jueves; public void setviernes (String viernes) { this.viernes = viernes; Estudiante.java package uam.pi.uamqrapp; public class Estudiante { private int id; private int idgrupo; public Estudiante() { this.id = 0; this.idgrupo = 0; public Estudiante(int id, int idgrupo) { this.id = id; 107

108 this.idgrupo = idgrupo; public int getid() { return this.id; public int getidgrupo() { return this.idgrupo; GrupoLista.java package uam.pi.uamqrapp; public class GrupoLista { private int iduea; private int idgrupo; private String grupo; private String nombreprofesor; private String lunes; private String martes; private String miercoles; private String jueves; private String viernes; public GrupoLista() { this.iduea = 0; this.idgrupo = 0; this.grupo = new String(""); this.nombreprofesor = new String(""); this.lunes = new String(""); this.martes = new String(""); this.miercoles = new String(""); this.jueves = new String(""); this.viernes = new String(""); public GrupoLista (int iduea, int idgrupo, String grupo, String nombreprofesor, String lunes, String martes, String miercoles, String jueves, String viernes) { this.iduea = iduea; this.idgrupo = idgrupo; this.grupo = new String (grupo); this.nombreprofesor = new String (nombreprofesor); 108

109 this.lunes = new String (lunes); this.martes = new String (martes); this.miercoles = new String (miercoles); this.jueves = new String (jueves); this.viernes = new String (viernes); public int getiduea() { return this.iduea; public int getidgrupo() { return this.idgrupo; public String getgrupo() { return this.grupo; public String getnombreprofesor() { return this.nombreprofesor; public String getlunes() { return this.lunes; public String getmartes() { return this.martes; public String getmiercoles() { return this.miercoles; public String getjueves() { return this.jueves; public String getviernes () { return this.viernes; public void setiduea (int iduea) { this.iduea = iduea; 109

110 public void setidgrupo (int idgrupo) { this.idgrupo = idgrupo; public void setgrupo (String grupo) { this.grupo = grupo; public void setnombreprofesor( String nombreprofesor) { this.nombreprofesor = nombreprofesor; public void setlunes (String lunes) { this.lunes = lunes; public void setmartes (String martes) { this.martes = martes; public void setmiercoles( String miercoles) { this.miercoles = miercoles; public void setjueves (String jueves) { this.jueves = jueves; public void setviernes (String viernes) { this.viernes = viernes; Utilidades de las clases Se crearon además, unas clases que se requieren para la correcta consulta de las listas de los horarios, las cuales identificamos con la terminación "Adapter" al final del nombre de los archivos 14. GrupoAdapter.java package uam.pi.uamqrapp; import java.util.arraylist; import android.content.context; import android.view.layoutinflater; 110

111 import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; import android.widget.textview; public class GrupoAdapter extends BaseAdapter { private ArrayList<GrupoLista> searcharraylist; private LayoutInflater myinflater; public GrupoAdapter (Context context, ArrayList<GrupoLista> h) { this.searcharraylist = h; myinflater = public int getcount() { return public Object getitem(int position) { return public long getitemid(int position) { return position; public View getview(int position, View convertview, ViewGroup parent) ViewHolder holder; null); if (convertview == null) { convertview = myinflater.inflate(r.layout.custom_row_grupo, holder = new ViewHolder(); holder.grupo = (TextView)convertView.findViewById(R.id.grupolista); holder.profesorgrupo = (TextView)convertView.findViewById(R.id.profesorGrupo); holder.grupolunes = (TextView)convertView.findViewById(R.id.grupolunes); 111

112 holder.grupomartes = (TextView)convertView.findViewById(R.id.grupomartes); holder.grupomiercoles = (TextView)convertView.findViewById(R.id.grupomiercoles); holder.grupojueves = (TextView)convertView.findViewById(R.id.grupojueves); holder.grupoviernes = (TextView)convertView.findViewById(R.id.grupoviernes); convertview.settag(holder); else { holder = (ViewHolder) convertview.gettag(); holder.grupo.settext(searcharraylist.get(position).getgrupo()); holder.profesorgrupo.settext(searcharraylist.get(position).getnombreprofe sor()); holder.grupolunes.settext(searcharraylist.get(position).getlunes()); holder.grupomartes.settext(searcharraylist.get(position).getmartes()); holder.grupomiercoles.settext(searcharraylist.get(position).getmiercoles( )); holder.grupojueves.settext(searcharraylist.get(position).getjueves()); holder.grupoviernes.settext(searcharraylist.get(position).getviernes()); return convertview; static class ViewHolder { TextView grupo; TextView profesorgrupo; TextView grupolunes; TextView grupomartes; TextView grupomiercoles; TextView grupojueves; TextView grupoviernes; 112

113 HorarioAdapter.java package uam.pi.uamqrapp; import java.util.arraylist; import android.content.context; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; import android.widget.textview; public class HorarioAdapter extends BaseAdapter { private static ArrayList<Horario> searcharraylist; private LayoutInflater myinflater; public HorarioAdapter (Context context, ArrayList<Horario> h) { searcharraylist = h; myinflater = public int getcount() { return public Object getitem(int position) { return public long getitemid(int position) { return position; public View getview(int position, View convertview, ViewGroup parent) ViewHolder holder; if (convertview == null) { convertview = myinflater.inflate(r.layout.custom_row_horario, null); holder = new ViewHolder(); holder.iduea = (TextView) convertview.findviewbyid(r.id.iduea); holder.uea = (TextView) convertview.findviewbyid(r.id.uea); 113

114 holder.grupo = (TextView) convertview.findviewbyid(r.id.grupo); holder.lunes = (TextView) convertview.findviewbyid(r.id.lunes); holder.martes = (TextView) convertview.findviewbyid(r.id.martes); holder.miercoles = (TextView) convertview.findviewbyid(r.id.miercoles); holder.jueves = (TextView) convertview.findviewbyid(r.id.jueves); holder.viernes = (TextView) convertview.findviewbyid(r.id.viernes); convertview.settag(holder); else { holder = (ViewHolder) convertview.gettag(); holder.iduea.settext(integer.tostring(searcharraylist.get(position).getid UEA())); holder.uea.settext(searcharraylist.get(position).getuea()); holder.grupo.settext(searcharraylist.get(position).getgrupo()); holder.lunes.settext(searcharraylist.get(position).getlunes()); holder.martes.settext(searcharraylist.get(position).getmartes()); holder.miercoles.settext(searcharraylist.get(position).getmiercoles()); holder.jueves.settext(searcharraylist.get(position).getjueves()); holder.viernes.settext(searcharraylist.get(position).getviernes()); return convertview; static class ViewHolder { TextView iduea; TextView uea; TextView grupo; TextView lunes; TextView martes; TextView miercoles; TextView jueves; TextView viernes; 114

115 HorarioSalaAdapter.java package uam.pi.uamqrapp; import java.util.arraylist; import android.content.context; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; import android.widget.textview; public class HorarioSalaAdapter extends BaseAdapter { private static ArrayList<Horario> searcharraylist; private LayoutInflater myinflater; public HorarioSalaAdapter (Context context, ArrayList<Horario> h) { searcharraylist = h; myinflater = public int getcount() { return public Object getitem(int position) { return public long getitemid(int position) { return position; public View getview(int position, View convertview, ViewGroup parent) ViewHolder holder; if (convertview == null) { convertview = myinflater.inflate(r.layout.custom_row_horario, null); holder = new ViewHolder(); holder.iduea = (TextView) convertview.findviewbyid(r.id.iduea); holder.uea = (TextView) convertview.findviewbyid(r.id.uea); 115

116 holder.grupo = (TextView) convertview.findviewbyid(r.id.grupo); holder.lunes = (TextView) convertview.findviewbyid(r.id.lunes); holder.martes = (TextView) convertview.findviewbyid(r.id.martes); holder.miercoles = (TextView) convertview.findviewbyid(r.id.miercoles); holder.jueves = (TextView) convertview.findviewbyid(r.id.jueves); holder.viernes = (TextView) convertview.findviewbyid(r.id.viernes); convertview.settag(holder); else { holder = (ViewHolder) convertview.gettag(); holder.iduea.settext(integer.tostring(searcharraylist.get(position).getid UEA())); holder.uea.settext(searcharraylist.get(position).getuea()); holder.grupo.settext(searcharraylist.get(position).getgrupo()); holder.lunes.settext(searcharraylist.get(position).getlunes()); holder.martes.settext(searcharraylist.get(position).getmartes()); holder.miercoles.settext(searcharraylist.get(position).getmiercoles()); holder.jueves.settext(searcharraylist.get(position).getjueves()); holder.viernes.settext(searcharraylist.get(position).getviernes()); return convertview; static class ViewHolder { TextView iduea; TextView uea; TextView grupo; TextView lunes; TextView martes; TextView miercoles; TextView jueves; TextView viernes; 116

117 Bases de datos Se generó la clase específica para el manejo y administración de la base de datos: DBHelper.java package uam.pi.uamqrapp; import java.io.fileoutputstream; import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.util.arraylist; import java.util.list; import android.annotation.suppresslint; import android.content.contentvalues; import android.content.context; import android.database.cursor; import android.database.sqlexception; import android.database.sqlite.sqlitedatabase; import android.database.sqlite.sqliteexception; import android.database.sqlite.sqliteopenhelper; 117

La última versión disponible cuando se redactó este manual era la 5 Beta (versión ), y sobre ella versa este manual.

La última versión disponible cuando se redactó este manual era la 5 Beta (versión ), y sobre ella versa este manual. Manual de Dev-C++ 4.9.9.2 Página 1 de 11 Introducción Dev-C++ es un IDE (entorno de desarrollo integrado) que facilita herramientas para la creación y depuración de programas en C y en C++. Además, la

Más detalles

Programación Android. Alejandro Alcalde. elbauldelprogramador.com

Programación Android. Alejandro Alcalde. elbauldelprogramador.com Programación Android Alejandro Alcalde elbauldelprogramador.com Copyright c 2013 Alejandro Alcalde P L A TEX. Programación Android por Alejandro Alcalde se encuentra bajo una Licencia Creative Commons

Más detalles

Laboratorio. Instalación de Visual Studio Community. Back To Basics Instalando Visual Studio Community. Versión: 1.0.

Laboratorio. Instalación de Visual Studio Community. Back To Basics Instalando Visual Studio Community. Versión: 1.0. Laboratorio Instalación de Visual Studio Community Versión: 1.0.0 Enero de 2016 Página 1 de 19 informes@ticapacitacion.com http://ticapacitacion.com CONTENIDO INTRODUCCIÓN EJERCICIO 1: INSTALANDO VISUAL

Más detalles

Descarga e Instalación de Java Development Kit (JDK)

Descarga e Instalación de Java Development Kit (JDK) Instalación del SDK de Android en Eclipse Por M.T.I. Jorge Carranza Gómez Para desarrollar aplicaciones para el Sistema Operativo Android, se deben revisar los requisitos mínimos para instalar el entorno

Más detalles

FIRMA ELECTRÓNICA INSTALACIÓN Y USO DE CERTIFICADOS EN ARCHIVO PKCS#12 MANUAL DE USUARIO V1.1 14/07/2015

FIRMA ELECTRÓNICA INSTALACIÓN Y USO DE CERTIFICADOS EN ARCHIVO PKCS#12 MANUAL DE USUARIO V1.1 14/07/2015 FIRMA ELECTRÓNICA INSTALACIÓN Y USO DE CERTIFICADOS EN ARCHIVO PKCS#12 MANUAL DE USUARIO V1.1 14/07/2015 Dirección Nacional de Tecnologías de la Información y Comunicaciones Instalación de certificado

Más detalles

Instrucciones de configuración del acceso remoto (VPN) de la UCLM para Windows, Mac y Linux

Instrucciones de configuración del acceso remoto (VPN) de la UCLM para Windows, Mac y Linux Instrucciones de configuración del acceso remoto (VPN) de la UCLM para Windows, Mac y Linux Referencia -- Fecha 14/03/2016 Autores Área TIC Destinatarios Estudiantes, PDI y PAS de la UCLM Descripción Este

Más detalles

INSTITUCION EDUCATIVA MANUEL ANGEL ANACHURY AREA: TECNOLOGIA E INFORMATICA

INSTITUCION EDUCATIVA MANUEL ANGEL ANACHURY AREA: TECNOLOGIA E INFORMATICA BASES DE DATOS (ACCES 2007) OBJETIVO: Conocer el concepto de bases de datos y su funcionalidad además de crear destrezas en su creación y manipulación. Elementos básicos de Access 2007 Vamos a ver cuáles

Más detalles

JAVA 7 Los fundamentos del lenguaje Java

JAVA 7 Los fundamentos del lenguaje Java Presentación 1. Historia 9 1.1 Por qué Java? 9 1.2 Objetivos del diseño de Java 10 1.3 Auge de Java 11 2. Características de Java 12 2.1 El lenguaje de programación Java 12 2.1.1 Sencillo 13 2.1.2 Orientado

Más detalles

Ejecuta el modo XP sin virtualización de hardware

Ejecuta el modo XP sin virtualización de hardware Una de las características más limpias nuevo en Windows 7 orgánico y categorías superiores es el modo de XP, pero no todas las máquinas son capaces de ejecutarlo. Hoy te mostramos cómo utilizar VMware

Más detalles

Tema: Introducción al IDE de Microsoft Visual C#.

Tema: Introducción al IDE de Microsoft Visual C#. Tema: Introducción al IDE de Microsoft Visual C#. Objetivos: El propósito de este tema es que el alumno se familiarice con el entorno de desarrollo de Visual C# Express mientras crea el formulario más

Más detalles

Manual de Usuarios SOFTWARE RAZUNA - DAM. Grupo de Innovación y Apropiación de Tecnologías de la Información Archivística CKAN

Manual de Usuarios SOFTWARE RAZUNA - DAM. Grupo de Innovación y Apropiación de Tecnologías de la Información Archivística CKAN Manual de Usuarios SOFTWARE RAZUNA - DAM Grupo de Innovación y Apropiación de Tecnologías de la Información Archivística Compilador: Sandra Milena Díaz Bermúdez CKAN 2016 SOFTWARE INTRODUCCIÓN Este manual

Más detalles

1

1 Curso: BORLAN DELPHI 5 Curso de desarrollo de aplicaciones Windows utilizando el entorno de programación Borland Delphi 5. Se estudian las particularidades del lenguaje Delphi, así como su sintaxis; sus

Más detalles

Elementos esenciales de Word

Elementos esenciales de Word Word 2013 Elementos esenciales de Word Área académica de Informática 2015 Elementos esenciales de Word Iniciar Microsoft Word 2013 Para entrar en Microsoft Word 2013 Haz clic en el botón Inicio para ir

Más detalles

La Herramienta Redmine para la Administración de Proyectos

La Herramienta Redmine para la Administración de Proyectos La Herramienta Redmine para la Administración de Proyectos 13. Administración y utilización de la funcionalidad de seguimiento de peticiones en Redmine Mag. José Eduardo Rodríguez Esquivel jose.rodriguez@ecci.ucr.ac.cr

Más detalles

Manual de Instalación para el óptimo funcionamiento de la Firma Electrónica Avanzada

Manual de Instalación para el óptimo funcionamiento de la Firma Electrónica Avanzada SECRETARÍA DE LA FUNCIÓN PÚBLICA U N I D A D D E I N F O R M Á T I C A ÁREA DE FIRMA ELECTRÓNICA Manual de Instalación para el óptimo funcionamiento de la Firma Electrónica Avanzada En este manual encontrará

Más detalles

Guía de instalación de CAM EXPRESS 8.5 Para Windows XP

Guía de instalación de CAM EXPRESS 8.5 Para Windows XP Guía de instalación de CAM EXPRESS 8.5 Para Primera Edición: octubre 2014 Guía de instalación de CAM EXPRESS 8.5 para Urrutiko Lanbide Heziketa Institutua Esta publicación realizada por Urrutiko Lanbide

Más detalles

Cómo utilizar Conference Manager para Microsoft Outlook

Cómo utilizar Conference Manager para Microsoft Outlook Cómo utilizar Conference Manager para Microsoft Outlook Mayo de 2012 Contenido Capítulo 1: Cómo utilizar Conference Manager para Microsoft Outlook... 5 Introducción a Conference Manager para Microsoft

Más detalles

Acceso a Datos con Visual Basic

Acceso a Datos con Visual Basic Capítulo 1: Definición del Proyecto Acceso a Datos con Visual Basic Sin duda alguna, que uno de los lenguajes más potentes para manejo de bases de datos es Microsoft Visual Basic.Net, por lo cual en esta

Más detalles

INTRODUCCIÓN. paco@portadaalta.es

INTRODUCCIÓN. paco@portadaalta.es INTRODUCCIÓN paco@portadaalta.es Índice Entorno de desarrollo Estructura de un proyecto Android Componentes de una aplicación Android Ejemplos: Mi primera aplicación Divisas 2 actividades Contador de cafés

Más detalles

COMO CREAR UNA RED LOCAL ENTRE EQUIPOS CON WINDOWS

COMO CREAR UNA RED LOCAL ENTRE EQUIPOS CON WINDOWS COMO CREAR UNA RED LOCAL ENTRE EQUIPOS CON WINDOWS XP Y VISTA: Explicación con direcciones estáticas y dinámicas. 1. RED CON DIRECCIONES DINAMICAS: La primera explicación la realizaré para XP. Lo primero

Más detalles

Sistema de Gestión y almacenamiento de archivos en el Campus Virtual

Sistema de Gestión y almacenamiento de archivos en el Campus Virtual Sistema de Gestión y almacenamiento de archivos en el Campus Virtual Página 1 de 15 GESTIÓN DE ARCHIVOS Dentro del Campus Virtual vamos a tener distintas formas de seleccionar y gestionar los archivos.

Más detalles

MANUAL DE CONFIGURACION DE ADOBE PARA LA VALIDACION DE LA FIRMA DE UN DOCUMENTO

MANUAL DE CONFIGURACION DE ADOBE PARA LA VALIDACION DE LA FIRMA DE UN DOCUMENTO MANUAL DE CONFIGURACION DE ADOBE PARA LA VALIDACION DE LA FIRMA DE UN DOCUMENTO Febrero 2009 1/17 Índice 1. Introducción...3 2. Instalar los certificados de Firmaprofesional...3 3. Configurar Adobe Reader

Más detalles

MASTER DESARROLLO DE APLICACIONES ANDROID

MASTER DESARROLLO DE APLICACIONES ANDROID MASTER DESARROLLO DE APLICACIONES ANDROID TEMARIO MODULO I La plataforma Android Origen Google Play Creación de una cuenta de desarrollador Publicación de una aplicación Seguimiento y actualización de

Más detalles

www.android-spa.com Android Creación de una aplicación sencilla: Forwarding - Página 1 -

www.android-spa.com Android Creación de una aplicación sencilla: Forwarding - Página 1 - Android Creación de una aplicación sencilla: Forwarding - Página 1 - Realización de la aplicación Forwarding en Android Este es un pequeño tutorial con el que se realizará un pequeño programa para Android

Más detalles

ALMACENAMIENTOS DE DATOS EN ANDROID CON SQLITE

ALMACENAMIENTOS DE DATOS EN ANDROID CON SQLITE SQLite M.Sc. Reynaldo Zeballos ALMACENAMIENTOS DE DATOS EN ANDROID CON SQLITE En este ejercicio vamos a crear una tabla TELEFONOS para la base de datos GUIATEL. Para lo cual utilizaremos SQLite que viene

Más detalles

IDENTIFICACIÓN DE LA ACTIVIDAD PEDAGÓGICA. Búsquedas en Google

IDENTIFICACIÓN DE LA ACTIVIDAD PEDAGÓGICA. Búsquedas en Google PROGRAMA DE FORMACIÓN UNIDAD DE APRENDIZAJE ACTIVIDAD OBJETIVOS IDENTIFICACIÓN DE LA ACTIVIDAD PEDAGÓGICA HIGIENE Y SEGURIDAD INDUSTRIAL - SEGURIDAD OCUPACIONAL I-A HERRAMIENTAS INFORMATICAS INTERNET:

Más detalles

PowerPoint 2010 Edición del contenido

PowerPoint 2010 Edición del contenido PowerPoint 2010 Edición del contenido Contenido CONTENIDO... 1 AGREGAR TEXTO A UNA DIAPOSITIVA... 2 MOVER Y COPIAR INFORMACIÓN... 5 PANEL DE TAREAS PORTAPAPELES... 7 TRABAJO CON DIAPOSITIVAS... 8 EDICIÓN

Más detalles

Manual de Instrucciones para el uso con un ordenador

Manual de Instrucciones para el uso con un ordenador Tablero electrónico Portátil de Escritura Manual de Instrucciones para el uso con un ordenador Nota: es necesario el uso de un ordenador personal con sistema operativo Microsoft Windows y un puerto de

Más detalles

Manual Lector Ges2S Rumitag (Versión 5.0.7)

Manual Lector Ges2S Rumitag (Versión 5.0.7) Manual Lector Ges2S Rumitag (Versión 5.0.7) Menú de opciones 1. Lectura 2. Control 1. Nuevo 2. Modificar 3. Borrar 4. Imprimir 5. Imprimir Todo 3. Borrar datos 4. Capacidad 5. Configuración 1. Nivel Batería

Más detalles

Instalación y Registro Versiones Educativas Alumno 2013 M13

Instalación y Registro Versiones Educativas Alumno 2013 M13 Instalación y Registro Versiones Educativas Alumno 2013 M13 Editex Instalación y Registro Online 1 Índice 1. Introducción... 3 2. Requisitos mínimos... 4 3. Descarga e instalación Versión Alumno... 5 4.

Más detalles

Desarrollo Para Dispositivos Móviles.

Desarrollo Para Dispositivos Móviles. Desarrollo Para Dispositivos Móviles. 72 Horas OBJETIVOS Aprender a utilizar los entornos de desarrollo más habituales para la creación de aplicaciones móviles Estudiar el desarrollo de aplicaciones para

Más detalles

Manual de instalación AutoFirma 1.4.3

Manual de instalación AutoFirma 1.4.3 DIRECCIÓN DE TECNOLOGÍAS DE LA INFORMACIÓN Y LAS Manual de instalación 1.4.3 Manual de usuario Índice de contenidos 1 Introducción...3 2 Requisitos mínimos...4 3 Enlaces de descarga...5 4 Instalación...5

Más detalles

MANUAL DE USUARIO VU ASIGNAR ROL USUARIOS EXTERNO

MANUAL DE USUARIO VU ASIGNAR ROL USUARIOS EXTERNO MANUAL DE USUARIO VU ASIGNAR ROL USUARIOS EXTERNO Sumario Propósito El propósito del manual es proporcionar información del sistema al Usuario externo, sobre cómo administrar un tercero, así como también

Más detalles

Instalación de VirtualBox. Prácticas adicionales

Instalación de VirtualBox. Prácticas adicionales Instalación de VirtualBox Prácticas adicionales 1.- Introducción VirtualBox es un programa de virtualizacionx86 y AMD64/Intel64 de gran alcance tanto para la empresa, así como el uso doméstico.virtualboxes

Más detalles

Fórmulas de Competición

Fórmulas de Competición 37 Fórmulas de Competición SECCIÓN 10 CAPÍTULO 37 COMPETICIÓN FÓRMULAS DE COMPETICIÓN Fórmulas de Competición. Seleccionamos la opción Fórmulas de Competición dentro de la zona Competición apareciéndonos

Más detalles

Índice. Herramientas de desarrollo. Historia Qué es Android? Arquitectura del sistema. Componentes Android Modelos de Negocio

Índice. Herramientas de desarrollo. Historia Qué es Android? Arquitectura del sistema. Componentes Android Modelos de Negocio 1 Introducción a Android Índice Historia Qué es Android? Arquitectura del sistema Herramientas de desarrollo Componentes Android Modelos de Negocio 2 Objetivos Herramientas de desarrollo Conocer las herramientas

Más detalles

Gestión de datos maestros

Gestión de datos maestros Gestión de datos maestros Con el administrador de datos maestros le será posible administrar y realizar tareas de mantenimiento en datos maestros comunes de la base de datos actual como un proceso. Esto

Más detalles

Ubuntu Server HOW TO : SERVIDOR DE IMPRESORAS

Ubuntu Server HOW TO : SERVIDOR DE IMPRESORAS Ubuntu Server 12.10 HOW TO : SERVIDOR DE IMPRESORAS EN ESTE SE REALIZA LO SIGUIENTE: En este how to se le va a enseñar como instalar CUPS y como administrar. Common Unix Printing System (Sistema de impresión

Más detalles

Figura 1: Abriendo el Performance Monitor Figura 2: Pantalla Inicial del Monitor

Figura 1: Abriendo el Performance Monitor Figura 2: Pantalla Inicial del Monitor Universidad de Los Andes Departamento de Ingeniería de Sistemas y Computación Infraestructura Computacional ISIS 2203 (C1) Manual Performance Monitor Windows Server 2008 Preparado por: Asistente Graduado

Más detalles

Hola Android. Introducción al desarrollo de aplicaciones para Android

Hola Android. Introducción al desarrollo de aplicaciones para Android Hola Android. Introducción al desarrollo de aplicaciones para Android Las aplicaciones para el sistema operativo móvil Android son desarrolladas en el lenguaje de programación Java en conjunto con el SDK

Más detalles

Tema 10: Plataforma Moodle: Primeros Pasos

Tema 10: Plataforma Moodle: Primeros Pasos Tema 10: Plataforma Moodle: Primeros Pasos Primeros pasos En este apartado darás tus primeros pasos en la plataforma Moodle del ITE, accediendo a la plataforma para autenticarte en ella con las credenciales

Más detalles

Manual Word Macros y Elementos rápidos

Manual Word Macros y Elementos rápidos Manual Word 2010 Macros y Elementos rápidos CONTENIDO Macros Grabar una macro Ejecutar una macro Macros Word permite automatizar tareas repetitivas mediante la creación de macros que consisten en una serie

Más detalles

Ejercicio 3. Manejo de la Vista y Eventos en Android Ejercicio 3 Curso de Android con Java Derechos Res Dere e c rvados hos Res Gl e obal rva

Ejercicio 3. Manejo de la Vista y Eventos en Android Ejercicio 3 Curso de Android con Java Derechos Res Dere e c rvados hos Res Gl e obal rva Android Con Java Ejercicio 3 Manejo de la Vista y Eventos en Android Objetivo del Ejercicio El objetivo del ejercicio es entender cómo controlar la Vista desde código Java, así como responder a eventos

Más detalles

Gestión de bases de datos de mysql desde Dreamweaver

Gestión de bases de datos de mysql desde Dreamweaver Gestión de bases de datos de mysql desde Dreamweaver Para realizar este tutorial debes tener instalado Adobe Dreamweaver CS6 y Wampserver 2.2. Contenido. Instalar el servidor de prueba Crear la base de

Más detalles

CÁMARA IP INALÁMBRICA HD 720p VISIÓN NOCTURNA, AUDIO Y FUNCIÓN DE GRABACIÓN

CÁMARA IP INALÁMBRICA HD 720p VISIÓN NOCTURNA, AUDIO Y FUNCIÓN DE GRABACIÓN CÁMARA IP INALÁMBRICA HD 720p VISIÓN NOCTURNA, AUDIO Y FUNCIÓN DE GRABACIÓN VTA-83700 Gracias por adquirir nuestra CÁMARA! Antes de instalar y operar el producto, se recomienda tener en cuenta las instrucciones

Más detalles

Manejo de Bases de Datos Mysql en Lenguaje C

Manejo de Bases de Datos Mysql en Lenguaje C http://undersecurity.net Servidor irc : irc.ircnode.com Canal irc : #undersec Manejo de Bases de Datos Mysql en Lenguaje C By: S[e]C Entendiendo el tratamiento de una base de datos MySQL. Antes de ir al

Más detalles

INTRODUCCIÓN AL POWER POINT 2007 POWER POINT Manual de Referencia para usuarios. Salomón Ccance CCANCE WEBSITE

INTRODUCCIÓN AL POWER POINT 2007 POWER POINT Manual de Referencia para usuarios. Salomón Ccance CCANCE WEBSITE INTRODUCCIÓN AL POWER POINT 2007 POWER POINT 2007 Manual de Referencia para usuarios Salomón Ccance CCANCE WEBSITE INTRODUCCIÓN AL POWER POINT 2007 Qué es una herramienta de presentación? Una herramienta

Más detalles

Objetos OLE 1. IMAGEN DE FONDO

Objetos OLE 1. IMAGEN DE FONDO 1. IMAGEN DE FONDO L as bases de datos de Access pueden almacenar información de distinta naturaleza: texto, valores numéricos o monetarios, fechas, etc. Pero además también pueden almacenar imágenes u

Más detalles

Instrucciones para obtener el certificado electrónico de la FNMT

Instrucciones para obtener el certificado electrónico de la FNMT Instrucciones para obtener el certificado electrónico de la FNMT Índice 1. Registro Documental... 3 2. Objeto del documento... 4 3. Instrucciones para obtener el certificado electrónico de la FNMT... 5

Más detalles

1.4.1 Inicio de la computadora por primera vez Hay problemas Causas, síntomas y soluciones a posibles averías...

1.4.1 Inicio de la computadora por primera vez Hay problemas Causas, síntomas y soluciones a posibles averías... Índice INTRODUCCIÓN...11 CAPÍTULO 1. EXPLOTACIÓN DE SISTEMAS MICROINFORMÁTICOS...13 1.1 La arquitectura de los ordenadores...14 1.1.1 La máquina de Turing...14 1.1.2 La arquitectura Harvard...15 1.1.3

Más detalles

Seleccione en el escritorio el programa Sucosoft S40 y darle doble click.

Seleccione en el escritorio el programa Sucosoft S40 y darle doble click. Programación y manejo de Sucosoft S40: Cómo Programar? Seleccione en el escritorio el programa Sucosoft S40 y darle doble click. Aparece una ventana denominada administrador Sucosoft en la cual se encuentra

Más detalles

INTRODUCCIÓN...9 CAPÍTULO 1. ELEMENTOS DE UN PROGRAMA INFORMÁTICO...11

INTRODUCCIÓN...9 CAPÍTULO 1. ELEMENTOS DE UN PROGRAMA INFORMÁTICO...11 Índice INTRODUCCIÓN...9 CAPÍTULO 1. ELEMENTOS DE UN PROGRAMA INFORMÁTICO...11 1.1 PROGRAMA Y LENGUAJESDE PROGRAMACIÓN...12 1.1.1 EL LENGUAJE JAVA...13 1.1.2 EL JDK...15 1.1.3 LOS PROGRAMAS EN JAVA...16

Más detalles

Taller de TeamViewer. Manual De TeamViewer

Taller de TeamViewer. Manual De TeamViewer Taller de TeamViewer Manual De TeamViewer Índice. Índice Objetivos de aprendizaje 2 TeamViewer..... 2 Página n. 1 Objetivos del aprendizaje Conocer que TeamViewer y su utilidad. Aprender como manejar un

Más detalles

MINISTERIO DE SALUD Y PROTECCIÓN SOCIAL BOGOTÁ, AGOSTO DE 2015

MINISTERIO DE SALUD Y PROTECCIÓN SOCIAL BOGOTÁ, AGOSTO DE 2015 CERTIFICADOS DE DEFUNCION ANTECEDENTE PARA REGISTRO CIVIL EN INSTITUCIONES PRESTADORAS DE SERVICIOS DE SALUD A TRAVÉS DE LA FIRMA MÓDULO DE NACIMIENTOS Y DEFUNCIONES DEL REGISTRO UNICO DE AFILIADOS RUAF

Más detalles

COLEGIO PABLO DE TARSO IED CONSTRUCCION DE PROYECTOS DE VIDA PRODUCTIVOS DREAMWEAVER UNO- PRÁCTICAS DOC RAUL MONROY PAMPLONA

COLEGIO PABLO DE TARSO IED CONSTRUCCION DE PROYECTOS DE VIDA PRODUCTIVOS DREAMWEAVER UNO- PRÁCTICAS DOC RAUL MONROY PAMPLONA Metas de comprensión cuarto periodo Comprende sus responsabilidades a la hora de formular sus propuestas como soluciones a problemas reales que impliquen el uso de las tecnologías de información y la gestión

Más detalles

Manual de ayuda de la herramienta de comunicación privada Correo Interno

Manual de ayuda de la herramienta de comunicación privada Correo Interno Manual de ayuda de la herramienta de comunicación privada Correo Interno Contenido Introducción... 3 Configuración del bloque... 3 Gestión del bloque... 4 Lista de contactos... 8 Creación y envío de nuevos

Más detalles

Documentación para desarrolladores

Documentación para desarrolladores Documentación para desarrolladores Página 1 de 180 1.Introducción ChinApp es una aplicación móvil con soporte para generar está misma a través de una aplicación web. Este documento es una informativa sobre

Más detalles

Funciones de Network Assistant

Funciones de Network Assistant CAPÍTULO 2 Network Assistant simplifica la administración de las comunidades o grupos ofreciendo una GUI, modos alternativos para configurar dispositivos en redes, dos niveles de acceso y una completa

Más detalles

SALVADOR GÓMEZ OLIVER WWW.SGOLIVER.NET

SALVADOR GÓMEZ OLIVER WWW.SGOLIVER.NET SALVADOR GÓMEZ OLIVER WWW.SGOLIVER.NET Versión 2.0 // Noviembre 2011 Este documento y todo el código fuente suministrado, al igual que todos los contenidos publicados en el blog sgoliver.net, se publica

Más detalles

En este artículo vamos a conocer los tipos de datos que podemos manejar programando en C.

En este artículo vamos a conocer los tipos de datos que podemos manejar programando en C. El primer objetivo de un programa informático es el manejo de datos. Un dato es toda aquella información que se puede tratar en un programa informático. En este artículo vamos a conocer los tipos de datos

Más detalles

INSTALACIÓN Y VERIFICACIÓN DE LA TARJETA CRIPTOGRÁFICA

INSTALACIÓN Y VERIFICACIÓN DE LA TARJETA CRIPTOGRÁFICA INSTALACIÓN Y VERIFICACIÓN DE LA TARJETA CRIPTOGRÁFICA Bienvenido! El acceso al sistema de LexNET, requiere estar en posesión de un certificado de firma electrónica en tarjeta. Para trabajar con la tarjeta,

Más detalles

INFORMÁTICA Y COMUNICACIONES

INFORMÁTICA Y COMUNICACIONES 441 INFORMÁTICA Y COMUNICACIONES Microsoft Access 2003 (Completo) DESCRIPCIÓN Microsoft Access 2003 (Completo) Descripción del funcionamiento del programa de gestión de bases de datos Microsoft Access

Más detalles

MANUAL DE INSTALACIÓN Y USO DE FBackup

MANUAL DE INSTALACIÓN Y USO DE FBackup MANUAL DE INSTALACIÓN Y USO DE FBackup FBackup es una herramienta gratuita para realizar copias de seguridad de nuestra información. Con FBackup podrás crear tus copias de seguridad tanto personales como

Más detalles

Tema 1. Introducción a OpenOffice Writer

Tema 1. Introducción a OpenOffice Writer Tema 1: Introducción a OpenOffice 1 Tema 1 Introducción a OpenOffice Índice de contenido Prefacio...2 Gestión básica de documentos...2 Tema 1: Introducción a OpenOffice 2 Prefacio Este curso tiene como

Más detalles

LENGUAJES JÓVENES PROGRAMADORES

LENGUAJES JÓVENES PROGRAMADORES LENGUAJES JÓVENES PROGRAMADORES SCRATCH Qué es Scratch? Es un lenguaje de programación creado por el MIT (Instituto Tecnológico de Massachusetts, EE.UU.) y diseñado para el aprendizaje de la programación.

Más detalles

DEMOSTRACION DE UNA APLICACIÓN N-CAPASCON JAVA- POSTGRESQL

DEMOSTRACION DE UNA APLICACIÓN N-CAPASCON JAVA- POSTGRESQL DEMOSTRACION DE UNA APLICACIÓN N-CAPASCON JAVA- POSTGRESQL En este manual podemos encontrar una guía importante para desarrollar una aplicación de escritorio N-Capas utilizando Herramientas Open-Source

Más detalles

Actualización de versión en red descargada de internet

Actualización de versión en red descargada de internet Actualización de versión en red descargada de internet Proceso de actualización de versión Importante!!! Generar respaldo de la información de sus empresas antes de llevar a cabo el proceso de actualización.

Más detalles

CANTABRIA GOBIERNO DE

CANTABRIA GOBIERNO DE Este manual describe cómo validar, con la aplicación Adobe Reader o Adobe Acrobat, la firma de los documentos en formato PDF que el BOC pone a disposición de los ciudadanos en su sede electrónica. Aunque

Más detalles

Ministerio de Educación. Base de datos en la Enseñanza. Open Office. Módulo 5: Informes

Ministerio de Educación. Base de datos en la Enseñanza. Open Office. Módulo 5: Informes Ministerio de Educación Base de datos en la Enseñanza. Open Office Módulo 5: Informes Instituto de Tecnologías Educativas 2011 Informes Los informes son la herramienta encargada de presentar los datos

Más detalles

Informática HOT POTATOES

Informática HOT POTATOES 1 Informática HOT POTATOES Hot Potatoes es un conjunto de seis herramientas de autor, desarrollado por el equipo del University of Victoria CALL Laboratory Research and Development, que permite elaborar

Más detalles

DIRECCIÓN REGIONAL DE EDUCACIÓN LIMA PROVINCIAS MANUAL MANEJO DEL PORTAL PERUEDUCA 2014

DIRECCIÓN REGIONAL DE EDUCACIÓN LIMA PROVINCIAS MANUAL MANEJO DEL PORTAL PERUEDUCA 2014 DIRECCIÓN REGIONAL DE EDUCACIÓN LIMA PROVINCIAS MANUAL MANEJO DEL PORTAL PERUEDUCA 0 MANUAL - PERUEDUCA REGISTRO DOCENTE www.perueduca.com.pe Hacer clic a este enlace Se visualiza la ventana del portal

Más detalles

Crear imagen con Windows XP, SP2 y actualizaciones críticas con NLite

Crear imagen con Windows XP, SP2 y actualizaciones críticas con NLite There are no translations available. Aprende a crear un CD o DVD autoarrancable de Windows XP, Servipack 2 y actualizaciones críticas de Windows con el programa de software libre NLite. Crear imagen con

Más detalles

PROCEDIMIENTO PARA GENERAR LOS REQUERIMIENTOS DE SELLOS DIGITALES

PROCEDIMIENTO PARA GENERAR LOS REQUERIMIENTOS DE SELLOS DIGITALES PROCEDIMIENTO PARA GENERAR LOS REQUERIMIENTOS DE SELLOS DIGITALES 1. Requerimiento de Sellos El Usuario que desee realizar una Solicitud de Sello Digital debe ingresar a la siguiente dirección Web y descargar

Más detalles

Cómo generar un blog

Cómo generar un blog Cómo generar un blog Patricia Martínez Falcón Erika Yazmin Avila Bonifacio Coordinación h@bitat puma Para crear un blog mediante Blogger es necesario contar con una contraseña en Google, además de la dirección

Más detalles

CUTCSA INFO Manual del Usuario

CUTCSA INFO Manual del Usuario Aplicación Móvil CUTCSA INFO Manual del Usuario Pág. 1 de 10 Historial de Revisiones Fecha Versión Descripción Autor 20/06/2014 1.0 Creación del documento Jhollman Chacón 28/07/2014 1.1 Horarios y Personalización

Más detalles

Guía de usuario PayPhone Store

Guía de usuario PayPhone Store 1 2 PayPhone te permite cobrar con tarjetas de crédito y débito de la manera más fácil, cómoda y segura, ya sea de forma presencial, es decir dentro de tú mismo establecimiento o a distancia, ideal para

Más detalles

MANUAL DEL USUARIO. Página Web. https://www.sfacilminube.com

MANUAL DEL USUARIO. Página Web. https://www.sfacilminube.com MANUAL DEL USUARIO Página Web https://www.sfacilminube.com 1 Contenido Página principal..3 Administración de archivos.5 Crear carpetas...7 Subir archivos..7 Filtrar archivo..8 Navegar entre carpetas 8

Más detalles

Archivos Datanet. Si desea acceder directamente a un capítulo, posicionese sobre el número de página y haga clic.

Archivos Datanet. Si desea acceder directamente a un capítulo, posicionese sobre el número de página y haga clic. Archivos Datanet Archivos Datanet...1 Download Automático de SIB...2 Requisitos para el uso...2 1. Contratación del servicio:...2 2. Alta de un Operador de Sistema :...2 3. Instale el programa:...6 AutoSIB...9

Más detalles

Manual de uso de OWNCLOUD

Manual de uso de OWNCLOUD Manual de uso de OWNCLOUD OwnCloud es una herramienta gratuita, de código abierto utilizada para almacenar datos en una nube localizada en la red. Tiene la funcionalidad de almacenar, compartir y proteger

Más detalles

UNIDAD 4. MODIFICAR TABLAS DE DATOS

UNIDAD 4. MODIFICAR TABLAS DE DATOS UNIDAD 4. MODIFICAR TABLAS DE DATOS Aquí veremos las técnicas de edición de registros para modificar tanto la definición de una tabla como los datos introducidos en ella. Esta unidad está dedicada, principalmente,

Más detalles

Cómo instalar Estudio One SQL versión 2.40

Cómo instalar Estudio One SQL versión 2.40 Pág. 1 de 9 El presente instructivo lo guiará para realizar la instalación de Estudio One SQL 2.40 en varias PCs (Terminales) conectadas en red a una PC Servidora (la PC que posee las bases de datos).

Más detalles

Módulo Conversor de Superficies

Módulo Conversor de Superficies Notarnet S.L. Módulo Conversor de Superficies Not@rnet Resumen Con el Módulo Conversor de Superficies, se ahorra tiempo y se evitan errores al transcribir cifras de superficies en letras, al convertir

Más detalles

Creando Plantilla de Procesos para la Generación de Team Project

Creando Plantilla de Procesos para la Generación de Team Project Creando Plantilla de Procesos para la Generación de Team Project Team Project Dentro de los múltiples tipos de tareas que he realizado en la implementación de Team Foundation, en las organizaciones que

Más detalles

Para entornos con más de un equipo conectados en red es necesario que el programa de firewall conceda paso a los servicios de Microsoft SQL Server.

Para entornos con más de un equipo conectados en red es necesario que el programa de firewall conceda paso a los servicios de Microsoft SQL Server. ET-SEGURIDAD SQL INSTRUCCIONES DE USO RÁPIDO IMPORTANTE Este software puede ser bloqueado por software antivirus. Asegúrese de añadir la excepción correspondiente si fuese necesario. Se recomienda deshabilitar

Más detalles

Actualizaciones de software Guía del usuario

Actualizaciones de software Guía del usuario Actualizaciones de software Guía del usuario Copyright 2008, 2009 Hewlett-Packard Development Company, L.P. Windows es una marca comercial registrada de Microsoft Corporation en los Estados Unidos. Aviso

Más detalles

Unidad 5. Tablas. La celda que se encuentra en la fila 1 columna 2 tiene el siguiente contenido: 2º Celda

Unidad 5. Tablas. La celda que se encuentra en la fila 1 columna 2 tiene el siguiente contenido: 2º Celda Unidad 5. Tablas Una tabla está formada por celdas o casillas, agrupadas por filas y columnas, en cada casilla se puede insertar texto, números o gráficos. Lo principal antes de empezar a trabajar con

Más detalles

PROYECTO 2 Parte 1 BASES DE DATOS. Curso (2 Semestre) Grupos 4F2M y 4F1M-1 (aula 5102) CONSULTAS REMOTAS EN JAVA A UNA BASE DE DATOS

PROYECTO 2 Parte 1 BASES DE DATOS. Curso (2 Semestre) Grupos 4F2M y 4F1M-1 (aula 5102) CONSULTAS REMOTAS EN JAVA A UNA BASE DE DATOS PROYECTO 2 Parte 1 BASES DE DATOS Curso 2014-15 (2 Semestre) Grupos 4F2M y 4F1M-1 (aula 5102) CONSULTAS REMOTAS EN JAVA A UNA BASE DE DATOS Pág. 1 de 8 1. Objetivos Generales Acceder a una Base de Datos

Más detalles

MANUAL DE INSTALACIÓN

MANUAL DE INSTALACIÓN MANUAL DE INSTALACIÓN PARA DISPOSITIVOS MÓVILES CONFIGURACIÓN DE APLICATIVOS SOFTPHONE PARA ANDROID 0. ZOIPER. Descarga e instala en tu teléfono la aplicación ZOIPER (versión gratuita) en la tienda de

Más detalles

Ejercicio 18. Configuración de Widgets en Android. Android Con Java. Ejercicio 18. Configuración de Widgets en Android. Curso de Android con Java

Ejercicio 18. Configuración de Widgets en Android. Android Con Java. Ejercicio 18. Configuración de Widgets en Android. Curso de Android con Java Android Con Java Ejercicio 18 Configuración de Widgets en Android Objetivo del Ejercicio El objetivo del ejercicio crear un Widget que antes de utilizarlo nos permita configurarlo. En este caso, solicitar

Más detalles

Guía rápida para el Uso de Evaluación Modular Q10 Académico, desde un Perfil Docente

Guía rápida para el Uso de Evaluación Modular Q10 Académico, desde un Perfil Docente Guía rápida para el Uso de Evaluación Modular Q10 Académico, desde un Perfil Docente http://capeco.edu.pe Guía Rápida para el uso de Evaluación Modular Q10 Académico, desde un Perfil Docente RECOMENDACIONES

Más detalles

Instituto Tecnológico de Las América. Materia Sistemas operativos III. Temas Creación de una Distro. Facilitador José Doñe

Instituto Tecnológico de Las América. Materia Sistemas operativos III. Temas Creación de una Distro. Facilitador José Doñe Instituto Tecnológico de Las América Materia Sistemas operativos III Temas Creación de una Distro Facilitador José Doñe Sustentante Robín Bienvenido Disla Ramirez Matricula 2011-2505 Grupo 1 Creación de

Más detalles

Base de Datos. Formularios. Consultas

Base de Datos. Formularios. Consultas Base de Datos y programa de Microsoft Access Definición Tablas Formularios Consultas Informes 1 BASE DE DATOS. DEFINICIÓN Y PLANIFICACIÓN Qué es una base de datos? Una base de datos es una serie de datos

Más detalles

TEMA 2: Sistemas Operativos

TEMA 2: Sistemas Operativos TEMA 2: Sistemas Operativos 2.1. QUÉ ES UN SISTEMA OPERATIVO? Un sistema operativo es un conjunto de programas encargados de gestionar los recursos del ordenador y que permiten la comunicación del usuario

Más detalles

CÓMO HACER. TU ACTUALIZACIÓN ios 7

CÓMO HACER. TU ACTUALIZACIÓN ios 7 CÓMO HACER TU ACTUALIZACIÓN ios 7 CÓMO HACER TU ACTUALIZACIÓN ios 7 Esta breve guía te ayudará a llevar a cabo la instalación de ios 7 con éxito en todos tus ipads. Te recomendamos seguir los pasos al

Más detalles

Manual de usuario de configuración de Navegadores para Sede Electrónica del SEPE

Manual de usuario de configuración de Navegadores para Sede Electrónica del SEPE Manual de usuario de configuración de Navegadores para Sede Electrónica del SEPE V4.2 Octubre de 2015 Ver. 4.0 Página 1 de 40 C/ Condesa de Venadito 9 Índice 1. OBJETIVOS... 3 2. REQUISITOS GENERALES...

Más detalles

INSTALACIÓN JDK. Guillermo Figueroa

INSTALACIÓN JDK. Guillermo Figueroa INSTALACIÓN JDK Guillermo Figueroa CONTENIDO Descarga JDK Definición de la variable de entorno Descarga API Java Tutorial MS-DOS Tutorial Jcreator DESCARGA JDK Para descargar el JDK(Java Development Kit)

Más detalles

UNA GUÍA PASO A PASO SOBRE CÓMO PUBLICAR EN OJS

UNA GUÍA PASO A PASO SOBRE CÓMO PUBLICAR EN OJS DESCRIPCIÓN BREVE En esta guía podrá conocer los fundamentos de la plataforma OJS y los pasos necesarios para publicar un número de revista sin seguir todo el proceso editorial. UNA GUÍA Servicio de Publicaciones

Más detalles

Universidad Tecnológica de los Andes. Ing. Hesmeralda Rojas Enriquez [GUÍA RATIONAL ROSE] Usando UML

Universidad Tecnológica de los Andes. Ing. Hesmeralda Rojas Enriquez [GUÍA RATIONAL ROSE] Usando UML 2011 Universidad Tecnológica de los Andes Ing. Hesmeralda Rojas Enriquez [GUÍA RATIONAL ROSE] Usando UML Tabla de Contenidos 1. Crear paquetes... 3 2. Crear casos de uso del sistema.... 4 3. Diagrama Global

Más detalles

1. Introducción Generalidades Configuración del Equipo Instalación de Java... 3

1. Introducción Generalidades Configuración del Equipo Instalación de Java... 3 Ú CONTENIDO 1. Introducción... 2 2. Generalidades... 2 3. Configuración del Equipo... 3 3.1 Instalación de Java... 3 3.2 Instalación de la aplicación AutoFirma... 12 3.3 Desarrollo de un proceso de firma

Más detalles