Está en la página 1de 177

Programacin de Dispositivos Mviles

ndice.
Introduccin-----------------------------------------------------------------------------------------------------------------------------------------------------------------3 Qu es un dispositivo mvil?------------------------------------------------------------------------------------------------------------------------------------------3 Historia de los dispositivos mviles------------------------------------------------------------------------------------------------------------------------------------3 Uniad 1. Tipos de dispositivos mviles-------------------------------------------------------------------------------------------------------------------------------------------6 Plataformas y lenguajes--------------------------------------------------------------------------------------------------------------------------------------------------8 Herramientas de desarrollo----------------------------------------------------------------------------------------------------------------------------------------------15 Consideraciones sobre el desarrollo. Limitaciones----------------------------------------------------------------------------------------------------------------16 Usos actuales---------------------------------------------------------------------------------------------------------------------------------------------------------------17 Perspectivas del futuro---------------------------------------------------------------------------------------------------------------------------------------------------19 Cronograma-----------------------------------------------------------------------------------------------------------------------------------------------------------------20 Unidad 2. Introduccin-----------------------------------------------------------------------------------------------------------------------------------------------------------------23 Coneptos bsicos de C#-------------------------------------------------------------------------------------------------------------------------------------------------23 Mostrar nmeros en pantalla--------------------------------------------------------------------------------------------------------------------------------------------24 Variables---------------------------------------------------------------------------------------------------------------------------------------------------------------------25 Identificadores--------------------------------------------------------------------------------------------------------------------------------------------------------------27 Comentario------------------------------------------------------------------------------------------------------------------------------------------------------------------27 Datos por el usuario: ReadLine----------------------------------------------------------------------------------------------------------------------------------------28 Tipos de datos bsico----------------------------------------------------------------------------------------------------------------------------------------------------29 Tipos de datos caracter--------------------------------------------------------------------------------------------------------------------------------------------------32 Secuencia de escape-----------------------------------------------------------------------------------------------------------------------------------------------------33 Toma de contacto con las cadenas de texto------------------------------------------------------------------------------------------------------------------------34 Los valores booleanos----------------------------------------------------------------------------------------------------------------------------------------------------34 If--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------35 Switch-------------------------------------------------------------------------------------------------------------------------------------------------------------------------41 While--------------------------------------------------------------------------------------------------------------------------------------------------------------------------42 Dowhile--------------------------------------------------------------------------------------------------------------------------------------------------------------------43 For-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------45 Sentencia Break------------------------------------------------------------------------------------------------------------------------------------------------------------47 Sentencia continue--------------------------------------------------------------------------------------------------------------------------------------------------------48 Sentencia goto--------------------------------------------------------------------------------------------------------------------------------------------------------------48 Array y cadena de texto--------------------------------------------------------------------------------------------------------------------------------------------------49 Estructuras o registros----------------------------------------------------------------------------------------------------------------------------------------------------54 Cadena de caracteres----------------------------------------------------------------------------------------------------------------------------------------------------56 Recorriendo con foreach-------------------------------------------------------------------------------------------------------------------------------------------------61 Ordenaciones simples----------------------------------------------------------------------------------------------------------------------------------------------------63 Funciones--------------------------------------------------------------------------------------------------------------------------------------------------------------------66 Variables locales y variables globales--------------------------------------------------------------------------------------------------------------------------------70 Algunas funciones tiles-------------------------------------------------------------------------------------------------------------------------------------------------74 Funciones matemticas--------------------------------------------------------------------------------------------------------------------------------------------------75

-3-

Programacin de Dispositivos Mviles

Recursividad----------------------------------------------------------------------------------------------------------------------------------------------------------------76 Parametros de retorno de Main--------------------------------------------------------------------------------------------------------------------------------------76 Programacin orientada a objetos-------------------------------------------------------------------------------------------------------------------------------------78 Objetos y clases en C#---------------------------------------------------------------------------------------------------------------------------------------------------78 La herencia. Visibilidad---------------------------------------------------------------------------------------------------------------------------------------------------80 Cmo se disean las clases?-----------------------------------------------------------------------------------------------------------------------------------------83 La palabra static----------------------------------------------------------------------------------------------------------------------------------------------------------83 Constructores---------------------------------------------------------------------------------------------------------------------------------------------------------------84 Polimorfismo y sobrecarga----------------------------------------------------------------------------------------------------------------------------------------------86 Array de objetos------------------------------------------------------------------------------------------------------------------------------------------------------------88 Funciones virtuales. La palabra override---------------------------------------------------------------------------------------------------------------------------90 Llamada a un mtodo de la clase padre---------------------------------------------------------------------------------------------------------------------------94 Sobrecarga de operadores----------------------------------------------------------------------------------------------------------------------------------------------95 Windows Mobile 5.0 (aplicable a Windows Mobile 6.5)----------------------------------------------------------------------------------------------------------96 Uso de Visual Studio 2005----------------------------------------------------------------------------------------------------------------------------------------------96 Controles en Compact Framework------------------------------------------------------------------------------------------------------------------------------------102 Trabajo con los controladores------------------------------------------------------------------------------------------------------------------------------------------107 Trabajando con imgenes-----------------------------------------------------------------------------------------------------------------------------------------------113 ADO.NET Acceso a Datos--------------------------------------------------------------------------------------------------------------------------------------------122 SQL Server 2005 Mobile Edition---------------------------------------------------------------------------------------------------------------------------------------123 Captura de datos-----------------------------------------------------------------------------------------------------------------------------------------------------------150 Insertar datos---------------------------------------------------------------------------------------------------------------------------------------------------------------152 Cambiar datos--------------------------------------------------------------------------------------------------------------------------------------------------------------154 Borrar datos-----------------------------------------------------------------------------------------------------------------------------------------------------------------156 Sincronizacin de datos--------------------------------------------------------------------------------------------------------------------------------------------------158 Empaquetado y desplegado--------------------------------------------------------------------------------------------------------------------------------------------169 Bibliografia-------------------------------------------------------------------------------------------------------------------------------------------------------------------175

-4-

Programacin de Dispositivos Mviles

Introduccin.
Desde la aparicin de la primera computadora comercial en 1980, el hombre ha intentado llevar consigo toda la informacin posible que le ayude a resolver sus problemas conforme se le vayan presentando durante el da, pero en ese tiempo era imposible por no contar con la tecnologa necesaria para ello.

Qu es un dispositivo mvil?
Los dispositivos mviles (tambin conocidos como computadora de mano, Palmtop o simplemente handheld) son aparatos de pequeo tamao, con algunas capacidades de procesamiento, mviles o no, con conexin permanente o intermitente a una red, con memoria limitada, diseados especficamente para una funcin, pero que pueden llevar a cabo otras funciones ms generales. Normalmente, son versiones limitadas en prestaciones, y por tanto en funcionalidades, de las computadoras porttiles o de sobremesa. Por cierto, las computadoras porttiles no se consideran como dispositivos mviles, ya que consumen ms batera y suelen ser un poco ms pesados de lo que se espera de algo pensado para llevar siempre encima. Un dispositivo mvil, entonces, es todo aquel aparato que pueda contener informacin, tenga un sistema operativo y haga una funcin en particular en la que se necesita almacenar, consultar y manipular informacin que se encuentre en el y que adems sea portable y de un tamao muy reducido.

Historia de los dispositivos mviles


El primer dispositivo mvil, para muchos, es la Newton, desarrollada y comercializada por Apple, y que estuvo a la venta entre 1993 y 1998. La Newton era un dispositivo revolucionario para su tiempo, que implementaba un sistema de reconocimiento de escritura y que poda sincronizarse con una computadora de sobremesa (de Apple, claro est). Fue tan revolucionaria, y se adelant tanto a su tiempo, que fue un fracaso comercial, por lo que termin retirndose del mercado. Panel de control de la Newton Pero aunque la Newton pueda considerarse como la primera PDA, desde luego no fue el primer dispositivo porttil programable. Durante los aos 80, tanto Casio como Hewlett-Packard desarrollaron y comercializaron varias calculadoras programables, que si bien no tenan la capacidad de sincronizar sus datos con una computadora de sobremesa, s tenan capacidades grficas, y accesorios que tal vez puedan sonar extravagantes ahora, como impresoras, o tarjetas de memoria extrables de 1Kb (s, un "k"). Sirva como ejemplo la Casio FX-750P, de la que el autor de este texto conserva un ejemplar que funciona desde el ao 1984, que tena una pantalla de una sola lnea, con 32 caracteres de 5x7 puntos, teclado QWERTY y teclado numrico, 4 KB de RAM, dos ranuras para tarjetas de memoria extrables de hasta 2 KB, y puerto serie por el que conectarla a una impresora. Y era programable en BASIC. Especificaciones de risa, verdad? No tanto, si se tiene en cuenta que la configuracin CLDC de J2ME slo obliga a que el telfono tenga 4KB de memoria, y que muchos de los mviles pre-Symbian tienen una memoria de 32 KB. Ms adelante veremos con un poco ms de detalle qu es eso de J2ME, y qu es la configuracin CLDC, pero por ahora basta con saber que es la especificacin que deben cumplir los mviles programables en java.

Casio FX-750P Las calculadoras programables de Casio rivalizaban en prestaciones con las de Hewlett-Packard. Si la FX-750P podra considerarse como el buque insignia de la marca japonesa, la serie HP48 lo era para los californianos. Las calculadores de esta serie, que se dividan en dos ramas, la S para los modelos estndar y la G para los de mayor funcionalidad, estuvo en produccin entre los aos 1990 y 2003. Las especificaciones comunes a todos los modelos de la gama eran una pantalla de 131x63 pxeles, un puerto de comunicaciones por infrarrojos y otro serie de 4 pines, y 512 KB de memoria. El modelo ms alto de la gama, la HP 48GX, soportaba dos tarjetas de expansin de memoria, de forma que se poda llegar a acumular un total de 5MB. HP 48G Tras la muerte de la Newton, nacieron los dos dispositivos que durante unos aos dominaron el mercado: la Pilot y el PocketPC. Los dispositivos de Palm se adelantaron a los de Microsoft en un par de aos. En parte por ello, su salida a produccin fue un xito de ventas, llegando incluso a acumular, en 2001, un 60 por ciento del mercado americano. Sin embargo, Palm se resinti del declive global del mercado de las PDA, comenzando un declive que coincidi prcticamente en el tiempo con la entrada en el mercado del gigante de la informtica de consumo: Microsoft.

-5-

Programacin de Dispositivos Mviles

Grafitti, el sistema de reconocimiento de caracteres de Palm OS, obligaba a escribir de forma determinada. En el ao 2000 vio la luz el primer PocketPC, el hijo de la Newton, y que al contrario que sta, s ha sobrevivido hasta hoy, pese a no ser un xito comercial de grandes dimensiones, gracias a la continuidad y el apoyo decidido de Microsoft. Los primeros PocketPC tenan como sistema operativo el llamado Windows CE 3.0. Por su nombre podra parecer que era una versin aligerada del sistema operativo ms utilizado en el mundo, pero en realidad no tena mucho que ver con ste. Compaq iPaq 3630, el primer PocketPC de xito La mayor razn para el xito del PocketPC ha sido su relativa sencillez de manejo y su integracin con computadoras de escritorio basados en Windows. La integracin es tal que para realizar una sincronizacin entre ambos basta con conectar el PocketPC a la computadora con un cable. Actualmente, los PocketPC y las Palm tienen pantallas de resolucin VGA, en prcticamente todos los casos incorporan protocolos de comunicaciones inalmbricos, como Bluetooth o Wifi, o unidades de GPS. Por prestaciones, son, sin duda, los hermanos mayores del mundo de la movilidad. Pero si las PDAs son las reinas en lo referente a prestaciones, en cuanto a unidades en el mercado, el rey indiscutible es el telfono mvil. Quin no tiene un telfono mvil? En realidad, lo raro es que haya quien no tenga un telfono totalmente funcional guardado en un cajn, porque se ha comprado otro que, en el plazo de unos meses, multiplicaba por diez o por cien las prestaciones de su antiguo terminal. Si la Newton, la Palm y el PocketPC han sido los que han abierto el camino, los que realmente han entrado con toda la fuerza posible a ocupar ese mercado han sido los telfonos mviles. Pero cul es el motivo o los motivos para que haya tantos telfonos? Es difcil de decir con total seguridad, pero se puede resumir principalmente en tres.

Motorola MicroTAC En primer lugar, el precio. Se pueden conseguir terminales por cero euros en ocasiones excepcionales, como al darse de alta con algn operador, pero en todo caso los precios de los telfonos de gama baja suele ser bastante asequible. El segundo factor es ms complejo, pero puede resumirse en mira lo moderno que soy, qu mvil tengo". Hay quien lo llama techno-lust, hay quien lo llama ganas de aparentar o de chulear a las amistades, pero bsicamente se resume en que todo el mundo quiere tener el

-6-

Programacin de Dispositivos Mviles

mvil ms moderno y con ms funcionalidades, sobre todo si es ms moderno y hace ms cosas que el del vecino. Esa obligacin por tener el dispositivo ms moderno viene motivada tambin en parte por la continua mejora de la tecnologa. Cada vez los mviles pueden hacer ms cosas, y eso crea una doble necesidad. Por un lado, es necesario tener un dispositivo que permita hacer esas cosas, sean las que sean (grabar vdeo, escuchar mp3, ver los goles de tu equipo favorito en tiempo real). Pero eso tambin provoca que cada vez se intenten hacer ms cosas con el telfono, lo que vuelve a hacer necesario un terminal ms potente, que a su vez crear la necesidad de contenidos de ms calidad, lo que a su vez... Esto supone nuestro tercer factor: un crculo vicioso para el usuario pero que beneficia por igual a los fabricantes y a las operadoras. Sin embargo, los mviles que verdaderamente pueden considerarse equivalentes a las PDAs son los de gama alta, o smartphones. El trmino smartphone es engaoso. Su traduccin literal sera telfonos inteligentes, y se utiliza indiscriminadamente para hacer referencia a cualquier telfono de gama alta, englobando tanto a dispositivos de la Serie 60 o superior de Symbian, como a los que funcionan bajo Windows Mobile o bajo Palm OS. De todas formas, la marca comercial SmartPhone es propiedad de Microsoft.

Sony Ericsson P910i Porque, efectivamente, hay una lnea de telfonos que funcionan bajo Windows Mobile. Por un lado, los PocketPC Phone Edition, que son hbridos de telfono y PocketPC y por otro los llamados comercialmente SmartPhones. La diferencia entre ambos est, fundamentalmente, en la pantalla tctil. Los PocketPC Phone Edition tienen, mientras que los SmartPhones no, y que se manejan de forma similar a los mviles Symbian de gama alta. Tanto PocketPC Phone Edition como PocketPC se engloban dentro de la gama Windows Mobile de Microsoft.2 Tambin Palm mantiene su irreductible nicho de mercado dentro de los telfonos de gama alta: la serie Treo. Los Treo son hbridos de telfono y PDA, con teclado QWERTY, y funcionan, salvo uno de los modelos (en concreto el Treo 700w, que utiliza PocketPC Phone Edition) bajo PalmOS.

Treo 700w En todo caso, el mercado de los telfonos de gama alta estaba copado, hasta hace muy poco, por los modelos con sistema Symbian. Sin embargo, en los ltimos dos aos hemos asistido a la irrupcin del representante por excelencia del techno-lust el iPhone de Apple. Si Apple fue la que abri el camino con la Newton, es el que ha vuelto a revolucionar el mercado con el iPhone, en parte porque ha sido el nico fabricante que realmente ha conseguido desarrollar un dispositivo que integrara a todos los anteriores existentes por separado (telfono, reproductor mp3 y PDA), reinventando la forma en la que se interacta con l.

-7-

Programacin de Dispositivos Mviles

Unidad 1
Manejo del entorno de desarrollo mvil
El alumno har uso de la tecnologa mvil, herramientas de la plataforma y tcnicas necesarias que permitan la construccin e implementacin de desarrollo de programacin de aplicaciones para ejecutarse en dispositivos mviles.

1.1 Diferencia las caractersticas de los dispositivos mviles y la plataforma de desarrollo con base en tecnologas y herramientas para aplicaciones mviles. Tipos de dispositivos mviles.
Dado el variado nmero de niveles de funcionalidad asociado con dispositivos mviles, era necesario hacer una clasificacin de los mismos, por ello en el 2005, T38 y DuPont Global Mobility Innovation Team propusieron los siguientes estndares para la definicin de dispositivos mviles. Dispositivo Mvil de Datos Limitados (Limited Data Mobile Device): telfonos mviles clsicos. Se caracterizan por tener un pantalla pequea de tipo texto. Ofrecen servicios de datos generalmente limitados a SMS y acceso WAP. Dispositivo Mvil de Datos Bsicos (Basic Data Mobile Device): se caracterizan por tener una pantalla de mediano tamao, men o navegacin basada en iconos, y ofrecer acceso a emails, lista de direcciones, SMS, y, en algunos casos, un navegador web bsico. Un tpico ejemplo de este tipo de dispositivos son los telfonos inteligentes (smartphones). Dispositivo Mvil de Datos Mejorados (Enhanced Data Mobile Device): se caracterizan por tener pantallas de medianas a grandes (por encima de los 240 x 120 pixels), navegacin de tipo stylus, y que ofrecen las mismas caractersticas que el "Dispositivo Mvil de Datos Bsicos" (Basic Data Mobile Devices) ms aplicaciones nativas como aplicaciones de Microsoft Office Mobile (Word, Excel, PowerPoint) y aplicaciones corporativas usuales, en versin mvil, como Sap, portales intranet, etc. Este tipo de dispositivos incluyen los S.O. como Windows Mobile.

A grandes rasgos, y dependiendo del tamao los dispositivos se pueden dividir en tres clases. 1.- Telfonos. Son los ms pequeos de la casa, y por tanto los ms ligeros y ms transportables. En general, tambin son los ms baratos, aunque un telfono de gama alta puede superar en precio a muchos de sus hermanos mayores, las PDAs. Su funcin primordial era clara: recibir y realizar llamadas; aunque parece que dentro de poco va a comenzar a ser complicado encontrar telfono que sirvan para eso. Funcionalidades propias de computadoras, o de dispositivos de otro tipo, como la grabacin y edicin de vdeo, realizacin de fotografas, lectura de documentos, localizacin en mapas, navegacin por Internet, y muchas cosas ms, son no slo habituales, sino esperadas en cualquier telfono moderno. El telfono mvil es un dispositivo inalmbrico electrnico basado en la tecnologa de ondas de radio, que tiene la misma funcionalidad que cualquier telfono de lnea fija. Su principal caracterstica es su portabilidad, ya que la realizacin de llamadas no es dependiente de ningn terminal fijo y no requiere ningn tipo de cableado para llevar a cabo la conexin a la red telefnica. Aunque su principal funcin es la comunicacin de voz, como el telfono convencional, su rpido desarrollo ha incorporado funciones adicionales como mensajera instantnea (sms), agenda, juegos, cmara fotogrfica, agenda, acceso a Internet, reproduccin de video e incluso GPS y reproductor mp3.

Motorola DynaTAC 8000X, uno de los primeros telfonos mviles fabricados en gran cantidad. La evolucin del telfono mvil ha permitido disminuir su tamao y peso, desde el Motorola DynaTAC, el primer telfono mvil en 1983 que pesaba 780 gramos, a los actuales ms compactos y con mayores prestaciones de servicio. Adems a lo largo de estos aos se ha llevado a cabo el desarrollo de bateras ms pequeas y de mayor duracin, pantallas ms ntidas y de colores, la incorporacin de software ms amigable.

-8-

Programacin de Dispositivos Mviles

Inicialmente los telfonos mviles slo permitan realizar llamadas de voz y enviar mensajes de texto. Conforme la tecnologa fue avanzando se incluyeron nuevas aplicaciones como juegos, alarma, calculadora y acceso WAP (acceso a Internet mediante pginas web especialmente diseadas para mviles). Smartphones o telfonos inteligentes. Un smartphone (telfono inteligente en espaol) es un dispositivo electrnico que funciona como un telfono mvil con caractersticas similares a las de una computadora personal. Es un elemento a medio camino entre un telfono mvil clsico y una PDA ya que permite hacer llamadas y enviar mensajes de texto como un mvil convencional pero adems incluye caractersticas cercanas a las de una computadora personal. Una caracterstica importante de casi todos los telfonos inteligentes es que permiten la instalacin de programas para incrementar el procesamiento de datos y la conectividad. Estas aplicaciones pueden ser desarrolladas por el fabricante del dispositivo, por el operador o por un tercero. Los telfonos inteligentes se distinguen por muchas caractersticas, entre las que destacan las pantallas tctiles, un sistema operativo as como la conectividad a Internet y el acceso al correo electrnico. El completo soporte al correo electrnico parece ser una caracterstica indispensable encontrada en todos los modelos existentes y anunciados en 2007, 2008 y 2009. Otras aplicaciones que suelen estar presentes son las cmaras integradas, la administracin de contactos, el software multimedia para reproduccin de msica y visualizacin de fotos y video-clips y algunos programas de navegacin as como, ocasionalmente, la habilidad de leer documentos de negocios en variedad de formatos como PDF y Microsoft Office. Una caracterstica comn a la mayora de smartphones es una lista de contactos capaz de almacenar tantos contactos como la memoria libre permita, en contraste con los telfonos clsicos que tienen un lmite para el nmero mximo de contactos que pueden ser almacenados. Casi todos los telfonos inteligentes tambin permiten al usuario instalar programas adicionales. 2.- PDAs. Organizadores electrnicos o computadoras de mano. Su nombre (PDA) significa Personal Digital Assistant (asistente personal digital), un trmino acuado en sus primeros aos de historia, pero que resume bien su funcionalidad principal, que es servir como organizadores, con agenda, calendario, gestin de contactos, y que posteriormente han ido creciendo, de forma que actualmente sirven tanto como aparatos en los que leer un libro como en los que encontrarse en un mapa. La lnea que los separa de los telfonos es cada vez ms difusa.

Apple Newton MessagePad 2000 Inicialmente los PDAs incluan aplicaciones estrictamente relacionadas con su funcin como agenda electrnica, es decir, se reducan a calendario, lista de contactos, bloc de notas y recordatorios. Con el paso de tiempo han ido evolucionando hasta los dispositivos actuales que ofertan un rango mucho ms extendido de aplicaciones, como juegos, acceso al correo electrnico o la posibilidad de ver pelculas, crear documentos, navegar por Internet o reproducir archivos de audio. Las caractersticas del PDA moderno son pantalla sensible al tacto, conexin a una computadora para sincronizacin, ranura para tarjeta de memoria, y al menos Infrarrojo, Bluetooth o WiFi. La irrupcin de Microsoft Windows CE (2000) y Windows Mobile (2003) en el sector los dot de mayores capacidades multimedia y conectividad. Las PDAs de hoy en da traen multitud de comunicaciones inalmbricas (Bluetooth, WiFi, IrDA, GPS,) que los hace tremendamente atractivos hasta para cosas tan inverosmiles como su uso para domtica o como navegadores GPS. 3.- Consolas. En realidad esta categora debera llamarse dispositivos orientados a jugar, porque son ms que simples consolas. Los dos ejemplos actualmente en el mercado son la Sony PlayStation Portable (PSP) y la Nintendo DS, que no slo sirven para jugar, sino que integran algunas de las funcionalidades tpicas de una PDA, como reproduccin de archivos multimedia, integracin con agenda y calendario, o navegador de Internet.

PSP

-9-

Programacin de Dispositivos Mviles

El mercado del videojuego porttil ha sufrido muchas transformaciones a lo largo de su historia. Partiendo de videojuegos electrnicos porttiles y experimentos poco exitosos de Videoconsolas porttiles a finales de los 70 y principios de los 80, pero que sentaron las bases de las futuras generaciones porttiles y el nuevo milenio donde las consolas porttiles son verdaderos centros multimedia. El sector de los videojuegos porttiles ha tenido dos pocas lgidas, en torno a la cuarta generacin de consolas de sobremesa cuando las porttiles suponan un 17% del mercado de los videojuegos, y vive su mximo auge en la sptima generacin de consolas suponiendo el 56% del mercado del videojuego de esa generacin.

Plataformas y lenguajes soportados.


Cada una de las plataformas tiene sus particularidades, no slo en cuanto al manejo del dispositivo por el usuario, sino tambin a la hora de desarrollar aplicaciones para las mismas. No ser lo mismo programar una aplicacin para Windows Mobile que para Symbian, entre otras cosas porque no todas las plataformas soportan los mismos lenguajes de programacin. Partiendo de la definicin de sistema operativo: Capa compleja entre el hardware y el usuario, concebible tambin como una mquina virtual, que facilita al usuario o al programador las herramientas e interfaces adecuadas para realizar sus tareas informticas, abstrayndole de los complicados procesos necesarios para llevarlas a cabo. Podemos deducir que el uso de uno u otro S.O determinarn las capacidades multimedia de los dispositivos, y la forma de stas de interactuar con el usuario. Existen multitud de opciones, si bien las ms extendidas son Symbian, BlackBerry OS, Windows Mobile, y recientemente iPhone OS y el sistema mvil de Google, Android, adems por supuesto de los dispositivos con sistema operativo Linux. Las caractersticas bsicas de cada uno son las siguientes:

Windows Mobile
Microsoft lanz su propio Windows para mviles, antes conocido como Windows CE o Pocket PC, tiene una larga historia como segundn en el campo de los PDA o computadoras de bolsillo, sin embargo hace pocos meses super por primera vez al hasta entonces lder, Palm OS. Windows Mobile es un sistema operativo escrito desde 0 y que hace uso de algunas convenciones de la interfaz de usuario del Windows de siempre. Una de las ventajas de Windows Mobile sobre sus competidores es que los programadores pueden desarrollar aplicaciones para mviles utilizando los mismos lenguajes y entornos que emplean con Windows para PC. En comparacin, las aplicaciones para Symbian necesitan ms esfuerzo de desarrollo, aunque tambin estn optimizadas para cada modelo de telfono.

Pantalla de inicio tpica de Windows Mobile 6 Este sistema se pretende vender como una versin muy aligerada de Windows, pero en realidad no tiene mucho que ver con l. El paradigma de funcionamiento es similar, basado en ventanas, aunque stas se comportan de forma muy diferente a como lo hacen en su hermano mayor de escritorio. Por ejemplo, al cerrar la ventana de un programa ste no se cierra realmente, sino que se sigue ejecutando como si se hubiera minimizado. El punto fuerte de estos dispositivos es que ofrecen funcionalidades similares a las de sus hermanos mayores, Por ejemplo, se pueden editar documentos de word, hojas de clculo de excel, leer libros en formato pdf o chm, recibir y enviar correo electrnico, manejar una agenda, la libreta de contactos, sincronizar datos con el PC, navegar por internet, utilizar un GPS... en definitiva, casi lo mismo que en un PC, pero sin teclado y con la pantalla bastante pequea.

- 10 -

Programacin de Dispositivos Mviles

Versin para Windows Mobile de Microsoft Word La entrada de datos se realiza a travs de la pantalla, que es tctil, y gracias al sistema de reconocimiento de escritura que implementan, que permite trabajar de una forma bastante natural y rpida. La mayora de las aplicaciones para estos dispositivos se desarrollan en .Net, la plataforma de desarrollo de Microsoft, o directamente en C++, aunque an quedan, como reminiscencia de sus inicios como Windows CE, algunas aplicaciones escritas en Embedded C++ o Embedded Basic, que eran dos entornos de desarrollo basados respectivamente en C++ y Basic, pero con muchas limitaciones. Pero en la actualidad casi todos los desarrollos para Windows Mobile se realizan en C++ o en .Net, basndose en el Compact Framework. El principal problema a la hora de desarrollar aplicaciones para estos dispositivos es el precio de las herramientas de desarrollo. Estas herramientas (Visual Studio, un entorno de desarrollo que soporta varios lenguajes como C#, C++, J#, JScript o ASP .Net) son de altsima calidad, pero de un precio que no est al alcance de todos los que se quieran aventurar a escribir una aplicacin para PocketPC. Por otra parte, el hecho de que Microsoft est detrs de la plataforma, dndole todo su apoyo, se nota en la cantidad y la calidad de la documentacin disponible para los desarrolladores. Newsletters, una seccin slo para dispositivos en el MSDN, blogs de los ingenieros de Microsoft que trabajan en Windows Mobile, actualizaciones de la documentacin en DVDs peridicos... en resumen, mucho y muy bueno. Tal vez por eso mismo, y pese al precio del entorno de desarrollo, la competencia es muy alta.Hay muchas compaas que producen aplicaciones para Windows Mobile, y que invierten mucho dinero en su desarrollo. No es, por tanto, un nicho de mercado en el que sea sencillo introducirse. En cualquier caso, siempre que se vaya a desarrollar aplicaciones para esta plataforma, deben tenerse en cuenta las limitaciones especficas de la misma, sobre todo a la hora de intentar desarrollar interfaces que sean lo ms point-and-click posibles, y que necesiten de la menor introduccin de textos posible.

Symbian
Si los PocketPC estn basados en un sistema operativo de Microsoft llamado Windows Mobile, la gran mayora de los telfonos mviles funcionan gracias a un sistema operativo llamado Symbian. Hace unos aos, a estos telfonos se les llamaba con el nombre genrico de SmartPhones. Este es el sistema operativo para mviles ms extendido entre smartphones, y por tanto el que ms aplicaciones para su sistema tiene desarrolladas. Actualmente Symbian copa ms del 65% del mercado de sistemas operativos. Symbian es un consorcio en el que participan los mayores fabricantes de telfonos mviles, con Nokia a la cabeza. Sony Ericsson, BenQ (que hace poco absorbi a Siemens), Fujitsu, Lenovo, Motorola, Panasonic, Samsung o Sharp estn representados en Symbian, y son por tanto, partcipes en el desarrollo y la expansin del sistema. De todos estos fabricantes, el que mayor cuota de mercado tiene es Nokia (que con algunas fluctuaciones, viene siendo desde hace aos de alrededor del 40%), que adems es el fabricante que primero apost por este sistema operativo, y el que ms uso hace de l. Por tanto, a partir de ahora, al referirme a telfonos Symbian, lo har sobre todo a telfonos Nokia. Symbian es un sistema operativo escrito en C++, por lo que presenta muy bajo consumo de recursos del dispositivo, a la vez que se ejecuta con gran rapidez. El sistema operativo Symbian se presenta en varios "sabores". En concreto, Nokia divide sus dispositivos Symbian en tres familias, que se llaman respectivamente Serie 40, Serie 60 y Serie 80. La Serie 40 es la que agrupa a los telfonos Symbian con pantallas ms pequeas (en general, hasta de 240x320 pxeles), y tiene ciertas limitaciones sobre las otras series, sobre todo en lo referente a la cantidad de recursos del telfono que puede poner a disposicin de las aplicaciones que se ejecuten sobre l.

- 11 -

Programacin de Dispositivos Mviles

La Serie 60 es la ms extendida, y es donde suelen estar los telfonos de gama media y alta de Nokia, a los que muchas veces se hace referencia como telfonos multimedia. Con alguna excepcin, suelen tener pantallas ms grandes que los de la serie 40, y suelen ser telfonos especficamente optimizados para ejecutar aplicaciones J2ME. Su principal virtud es la capacidad que tiene el sistema para adaptar e integrar todo tipo de aplicaciones. Admite la integracin de aplicaciones y, como sistema operativo, ofrece las rutinas, los protocolos de comunicacin, el control de archivos y los servicios para el correcto funcionamiento de estas aplicaciones. La tecnologa del sistema operativo Symbian se ha diseado teniendo en cuenta puntos clave como el poder proporcionar la energa, memoria y gestin de entrada y salida de recursos requeridos especficamente en los dispositivos mviles. Tambin, supone una plataforma abierta, sta es la clave, que ana telecomunicaciones y los estndares globales de internet. Los usuarios de Symbian sealan como principal ventaja del sistema el hecho de que exista una amplia seleccin de aplicaciones disponibles para todo tipo de telfonos mviles. Destacan tambin la compatibilidad con los estndares de conectividad y redes como Bluetooth, WiFi, GSM, GPRS, CDMA y WCDMA.

Captura de una interfaz Series 60 La Serie 80, finalmente, es la de los llamados Communicators, esos telfonos que se abren longitudinalmente y que esconden teclados QWERTY. En realidad son un paso intermedio entre el telfono y la PDA. Aparte de la implementacin que hace Nokia de Symbian, Sony Ericsson implementa otro sabor ms de ese sistema, llamado UIQ, que se maneja por teclado o a travs de una pantalla tctil. Estos dispositivos suelen implementar sistemas de reconocimiento de escritura, y los ms conocidos son, como he dicho, la serie P de Sony Ericsson. Actualmente, en el mercado de los telfonos mviles Symbian es el sistema ms extendido, aunque no el nico. La mayora de los fabricantes siguen implementando sus propios sistemas, por lo que sigue sin haber una uniformidad o coherencia entre dispositivos.

Symbian UIQ Las tres grandes posibilidades tecnolgicas a la hora de desarrollar aplicaciones para telfonos mviles son C++, J2ME y Flash Lite.

C++
Es el lenguaje de programacin por excelencia para aplicaciones que necesitan extraer el mximo del terminal, tanto en capacidad de procesamiento y por lo tanto en velocidad de ejecucin, como en utilizar las posibilidades de hardware que ofrezca el dispositivo. El ejemplo ms claro de aplicacin candidata a ser realizada en C++ sera un juego de conduccin, con capacidades multiusuario a travs de bluetooth. Es ideal, por tanto, para aplicaciones crticas (como por ejemplo, sistemas operativos para telfonos como Symbian). C++ es un lenguaje de programacin, de los que se llaman orientados a objetos, que en realidad es una evolucin del lenguaje ms utilizado en la historia de la informtica: el lenguaje C. Desarrollar en C++ es bastante complicado para casi cualquier programador. Hacen

- 12 -

Programacin de Dispositivos Mviles

falta, por tanto, programadores de un perfil muy especializado o muy alto, y el lenguaje en s no hace posible el desarrollo de aplicaciones con gran rapidez, con lo que los proyectos desarrollados en C++ suelen ser ms caros que aquellos producidos con otros lenguajes.

J2ME
J2ME es un subconjunto del lenguaje Java. Pero qu es el lenguaje Java? Es un lenguaje de programacin desarrollado a principios de los aos noventa por James Gosling y algunos de sus colegas de Sun Microsystems. Las principales caractersticas de este lenguaje son, por un lado, que es de los llamados orientados a objetos, lo que supuestamente permite desarrollar aplicaciones ms complejas con mayor facilidad, y por otro, que fue diseado para ser independiente de la plataforma, lo que supuso una gran novedad en su momento. Sin embargo, el caso de J2ME es especial, ya que es de todo, menos independiente de la plataforma. La especificacin J2ME est dividida en dos grandes grupos, dependiendo de la cantidad de funcionalidades para las que se quiera dar soporte. Esos grupos son las llamadas Configuraciones (en toda la documentacin sobre J2ME se suele hacer referencia a ellas por su nombre en ingls: Configurations). Hay dos configuraciones, que dividen la plataforma en dos grandes grupos de dispositivos.

El mapa con las configuraciones y perfiles J2ME. Lioso? Por un lado, los dispositivos ms potentes, son los que soportan la Configuracin CDC. Durante mucho tiempo en este grupo slo caban las PDAs (dispositivos como la Palm, por ejemplo), dadas las exigencias de memoria y tamao de pantalla para cumplir con la especificacin. La otra configuracin, la llamada CLDC, es la que agrupaba a los dispositivos con menor capacidad de procesamiento, y es donde siempre han estado los mviles. Actualmente, Nokia, el mayor fabricante de telfonos mviles, est en proceso de portar toda su gama de telfonos Symbian a la Configuracin CDC, un indicador ms de cmo el hardware va mejorando progresivamente en prestaciones. Dentro de cada una de las configuraciones, no todos los dispositivos soportan las mismas funcionalidades. stas est divididas en los llamados Perfiles (o en su nombre original, Profiles). Los dos perfiles de la CLDC son el MIDP 1.0 y el MIDP 2.0. Como podra suponerse, el perfil MIDP 2.0 incorpora libreras que no aparecen en los telfonos MIDP 1.0, con las que se pueden implementar aplicaciones que accedan a la cmara, que puedan capturar imgenes, vdeos, que accedan a servicios web, etc. Los dispositivos que se adhieran a la especificacin de cada uno de esos perfiles tienen que dar soporte a una serie de funcionalidades obligatoriamente. Esas funcionalidades vienen empaquetadas en lo que se llama especificaciones. Algunas de esas especificaciones son

- 13 -

Programacin de Dispositivos Mviles

obligatorias para poder decir que el dispositivo soporta uno u otro de los perfiles, mientras que otras son opcionales y pueden o no ser implementadas por el fabricante. Por ejemplo, un telfono que implemente grficos 3D deber hacerlo soportando la especificacin jsr-184. Pero por qu es todo tan complicado? Porqu es necesaria tanta especificacin, perfiles, etc?. Para asegurar un mnimo de compatibilidad entre dispositivos desarrollados por fabricantes dispares, y para asegurar al programador un mnimo comn denominador en el que su aplicacin funcione. En todo caso, la adhesin a una especificacin no asegura que las cosas funciones igual y bien en todo tipo de dispositivos, por eso es importante testear pronto y testear a menudo, y en el mayor nmero de dispositivos posibles. Adems, debe tenerse en cuenta que ninguna especificacin obliga a un tamao de pantalla determinado. Por tanto, hay que ser extremadamente cuidadoso en delegar la presentacin en pantalla en el propio dispositivo. Lo cual tampoco es necesariamente un problema, ya que la propia plataforma funciona as, dejando al dispositivo que sea el que pinte las cosas. Eso tiene como ventaja que si se hace bien, siempre saldr bien, y como inconveniente, que no se puede suponer que las aplicaciones se vayan a ver igual en dos telfonos distintos. Pero donde es ms importante esa limitacin es a la hora de desarrollar juegos, a que suelen ser a pantalla completa, y con elementos de interfaz propios, y en los que se suele buscar a toda costa la consistencia entre dispositivos. En todo caso J2ME es la plataforma de desarrollo para mviles ms extendida, porque no est limitada slo a los telfonos con sistema Symbian, porque durante mucho tiempo ha sido la nica disponible para los desarrolladores, y porque algunos aos en los que no ha sido la nica, programar en J2ME era la nica forma de implementar muchas funcionalidades. De hecho, an hoy, sigue siendo la plataforma ms extendida, con mayor nmero de desarrolladores, y con mayor nmero de aplicaciones disponibles.

Flash Lite
Flash Lite es un adaptacin de la plataforma Flash para dispositivos mviles. Actualmente coexisten varias versiones, Flash Lite 1.1, Flash Lite 2.0 y Flash Lite 2.0 Flash Lite 1.1, es la versin ms extendida, sobre todo en Asia, y basada en la versin 4 de player de flash. Y es la ms extendida por dos razones primordiales; en primer lugar porque es la que ms tiempo lleva disponible, y en segundo lugar porque es la que necesita de hardware menos potente para su ejecucin.

Emulador incorporado en Adobe Flash 8 Al estar basado en la versin 4 del player de flash, slo soporta la sintaxis de ActionScript de Flash 4, una sintaxis bastante extraa y alejada de las convenciones de programacin modernas. Esa forma de programar necesita de vinculaciones muy fuertes entre el cdigo y los grficos, por lo que es muy difcil que los desarrolladores que no estn acostumbrados a ella se puedan adaptar con facilidad. Adems, para desarrollar cualquier aplicacin con cierta interactividad, termina siendo necesario repartir el cdigo entre multitud de elementos grficos, por lo que la complejidad del desarrollo crece exponencialmente con la complejidad de la aplicacin. Por no hablar del coste de mantenimiento. Tampoco se pueden obviar las limitaciones propias de flash Lite 1.1. Por ejemplo, no se pueden guardar datos en la memoria del telfono, no es nada fcil cargar datos en tiempo de ejecucin, y directamente no es posible cargar imgenes, por ejemplo. Pese a todo, al igual que para crear aplicaciones complejas, Flash Lite 1.1 no es, desde luego, la mejor herramienta, s es ideal para realizar otro tipo de aplicaciones, como fondos de pantalla animados, salvapantallas, o incluso micro juegos muy sencillos. Por qu? Precisamente por estar basado en Flash 4, que permite desarrollar animaciones con interactividad sencilla en tiempos mucho menores que cualquier otra plataforma. Todo cambi, sin embargo, con la llegada de Flash Lite 2.0. En primer lugar, Flash Lite 2.0 est basado en el Flash Player 7. En realidad, la funcionalidad que permite es muy similar a la de cualquier aplicacin flash basada en esa versin del player. Por tanto, ahora es posible guardar datos en la memoria del telfono o cargar ficheros XML con estructuras de datos complejas a travs de la conexin GPS. Para el programador la mejora ha sido tambin sustancial, ya que puede aplicar las tcnicas modernas de programacin:

- 14 -

Programacin de Dispositivos Mviles

programacin orientada a objetos, patrones de diseo, aplicaciones dirigidas por eventos Ahora es posible desarrollar una aplicacin Flash Lite de la misma forma en la que se hara una J2ME, por ejemplo. Aunque las mejoras son sustanciales, tambin hay un aspecto en el que Flash Lite 2 cojea, y es los altos requerimientos de hardware que necesita para su ejecucin. Por ahora slo est disponible para telfonos de la gama alta de la Serie 60 de Nokia. Flash Lite 3 es la evolucin lgica de la plataforma, soporta vdeo incluyendo H.264, y un entorno de desarrollo rpido. Sin embargo, al menos en Asia, donde al menos en cuestin de dispositivos se est a la cabeza del desarrollo mundial, y por varios cuerpos de distancia, la implantacin de la plataforma es mnima.

iPhone OS
El iPhone, el ltimo en llegar, rompe tambin con las lneas maestras en cuanto a desarrollo se refiere, marcadas por sus antecesores. El sistema operativo utilizado es una versin aligerada de Mac OS X, el sistema detrs de las computadoras de Apple, y por tanto, las herramientas de desarrollo que se deben utilizar son las mismas que para trabajar en escritorio. Aunque oficialmente no se puede instalar ninguna aplicacin que no est firmada por Apple ya existen formas de hacerlo, la va oficial forma parte del iPhone Developer Program (de pago) y hay que descargar el SKD que es gratuito. iPhone dispone de un interfaz de usuario realmente interesante, la nica pega es la cantidad de restricciones que tiene, aunque quizs Apple se d cuenta que para triunfar mucho ms es mejor liberar y dar libertad a su sistema. Aunque su tiempo de vida es corto ya copa casi el 7% del mercado.

Objetive-C
El lenguaje que debe utilizarse para desarrollar aplicaciones nativas para iPhone OS es Objective-C, un superset de C (una especie de C enriquecido), de forma que el desarrollador se apoya en un extenso Framework orientado a objetos, escalable y altamente modular, llamado Cocoa. En realidad, Cocoa es una coleccin de frameworks, que proporcionan todas las piezas necesarias para construir una aplicacin: desde elementos de interfaz hasta gestin de trfico de red.

Una aplicacin para iPhone, casualmente desarrollada por el autor. Pese a lo modular y extenso de los frameworks, el mayor problema con el que se encuentran los recin llegados a la plataforma es que la curva de aprendizaje de Objective-C es bastante acusada. Especialmente si, adems, se viene de un entorno de desarrollo Windows, ya que no slo hay que cambiar de lenguaje, sino de forma de desarrollo por completo. Adems, para poder desarrollar aplicaciones para iPhone es necesario estar registrado (previo pago) como desarrollador con Apple, para as poder obtener los certificados digitales necesarios para que las aplicaciones funcionen en los dispositivos. Por si fuera poco, la nica forma de poner esas aplicaciones en esos dispositivos, es a travs de una tienda de aplicaciones controlada por Apple.

Blackberry OS
BlackBerry es un sistema operativo multitarea que est arrasando en la escena empresarial, en especial por sus servicios para correo y teclado QWERTY. Actualmente BlackBerry OS cuenta con un 11% del mercado. BlackBerry aparece en el mercado justo en el momento en que comenzaba a demandarse un sistema operativo que permitiera utilizar de una forma fcil, cmoda y rpida los servicios de correo electrnico. Hoy en da es tambin proveedor de servicios de correo electrnico a dispositivos que no son BlackBerry, gracias al programa BlackBerry Connect. As, en lneas generales, en un dispositivo BlackBerry es posible redactar, enviar y recibir todo tipo de mensajes de correo electrnico, al igual que en el programa que se utiliza en ua computadora. Adems, es posible realizar y contestar a las llamadas que se emitan a travs de la red de telefona mvil, lo que permite sustituir el

- 15 -

Programacin de Dispositivos Mviles

telfono mvil. Tambin, como evolucin lgica, los dispositivos de este fabricante permiten la navegacin por internet en pginas HTML o WAP y tienen la capacidad de enviar o recibir mensajes SMS. Por lo dems, este sistema operativo incorpora mltiples aplicaciones y programas que convierten a los dispositivos en completos organizadores de bolsillo con funciones de calendario, libreta de direcciones, bloc de notas, lista de tareas, entre otras.

Android
Android es un sistema operativo para telfonos, basado en el ncleo de Linux, y que, aunque disponible para cualquier fabricante como open-source, actualmente es el motor de los dispositivos comercializados por Google (en el momento de escribir este texto, slo existe un dispositivo, el conocido en Asia como HTC Dream, y en el resto del mundo como G1). Android tambin proporciona al desarrollador un completo Framework Java, un intento de normalizacin de la selva de especificaciones en que se ha convertido J2ME, que al igual que en el caso del iPhone, est orientado a facilitar y hacer ms rapido el desarrollo, por un lado, y a proporcionar un look and feel especfico y reconocible de la plataforma. Tambin se proporciona una tienda de aplicaciones, donde se pueden vender desarrollos comerciales. En este momento, an est por ver si la plataforma termina por alcanzar el momento suficiente como para terminar despegando. Google promete una plataforma de desarrollo gratuita, flexible, econmica en el desarrollo de aplicaciones y simple, diferenciada de los estndares que ofrecen Microsoft o Symbian.

Palm OS
Convertido en el autntico lder del mercado desde su aparicin en 1996, comenz a ceder protagonismo con la llegada del nuevo siglo, hasta que en 2003 el fabricante se vio en la necesidad de dividirse y la plataforma pas a formar parte de la nueva empresa denominada PalmSource, que en 2005 fue adquirida por la compaa japonesa Access. Los motivos de este retroceso en cuanto a ingresos de la compaa son fciles de imaginar, la lenta pero imparable penetracin de Windows Mobile, la evolucin de decenas de modelos de telfonos mviles inteligentes (la mayora con Symbian) y la aparicin de la plataforma y dispositivos BlackBerry comenzaron a dejar en segundo plano a las PDA que no incorporaban telefona mvil. Esta plataforma ha evolucionado desde la clsica interfaz de un asistente de mano, a incorporar todo tipo de programas y funcionalidades, como telfono, correo electrnico, mensajera y navegacin en internet, adems de compatibilidad con los archivos de Office, msica, vdeo y fotografas. En la actualidad ya se desarrollan dispositivos Palm Treo que incorporan el sistema operativo Windows Mobile. El sistema operativo Palm OS, parece que se encamina a su plena operabilidad en Linux, lo que le augura un futuro prometedor.

Comparativa
El Kernel de un sistema operativo es el ncleo del mismo, el software responsable de facilitar a los distintos programas acceso seguro a la computadora o, en forma ms bsica, es el encargado de gestionar recursos, a travs de servicios de llamada al sistema. Por ello, es importante conocer qu ncleo utiliza cada uno de los sistemas operativos de esta comparativa.

La principal diferencia entre un kernel de libre distribucin y uno propietario radica en que los de libre distribucin como Linux cuenta con una amplia y experimentada comunidad de desarrolladores, gracias a los cuales se detectan rpidamente agujeros de seguridad, fallos, etc. y se realizan mejoras tanto para solucionar estos problemas como para adaptarse a los nuevos tiempos. En cerrados o propietarios, es ms costoso encontrar errores y mejorarlos, ya que deben ser los propios desarrolladores del sistema los que detecten y realicen las mejoras, por lo que deben dedicarse ms recursos a investigacin en estos sistemas consiguiente aumento del coste del mismo.

Adaptabilidad. La capacidad o facilidad para poder adaptarlo a diferentes terminales o en diferentes mquinas. En este sentido, Android es el que mayor adaptabilidad presenta, ya que cada vez se est empleando en ms dispositivos, no slo telfonos mviles, sino tambin en netbooks y como sistema empotrado. En cambio el resto de sistemas operativos tienen una adaptabilidad algo menor y ms complicada.

- 16 -

Programacin de Dispositivos Mviles

Conectividad. Hoy en da, para poder sacar el mximo partido a todas las funcionalidades que ofrecen cada uno de ellos es indispensable contar con acceso a Internet. En este sentido, se valora enormemente el hecho de que cuenten con acceso WiFi a Internet, as como conectividad 3G que permitan conectarse a Internet desde cualquier lugar.

Actividad 1: Diferencia de plataformas


Distingue mediante una investigacin, las plataformas orientadas a desarrollo mvil donde considere: La descripcin de la arquitectura. Sistema operativo que utiliza. Lenguajes de Interfaces de servicios. Lenguajes de desarrollo y bibliotecas. Base de datos que soporta. Emuladores con los que cuenta. Elabora una tabla comparativa de cada plataforma encontrada donde plasme las diferencias. Presenta la tabla comparativa elaborada y emite un reporte de la actividad.

Actividad 2: Diferenciacin de dispositivos mviles y caractersticas de tipos de aplicaciones


Diferenciacin de Dispositivos Mviles Distingue mediante una investigacin los dispositivos mviles donde se pueda implementar una solucin, con base en: El tipo de sistema operativo que soporta. La base de datos que soporta. Diferenciacin de caractersticas de tipos de aplicaciones Distingue mediante una investigacin las caractersticas de los tipos y usos de aplicaciones mvil que se puedan implementar:

En Aplicaciones para conectividad con dispositivos presentes en red local o Internet describiendo: Cobertura de la red para obtener una comunicacin aceptable. Uso de Repositorio de datos locales. En Aplicaciones orientadas a dispositivos mviles seleccionando entre: - Sitio Web. - Aplicacin especfica para el aparato.

Elabora una tabla comparativa de cada dispositivo y aplicacin, anexando tambin las plataformas encontradas de la actividad anterior donde plasme las diferencias. Menciona tambin las conveniencias e inconveniencias del uso de cada dispositivo, aplicacin y plataforma en usos con equipos mviles Emite un reporte de la actividad realizada.

1.2 Utiliza el entorno de desarrollo de programacin mvil de acuerdo a los componentes y herramientas del lenguaje para la construccin de aplicaciones. Herramientas de desarrollo.
Las herramientas de desarrollo a utilizar dependern de la plataforma para la que hayas planteado tu aplicacin. Si tu aplicacin debe funcionar en dispositivos Windows Mobile, debers utilizar el Visual Studio de Microsoft, un entorno de desarrollo bastante caro, como ya hemos dicho, pero que es casi sin discusin el mejor de todos los disponibles, y para el que vas a contar con ms documentacin de la que puedas llegar a absorver. Debers basar tu aplicacin, o bien en cdigo C++ nativo, con lo que necesitars unos conocimientos tcnicos bastante elevados antes de comenzar el desarrollo, o bien apoyndote en el .Net Compact Framework, que es un subconjunto del .Net Framework, pudiendo programar en C#. Para dispositivos Symbian, la opcin ms extendida es, como hemos visto, J2ME. Las herramientas de desarrollo para J2ME no estn tan refinadas como las de Windows Mobile, pero an as, hay un entorno especfico, el NetBeans Mobility Pack, y plugins y add-ons para los IDES java ms populares: Eclipse e IDEA. Los tres entornos, una vez instalados los plugin correspondientes, permiten desarrollar, empaquetar y testear aplicaciones J2ME en los emuladores incorporados. Pero nunca debe olvidarse que los emuladores no son el dispositivo real, sino, como su nombre indica, emulaciones del dispositivo que estn corriendo en una mquina que es varios rdenes de magnitud ms rpida. Por tanto, lo que en un emulador funciona bien, puede que en el dispositivo no funcione tan bien.

- 17 -

Programacin de Dispositivos Mviles

Por eso, siempre que se desarrolle para un dispositivo mvil, pero sobre todo si se est haciendo en J2ME o Flash Lite, hay que probar los programas en el dispositivo segn se estn desarrollando. Y cuanto antes se empiece a probar, mejor, de esa forma los posibles problemas aflorarn antes, y sern ms fciles de resolver. En el caso del iPhone ser necesario un Mac con procesador Intel (no existe SDK para Windows ni para Linux), y aprender un lenguaje y una metodologa de desarrollo completamente nueva y, a da de hoy, no excesivamente documentada. Pero a la hora de decidir sobre la tecnologa a utilizar para desarrollar una aplicacin destinada a ser ejecutada en un dispositivo mvil, conviene preguntarse, entre otras, al menos un par de las siguientes preguntas: A quin va dirigida la aplicacin?. Es una aplicacin para todo tipo de usuarios, o es una aplicacin empresarial?. Los usuarios van a tener un entrenamiento especfico para manejarla? Se est desarrollando un juego o una aplicacin?. La diferencia es muy importante, sobre todo si es un juego, ms an si se toma en consideracin tambin la pregunta anterior. Dependiendo del tipo de usuario al que est dirigido se puede suponer el tipo de dispositivo para el que se deber hacer el desarrollo. Hay algn requerimiento previo?. Tal vez sea una pregunta obvia, pero si el cliente slo quiere dar soporte a dispositivos Symbian Qu tal tus conocimientos tcnicos? A todos nos gusta aprender nuevas tecnologas, pero a la hora de sacar adelante un proyecto es mejor atenerse a lo ya conocido y a aquello en lo que se es eficaz y productivo. Qu presupuesto tienes? Al final, se es el factor determinante, que terminar de resolver cualquier duda que tengas.

Consideraciones sobre el desarrollo. Limitaciones.


Hay dos limitaciones fundamentales a que tener en cuenta a la hora de desarrollar un aplicacin para ser ejecutada en un dispositivo mvil, y son las particularidades de hardware y las de la conexin. Aunque los dispositivos cada vez tienen ms memoria y ms capacidad de proceso, siguen siendo hermanos pequeos de las computadoras de escritorio. Por tanto, debe tenerse especial cuidado con no realizar demasiadas animaciones, ni gastar ciclos de proceso en procedimientos que no sean estrictamente necesarios. La pantalla es pequea, mal iluminada, y se suele mirar en movimiento, como ya hemos visto con anterioridad, por lo que podemos aprovechar eso en nuestro beneficio. Por ello la entrada de datos debe ser lo ms sencilla posible. En el caso de las PDAs, se realizar escribiendo en la pantalla con un lpiz, para que sea el dispositivo el que realice el reconocimiento de la escritura. Aunque ya no hace falta escribir de forma especial, como ocurra con el sistema de reconocimiento de escritura de las primeras Pilot, llamado Graffiti, para que el dispositivo entienda la letra, tampoco se puede ser demasiado descuidado con la caligrafa. En los mviles, sin embargo, la entrada de datos se va a hacer, lo ms probablemente, con una sola mano, y en condiciones no muy apropiadas. El teclado, en la mayora de los casos, tiene slo 10 teclas tiles, que se van a utilizar en movimiento. En cualquiera de los dos casos, hay que intentar, por tanto, formatear las pantallas de entrada de datos para que se pueda realizar el mayor nmero de operaciones o bien punteando encima de botones, en el caso de las PDAs, o bien navegando con el joystick y confirmando con alguno de los botones principales en el caso de los telfonos; evitando en lo posible que el usuario tenga que dirigirse al teclado. Siempre es preferible que haya, por ejemplo, un desplegable en el que elegir entre Calle, Va, Avenida y Paseo, a que haya un campo de texto en el que se tenga que escribir, letra a letra, Calle. Adems, no hay que olvidar que los interfaces de los distintos dispositivos son desesperantemente heterogneos. Adems, ni el tamao de las pantallas, ni el tamao ni la ubicacin de las teclas ayuda a la hora de introducir datos por el usuario. Por eso, siempre hay que intentar desarrollar los interfaces de las aplicaciones de forma que no sean necesarias muchas pulsaciones de teclas, e intentar que, cuando sea necesario pulsar alguna tecla sea alguna de las softkeys, o teclas especiales. En el caso de los dispositivos mviles, ms que en cualquier otro, menos es ms. No slo menos es ms, sino que la colocacin de los elementos de ese menos son los que van a marcar la diferencia. En realidad, no es slo una cuestin de colocacin en pantalla, sino de organizacin de la informacin a presentar, de lo que se llama arquitectura de la informacin. La premisa es bastante sencilla: dadas las dificultades para la introduccin de datos, hay que intentar simplificarla al mximo. Para ello, es muy importante organizar el interfaz de la aplicacin de forma que los procesos de entrada de datos sean lo ms naturales posibles, y que el usuario nunca pase por pantallas cuya presentacin no sea estrictamente necesaria. Pero en realidad esas precauciones no hay que tomarlas slo a la hora de introducir datos, sino tambin a la hora de presentar informacin, y a la hora de estructurar la navegacin por la aplicacin. Normalmente es mucho ms efectivo presentar la informacin agrupada de forma jerrquica, para de ese modo discriminar cuanto antes qu es lo que va a necesitar ver el usuario, y no mostrarle nada que no le resulte estrictamente necesario. En cuanto a las conexiones, lo primero que hay que tener siempre en cuenta es que, al contrario que en las aplicaciones web estndar, no estn siempre disponibles. Por tanto, nunca se puede suponer que el dato que es necesario para poder seguir adelante en la ejecucin de la aplicacin, va a poderse obtener a travs de una conexin a Internet.

- 18 -

Programacin de Dispositivos Mviles

Adems, debe tenerse en cuenta que antes de realizar una conexin a cualquier servicio tarificable, el dispositivo va a solicitar confirmacin al usuario, y que ste puede denegarla, lo cual es perfectamente posible, dado el precio de las conexiones, que son facturables por peso, por cantidad de bytes enviados y descargados, no por tiempo, por lo que siempre hay que optimizar todo lo posible lo que se vaya a enviar en uno u otro sentido. Por si no fueran dificultades suficientes, la latencia de la red, es decir, el tiempo de espera entre una peticin de datos y el comienzo de la llegada de la respuesta, es mucho mayor que la de cualquier aplicacin web normal. Por tanto, hay que ser muy cuidadosos a la hora de informar al usuario sobre lo que est ocurriendo en todo momento, si se est en espera de datos, si ya se estn recibiendo, dando siempre, si es posible, estimaciones sobre el tiempo que resta para la terminacin de todas las tareas. Tampoco se puede suponer que la ejecucin de la aplicacin sea lineal y completa. La funcin bsica de muchos dispositivos es emitir y recibir llamadas telefnicas. Por tanto, nuestra aplicacin debe ser capaz de comportarse adecuadamente al recibir una llamada, entre otras cosas porque la funcin de telfono tiene asignada la prioridad ms alta de todas las del dispositivo, es decir, se va a parar la ejecucin de cualquier aplicacin cuando entre una llamada nueva. Se debe tener prevista una forma de congelar el estado de la aplicacin justo antes de recibir la llamada, para que cuando sta termine, y tras la confirmacin del usuario, se pueda volver a ese estado. Por tanto, si es un juego, todos los elementos del mismo deben permanecer estticos hasta que la llamada termine y el usuario confirme que desea continuar con la aplicacin. En general, hay que intentar probar las aplicaciones en el dispositivo para el que se vayan a desarrollar cuanto antes. De hecho, hay que probar mucho, y comenzar a probar lo antes posible. Nunca hay que fiarse de emuladores, entre otras cosas, porque se ejecutan en hardware cuya capacidad de procesamiento es superior a la del dispositivo en varios rdenes de magnitud. Por tanto, al desarrollar para dispositivos mviles, es muy importante comenzar a probar pronto, y probar a menudo, a fin de evitar sorpresas desagradables.

Usos actuales.
Durante todo este documento hemos estado hablando de las plataformas, los lenguajes de programacin, los sistemas operativos, pero en realidad, para qu sirven? Qu se puede hacer con un mvil? Qu se est haciendo actualmente?. Actualmente, el desarrollo para dispositivos mviles se puede dividir en dos categoras. Por un lado, el desarrollo web puro y duro (webs hechas para ser navegadas desde mviles), y por otro, la programacin de aplicaciones para ser ejecutadas en el propio mvil. No hay que olvidar que, actualmente, casi cualquier dispositivo implementa algn protocolo de comunicacin, sea ste WI-FI o Bluetooth, por lo que es sencillo que, si no es capaz de conectar a Internet por s mismo, como hara un telfono, pueda hacerlo emparejndose con algn otro dispositivo que s pueda. Dicho de otra forma, con un telfono se puede uno conectar a Internet. Con un PocketPC o una Palm es probable que no, pero se puede hacer sin muchos problemas emparejndolo con un telfono. Actualmente hay varios portales de servicios basados en web que proporcionan interfaces especficos para ser navegados desde dispositivos mviles. Compra de entradas para espectculos, consulta de callejeros, de mapas de carreteras, obtencin de informacin sobre restaurantes o farmacias de la zona en la que se encuentra el usuario, son algunos de los servicios ms extendidos.

Metro, un programa multiplataforma con planos de Metro de varias ciudades de todo el mundo El apartado de las aplicaciones ejecutables en el telfono est sin duda dominado por los microjuegos. Las limitaciones grficas y sonoras, sobre todo de los telfonos, no slo no son un problema sino que ayudan a proporcionar a los juegos cierto aire retro, de mquina recreativa de los 80, que les hace ms atractivos. Su bajo peso, adems, les hace ideales para ser descargados directamente al telfono mediante envo de sms a nmeros especiales, por ejemplo, por lo que su sistema de distribucin tiene todas las ventajas de las distribuciones virales. Adems de los minijuegos, otro campo en el que estn surgiendo muchas oportunidades para los desarrolladores es en la construccin de aplicaciones basadas en servicios de localizacin, utilizando datos de posicionamiento de unidades GPS, y combinando esos datos con los obtenidos sobre el entorno del usuario desde un servicio web.

- 19 -

Programacin de Dispositivos Mviles

Tom Tom Mobile en un Symbian Serie 60 Tambin se est trabajando bastante en aplicaciones que puedan servir como apoyo a personas con minusvala, tanto visual como auditiva. Sistemas de localizacin, de reconocimiento ptico, sistemas de traduccin de y a Braille porttiles Por otro lado, los telfonos son pequeos terminales con completas capacidades multimedia, e integran cmaras fotogrficas que son capaces de grabar vdeo y reproductores multimedia que no tienen nada que envidiar a los desarrollados para las computadoras de escritorio. De esas cmaras integradas han salido algunas de las fotografas o vdeos ms famosos en los ltimos meses, como los de los atentados de Londres, o los de algunos nios pegando a sus compaeros de clase.

Acceso a flickr.com desde Opera Mobile Sin embargo, pese al amplio abanico de funcionalidades de los dispositivos, pese a su enorme ndice de penetracin en el mercado, pese a las cantidades de dinero que se alrededor de las descargas de contenidos multimedia o del envo de sms, an no se ha producido el despegue definitivo del desarrollo de aplicaciones. Hablamos mucho de lo cercano que est el despegue definitivo de las aplicaciones mviles, de lo que se ve a poder hacer con los terminales de ltima generacin y las conexiones de banda ancha, pero lo cierto es que ese discurso se lleva escuchando, casi sin alteraciones, desde hace ya varios aos. Lo cierto es que el mercado mueve millones anualmente en descargas de contenidos multimedia, como tonos o fondos de pantalla. Es muy sencillo descargarse un tono polifnico enviando un sms, y al realizarse el pago no en dinero contante y sonante, sino descontando el importe del saldo o de la prxima factura, tampoco se tiene sensacin de estar realizando un gasto real. Sin embargo, el mismo tono puede editarse en una computadora de sobremesa, convertirlo en un formato compatible con el telfono, y enviarlo a ste por BlueTooth, por ejemplo, con lo que el coste final sera cero. El porqu se gasta tanto dinero en servicios que puede realizar uno mismo con un poco de trabajo a los mandos de su computadora, mientras otros, que han costado millones de euros en desarrollo, como por ejemplo la videoconferencia por 3G, prcticamente no se utilizan, es uno de los misterios ms grandes de este nuevo siglo, al menos para los que han desarrollado esos servicios. Sin embargo, estudiando con detenimiento las pautas de comportamiento del usuario medio, entendiendo como tal el que no tiene porqu saber lo que quiere decir Symbian, parece evidente que las ltimas novedades tecnolgicas no son ms que soluciones en busca de un problema. Lo que parece demandar el mercado son servicios y aplicaciones que le simplifiquen la vida, que no requieran de mucha intervencin por su parte para funcionar correctamente.

- 20 -

Programacin de Dispositivos Mviles

Merece consideracin aparte el caso del iPhone, por mltiples razones. La existencia de un mercado cerrado, controlado por el fabricante y la necesidad de pasar por un proceso de certificacin (de pago), no han impedido que ha da de hoy, haya ms de 15.000 aplicaciones disponibles. Sin embargo, hay varios riesgos asociados a un crecimiento tan rpido de una plataforma. El riesgo de implosin es muy alto, y dada la gran rapidez con la que aparecen aplicaciones nuevas, es muy difcil que un desarrollador se plantee trabajar en una aplicacin por un tiempo considerable, lo que hace que el porcentaje de aplicaciones que realmente pueden considerarse como killer es mnimo.

Perspectiva del futuro.


Es muy difcil predecir el futuro. Ms an cuando estamos intentando predecir el futuro de un campo en el que la innovacin es la mxima, lo que todos los implicados buscan, ya sean fabricantes de terminales, desarrolladores de aplicaciones, u operadoras y proveedores de servicios. Pero s que tenemos unos cuantos datos con los que atrevernos a aventurar una previsin para el futuro cercano. En primer lugar, el hardware va a seguir evolucionando. Segn la Ley de Moore, cada 18 meses la potencia de las computadoras se duplica. Esta ley es igual de aplicable para un PC de escritorio, para la supercomputadora Mare Nostrum, para un PocketPC o para un mvil. Como deca Don Hilarin, la ciencia adelanta que es una barbaridad. Por tanto, podemos esperar un avance considerable en la capacidad de proceso de los dispositivos en un plazo relativamente corto, un avance que adems va a ser constante, se va a seguir produciendo a lo largo del tiempo. Y a ms capacidad de proceso, mayor calidad de los contenidos. As pues, lo primero que podemos esperar es que los juegos sean ms complejos, con mejores grficos y mejor sonido, por ejemplo, o aplicaciones complejas con integracin de grficos 3D (aplicaciones sobre medicina o astronoma, por ejemplo). Pero mejor hardware no slo trae consigo aplicaciones de ms calidad, sino mejores posibilidades de comunicacin e interaccin entre dispositivos y por lo tanto entre los dueos de los mismos. Bluetooth de alta velocidad, Wi-Fi, voz ip, comunicaciones por push... son varias las tecnologas que van a servir para mejorar la comunicacin y el intercambio de datos entre dispositivos. Nadie quiere quedarse sin al menos una parte del pastel del futuro. Mientras algunos estn desarrollando pantallas interactivas que se puedan enrollar para transportar, otros estn trabajando en interfaces de usuario que parten de paradigmas totalmente distintos a los que estamos acostumbrados a utilizar y otros estn trabajando en el dispositivo que los una a todos. Esa ltima rama de investigacin, la ya famosa convergencia, puede ser una de las que ms frutos d en un futuro cercano. La idea detrs de esa lnea de desarrollo es el intentar buscar un dispositivo que pueda realizar las funciones de todos los que habitualmente solemos utilizar: reproductor mp3, telfono, agenda electrnica, incluso navegador GPS. Todo en un nico aparato, de dimensiones reducidas, pero con una pantalla lo suficientemente grande como para ser funcional. El penltimo intento fue el Origami de Microsoft, pero han sido varios los que lo han intentado previamente, sin mucho xito: BenQ, Sony-Ericsson, Apple Sin embargo, s parece que los netbooks, especialmente en Asia, donde es raro ver otra cosa, estn cuajando en el mercado. Si bien parece claro que los dispositivos, en un futuro cercano, van a tender a converger a un nico super-dispositivo, qu se puede esperar de cmo sern por tanto las aplicaciones del futuro? Siempre es complicado adivinar lo que va a ocurrir, pero puede esperarse un aumento de las aplicaciones con cierto componente social, al igual que est ocurriendo en la web, que permitan interactuar a los usuarios, jugar en grupo, compartir archivos multimedia con facilidad. Tambin es de suponer que cada vez haya ms aplicaciones especializadas en la gestin y reproduccin de archivos multimedia, sobre todo msica y vdeo, aplicaciones integradas con servicios de descarga a travs del PC de escritorio. En todo caso, lo que nico que parece seguro es que cada vez va a haber ms dispositivos mviles circulando por las calles en manos de sus dueos, dispositivos con mayores capacidades de proceso y multimedia. Una oportunidad que sera una pena dejar pasar.

Actividad 3: Establecimiento de objetivo y tecnologa a utilizar en programacin orientada a mvil


El alumno propone un desarrollo de aplicacin mvil de un caso de la vida real, donde cuestiona cual es el problema a resolver, tomando en cuenta que elementos pueden ser transformados a datos manejables con un dispositivo mvil. Se apoya tambin en casos de uso con equipo mvil como sigue: Ventas ambulantes Inspecciones de proyectos. Toma de Inventarios. Empresas de Servicios. Toma de encuestas o censos. Consultas de cuentas bancarias.

Navegacin red de Internet.

Definicin de objetivo

- 21 -

Programacin de Dispositivos Mviles

Define el objetivo de la aplicacin Web orientada a mvil, de manera concreta e incluyendo los requerimientos especficos del caso en cuestin. Elabora a detalle una propuesta de proyecto de implantacin de la solucin mvil, incluyendo sus fases: Planeacin y anlisis de la propuesta. Diseo de la aplicacin mvil. Elaboracin de las rutinas de programacin. Prueba piloto de la solucin. Puesta a punto y operacin de la aplicacin. Determinacin de tecnologa a utilizar Propone en forma detallada la tecnologa a utilizar (arquitectura, plataforma, emulador de dispositivo y equipo mvil), considerando: El objetivo definido de la propuesta de solucin mvil. Las caractersticas tcnicas del dispositivo mvil. Emuladores para equipos mviles que soporta la arquitectura. Componentes de la plataforma de desarrollo. Enumera adicionalmente las ventajas que se pueden tener con el desarrollo de esta propuesta y el uso de la tecnologa seleccionada. Presenta la propuesta establecida y emite un reporte de la actividad.

Actividad 4: Elaboracin del plan de trabajo para la implementacin de propuesta de solucin establecida
1. PLAN DE TRABAJO Un plan de trabajo es un documento donde se en listan las actividades, las fechas en las que se realizarn, los recursos necesarios y las personas responsables. El primer paso es la definicin de los objetivos, estos son el punto de partida en el proceso de Planeacin, estos nos determinarn las actividades que necesitaremos realizar para lograr los objetivos propuestos. Las siguientes preguntas te servirn de gua para elaborar tu planeacin: Cul es el objetivo de mi proyecto? Qu actividades especficas necesito realizar para alcanzar los objetivos y responder a mis preguntas? En qu secuencia se llevarn a cabo? Cundo estar terminada cada actividad? Qu productos concretos obtendr en cada actividad? Qu recursos necesito? El resultado de este proceso es un plan de actividades y tareas a ejecutarse en un periodo determinado. Realizar tu plan y estar revisndolo constantemente te permite tener retroalimentacin til y permanente de las acciones, as podrs verificar que vas en la direccin indicada para llegar a los resultados esperados y no perders tiempo haciendo actividades secundarias. Una herramienta til para elaborar un plan de trabajo es el "cronograma".

CRONOGRAMA

El cronograma tambin conocido como Grfica de Gantt, es el resumen de un plan de trabajo en forma grfica, que muestra las actividades ms importantes en orden cronolgico, as como la fecha de inicio y termino en que se llevarn a cabo, la persona que es responsable de efectuarlas, los recursos necesarios y los productos esperados. La presentacin del cronograma puede variar, una opcin es:

- 22 -

Programacin de Dispositivos Mviles

ELABORACION DEL PLAN DE TRABAJO Y CRONOGRAMA


Escribe el tema de tu proyecto: Escribe el objetivo (s): Elabora una lista con las actividades que necesitas hacer para alcanzar tu objetivo. Revisa el cronograma del curso revisa fechas y etapas. En Excel elabora tu formato para cronograma y en base a los tiempos marcados en el cronograma del curso, agrupa tus actividades por etapas y asgnales fecha de inicio y termino as recursos y los productos. Guarda tu archivo en la carpeta de proyecto como cronograma. Utiliza las opciones de formato para dar claridad a tu cronograma y que se convierta a una herramienta til para utilizar durante el semestre, permitindote realizar tus actividades en tiempo y lograr los productos de cada. Coloca en la parte superior del cronograma tu tema y tu(s) objetivo(s) para no perderlos de vista. Al final del cronograma abre un cuadro de texto y escribe Qu te aporta esta actividad? Qu utilidad tiene o podr tener? Imprime tu plan de trabajo, revisa su formato y contenido, realiza los cambios que creas conveniente y vuelve a imprimir 2 copias. Una copia debers entregarla al final de la clase y la otra es para que puedas guiar tus actividades a partir de hoy.

2. Elabora el plan de trabajo o calendario para la implementacin de la propuesta de solucin para equipo mvil, definiendo: orden, tiempos, holgura y actividades tomando en cuenta las fases de: Diseo de la aplicacin mvil. Elaboracin de las rutinas de programacin. Prueba piloto de la solucin. Puesta a punto u operacin de la aplicacin. 3. Grafica las fases de la implementacin de la propuesta de solucin. 4. Presenta la grafica o plan de trabajo elaborado y emite un reporte de la actividad.

Actividad 5: Elaboracin de cotizacin para implementacin de solucin mvil


1. Estima costos por cada fase del plan de trabajo del proyecto de implementacin de solucin mvil establecida, mediante dos escenarios de cotizacin. (Apoyarse en el ejemplo anexo). EJEMPLO DE COTIZACIN

ESCENARIO 1

Concepto

Descripcin Incluye: Licencia de las herramientas o lenguajes .NET Instalacin de las de las herramientas o lenguajes .NET Planeacin y anlisis de la propuesta. Diseo de la aplicacin mvil. Elaboracin de las rutinas de programacin. Prueba piloto de la solucin. Puesta en punto y arranque. - CONSULTORIA 200HRS. (100 pesos /HORA) CURSO EN EL MANEJO DE LA APLICACIN

Licenciamiento

Costo en m $22,300.00 pesos + IVA Correspondiente

Desarrollo de la implementacin

$30,000.00 pesos + IVA Correspondiente

Formacin Capacitacin

$5,000.00 pesos + IVA

- 23 -

Programacin de Dispositivos Mviles

(OPCIONAL) Opcional. Infraestructura.

WEB ORIENTADA A MOVIL Incluye: Servidor dedicado Instalacin y Soporte tcnico 1 ao.
ESCENARIO 2

Correspondiente $30,052.00 + IVA Correspondiente

N
Concepto

Licenciamiento

Desarrollo de la implementacin

(OPCIONAL) Opcional. Infraestructura.

Descripcin Incluye: Licencia de las herramientas o lenguajes .NET Instalacin de las de las herramientas o lenguajes .NET Planeacin y anlisis de la propuesta. Diseo de la aplicacin mvil. Elaboracin de las rutinas de programacin. Prueba piloto de la solucin. Puesta en punto y arranque. Incluye: Servidor dedicado Instalacin y Soporte tcnico 1 ao.
FORMA DE PAGO

Costo en m $22,300.00 pesos + IVA Correspondiente

$30,000.00 pesos + IVA Correspondiente

$30,052.00 + IVA Correspondiente Porcentaje 50% 50%

Concepto Anticipo Al finalizar el servicio

VALIDEZ DE LA PROPUESTA Esta propuesta es vlida por 30 das contados a partir de la fecha de presentacin al cliente. Una vez aprobadas las propuestas de diseo, los cambios tendrn un costo adicional. ACUERDO DE CONFIDENCIALIDAD La Empresa, se compromete a mantener en estricta confidencialidad y reserva toda informacin, as como acuerdos promocinales y comerciales establecidos con cualquier empresa o dependencia, incluso previo a la implantacin de la solucin. 2. Elaboracin de Cotizacin Escenario 1 Establece la estimacin de costos en una tabla incluyendo lo siguiente: Estimacin de costos por adquisicin y licenciamiento de la plataforma. Estimacin de costos por servicios por implementacin de la aplicacin. Estimacin de costos por consultora y capacitacin en el uso de la aplicacin. Escenario 2 Establece la estimacin de costos en una tabla incluyendo lo siguiente: Estimacin de costos por adquisicin y licenciamiento de la plataforma. Estimacin de costos por servicios por implementacin de la aplicacin. 3. Planteamiento de escenarios de opcin de financiamiento para el cliente. 4. Presenta la cotizacin elaborada y emite un reporte de la actividad.

- 24 -

Programacin de Dispositivos Mviles

Unidad 2
Implementacin de la aplicacin para dispositivos mviles
El alumno realizar la implementacin del desarrollo de soluciones Web y de gestin de datos orientadas a mviles considerando los procesos de diseo, elaboracin y configuracin de sitios Web; que conlleven al acceso de datos e informacin en lnea o tiempo real con mltiples usos.

2.1 Construye aplicaciones informticas Web que puedan ejecutarse en un entorno mvil por medio de la plataforma y emuladores de dispositivos mviles especficos, a fin de acceder informacin comercial, de servicios o personal. Introduccin
Para los dispositivos mviles, como ya se menciona se pueden utilizar Java (J2ME), Flash Lite y Microsoft .Net, por lo que utilizaremos ste ltimo para la realizacin de aplicaciones para dispositivos mviles, por lo que vamos a utilizar el lenguaje C# (C sharp) para ello, por lo que en la unidad primero se dir que es C#, cmo funciona y por ltimo como se crean aplicaciones para mviles mediante este lengua C# es un lenguaje de programacin de ordenadores. Se trata de un lenguaje moderno, evolucionado a partir de C y C++, y con una sintaxis muy similar a la de Java. Los programas creados con C# no suelen ser tan rpidos como los creados con C, pero a cambio la productividad del programador es mucho mayor. Se trata de un lenguaje creado por Microsoft para crear programas para su plataforma .NET, pero estandarizado posteriormente por ECMA y por ISO, y del que existe una implementacin alternativa de "cdigo abierto", el "proyecto Mono", que est disponible para Windows, Linux, Mac OS X y otros sistemas operativos. Los pasos que seguiremos para crear un programa en C# sern: Escribir el programa en lenguaje C# (fichero fuente), con cualquier editor de textos. Compilarlo con nuestro compilador. Esto crear un "fichero ejecutable". Lanzar el fichero ejecutable. La mayora de los compiladores actuales permiten dar todos estos pasos desde un nico entorno, en el que escribimos nuestros programas, los compilamos, y los depuramos en caso de que exista algn fallo. Mientras que en lenguaje C se puede escribir un programa de esta manera: #include <stdio.h> void main() { printf("Hola"); } En C# hay que dar todavia mas pasos para conseguir lo mismo: public class Ejemplo01 { public static void Main() { System.Console.WriteLine("Hola"); } }

Conceptos bsicos de C#
Vamos con un primer ejemplo de programa en C#, posiblemente el ms sencillo de los que "hacen algo til". Se trata de escribir un texto en pantalla. Vamos a verlo ahora con ms detalle: public class Ejemplo01 { public static void Main() { System.Console.WriteLine("Hola"); } } Esto escribe "Hola" en la pantalla. Pero hay mucho alrededor de ese "Hola", y vamos a comentarlo antes de proseguir, aunque muchos de los detalles se irn aclarando ms adelante. En este primer anlisis, iremos de dentro hacia fuera:

- 25 -

Programacin de Dispositivos Mviles

WriteLine("Hola"); - "Hola" es el texto que queremos escribir, y WriteLine es la orden encargada de escribir (Write) una lnea (Line) de texto en pantalla. Console.WriteLine("Hola"); porque WriteLine es una orden de manejo de la "consola" (la pantalla "negra" en modo texto del sistema operativo). System.Console.WriteLine("Hola"); porque las rdenes relacionadas con el manejo de consola (Console) pertenecen a la categora de sistema (System). Las llaves { y } se usan para delimitar un bloque de programa. En nuestro caso, se trata del bloque principal del programa. public static void Main() - Main indica cual es "el cuerpo del programa", la parte principal (un programa puede estar dividido en varios fragmentos, como veremos ms adelante). Todos los programas tienen que tener un bloque "Main". Los detalles de por qu hay que poner delante "public static void" y de por qu se pone despus un parntesis vaco los iremos aclarando ms tarde. De momento, deberemos memorizar que sa ser la forma correcta de escribir "Main". public class Ejemplo01 - de momento pensaremos que "Ejemplo01" es el nombre de nuestro programa. Una lnea como esa deber existir tambin siempre en nuestros programas, y eso de "public class" ser obligatorio. Nuevamente, aplazamos para ms tarde los detalles sobre qu quiere decir "class" y por qu debe ser "public". Como se puede ver, mucha parte de este programa todava es casi un "acto de f" para nosotros. Debemos creernos que "se debe hacer as". Poco a poco iremos detallando el por qu de "public", de "static", de "void", de "class"... Por ahora nos limitaremos a "rellenar" el cuerpo del programa para entender los conceptos bsicos de programacin. Slo un par de cosas ms antes de seguir adelante:

Cada orden de C# debe terminar con un punto y coma (;)

C# es un lenguaje de formato libre, de modo que puede haber varias rdenes en una misma lnea, u rdenes separadas por varias lneas o espacios entre medias. Lo que realmente indica dnde termina una orden y donde empieza la siguiente son los puntos y coma. Por ese motivo, el programa anterior se podra haber escrito tambin as (aunque no es aconsejable, porque puede resultar menos legible): public class Ejemplo01 { public static void Main() { System.Console.WriteLine("Hola"); } }

De hecho, hay dos formas especialmente frecuentes de colocar la llave de comienzo, y yo usar ambas indistintamente. Una es como hemos hecho en el primer ejemplo: situar la llave de apertura en una lnea, sola, y justo encima de la llave de cierre correspondiente. Esto es lo que muchos autores llaman el "estilo C". La segunda forma habitual es situndola a continuacin del nombre del bloque que comienza (el "estilo Java"), as: public class Ejemplo01 { public static void Main(){ System.Console.WriteLine("Hola"); } } (esta es la forma que yo emplear preferentemente en este texto cuando estemos trabajando con fuentes de mayor tamao, para que ocupe un poco menos de espacio).

La gran mayora de las rdenes que encontraremos en el lenguaje C# son palabras en ingls o abreviaturas de stas. Pero hay que tener en cuenta que C# distingue entre maysculas y minsculas, por lo que "WriteLine" es una palabra reconocida, pero "writeLine", "WRITELINE" o "Writeline" no lo son.

Mostrar nmeros enteros en pantalla


Cuando queremos escribir un texto "tal cual", como en el ejemplo anterior, lo encerramos entre comillas. Pero no siempre querremos escribir textos prefijados. En muchos casos, se tratar de algo que habr que calcular. El ejemplo ms sencillo es el de una operacin matemtica. La forma de realizarla es sencilla: no usar comillas en WriteLine. Entonces, C# intentar analizar el contenido para ver qu quiere decir. Por ejemplo, para sumar 3 y 4 bastara hacer: public class Ejemplo01suma {

- 26 -

Programacin de Dispositivos Mviles

public static void Main() { System.Console.WriteLine(3+4); } } Ejercicio propuesto: crea un programa que diga el resultado de sumar 118 y 56.

Operaciones aritmticas bsicas


Est claro que el smbolo de la suma ser un +, y podemos esperar cual ser el de la resta, pero alguna de las operaciones matemticas habituales tiene smbolos menos intuitivos. Veamos cuales son los ms importantes: Operador Operacin + Suma Resta, negacin * Multiplicacin / Divisin % Resto de la divisin ("mdulo")

Orden de prioridad de los operadores


Sencillo:

En primer lugar se realizarn las operaciones indicadas entre parntesis. Luego la negacin. Despus las multiplicaciones, divisiones y el resto de la divisin. Finalmente, las sumas y las restas. En caso de tener igual prioridad, se analizan de izquierda a derecha.

Introduccin a los problemas de desbordamiento


El espacio del que disponemos para almacenar los nmeros es limitado. Si el resultado de una operacin es un nmero "demasiado grande", obtendremos un mensaje de error o un resultado errneo. Por eso en los primeros ejemplos usaremos nmeros pequeos. Ms adelante veremos a qu se debe realmente este problema y cmo evitarlo. Como anticipo, el siguiente programa ni siquiera compila, porque el compilador sabe que el resultado va a ser "demasiado grande": public class Ejemplo01multiplic { public static void Main() { System.Console.WriteLine(10000000*10000000); } }

Variables. Introduccin a las variables: int


Las variables son algo que no contiene un valor predeterminado, un espacio de memoria al que nosotros asignamos un nombre y en el que podremos almacenar datos. El primer ejemplo nos permita escribir "Hola". El segundo nos permita sumar dos nmeros que habamos prefijado en nuestro programa. Pero esto tampoco es "lo habitual", sino que esos nmeros dependern de valores que haya tecleado el usuario o de clculos anteriores. Por eso necesitaremos usar variables, en las que guardemos los datos con los que vamos a trabajar y tambin los resultados temporales. Vamos a ver como ejemplo lo que haramos para sumar dos nmeros enteros que fijsemos en el programa.

Definicin de variables: nmeros enteros


Para usar una cierta variable primero hay que declararla: indicar su nombre y el tipo de datos que querremos guardar. El primer tipo de datos que usaremos sern nmeros enteros (sin decimales), que se indican con "int" (abreviatura del ingls "integer"). Despus de esta palabra se indica el nombre que tendr la variable: int primerNumero; Esa orden reserva espacio para almacenar un nmero entero, que podr tomar distintos valores, y al que nos referiremos con el nombre "primerNumero".

- 27 -

Programacin de Dispositivos Mviles

Asignacin de valores
Podemos darle un valor a esa variable durante el programa haciendo primerNumero = 234; O tambin podemos darles un valor inicial ("inicializarlas") antes de que empiece el programa, en el mismo momento en que las definimos: int primerNumero = 234; O incluso podemos definir e inicializar ms de una variable a la vez int primerNumero = 234, segundoNumero = 567; (esta lnea reserva espacio para dos variables, que usaremos para almacenar nmeros enteros; una de ellas se llama primerNumero y tiene como valor inicial 234 y la otra se llama segundoNumero y tiene como valor inicial 567). Despus ya podemos hacer operaciones con las variables, igual que las hacamos con los nmeros: suma = primerNumero + segundoNumero;

Mostrar el valor de una variable en pantalla


Una vez que sabemos cmo mostrar un nmero en pantalla, es sencillo mostrar el valor de una variable. Para un nmero hacamos cosas como System.Console.WriteLine(3+4); pero si se trata de una variable es idntico: System.Console.WriteLine(suma); O bien, si queremos mostrar un texto adems del valor de la variable, podemos indicar el texto entre comillas, detallando con {0} en qu parte del texto queremos que aparezca el valor de la variable, de la siguiente forma: System.Console.WriteLine("La suma es {0}", suma); Si se trata de ms de una variable, indicaremos todas ellas tras el texto, y detallaremos dnde debe aparecer cada una de ellas, usando {0}, {1} y as sucesivamente: System.Console.WriteLine("La suma de {0} y {1} es {2}", primerNumero, segundoNumero, suma); Ya sabemos todo lo suficiente para crear nuestro programa que sume dos nmeros usando variables: public class Ejemplo02 { public static void Main() { int primerNumero; int segundoNumero; int suma; primerNumero = 234; segundoNumero = 567; suma = primerNumero + segundoNumero; System.Console.WriteLine("La suma de {0} y {1} es {2}", primerNumero, segundoNumero, suma);

} }

Repasemos lo que hace:

(Nos saltamos todava los detalles de qu quieren decir "public", "class", "static" y "void").

- 28 -

Programacin de Dispositivos Mviles

Main() indica donde comienza el cuerpo del programa, que se delimita entre llaves { y } int primerNumero; reserva espacio para guardar un nmero entero, al que llamaremos primerNumero. int segundoNumero; reserva espacio para guardar otro nmero entero, al que llamaremos segundoNumero. int suma; reserva espacio para guardar un tercer nmero entero, al que llamaremos suma. primerNumero = 234; da el valor del primer nmero que queremos sumar segundoNumero = 567; da el valor del segundo nmero que queremos sumar

suma = primerNumero + segundoNumero; halla la suma de esos dos nmeros y la guarda en otra variable, en vez de mostrarla directamente en pantalla. System.Console.WriteLine("La suma de {0} y {1} es {2}", primerNumero, segundoNumero, suma); muestra en pantalla el texto y los valores de las tres variables (los dos nmeros iniciales y su suma). Ejercicio propuesto:

Hacer un programa que realice la siguiente operacin: que sume los dos primeros nmeros de dos variables y el resultado lo multiplique por el tercer nmero de una tercer variable, mostrando el resultado en pantalla mediante una cuarta variable. Nota: la operacin se debe de realizar en una sola lnea.

Identificadores
Estos nombres de variable (lo que se conoce como "identificadores") pueden estar formados por letras, nmeros o el smbolo de subrayado (_) y deben comenzar por letra o subrayado. No deben tener espacios entre medias, y hay que recordar que las vocales acentuadas y la ee son problemticas, porque no son letras "estndar" en todos los idiomas. Por eso, no son nombres de variable vlidos: 1numero un numero Ao1 MsDatos (empieza por nmero) (contiene un espacio) (tiene una ee) (tiene una vocal acentuada)

Tampoco podremos usar como identificadores las palabras reservadas de C#. Por ejemplo, la palabra "int" se refiere a que cierta variable guardar un nmero entero, as que esa palabra "int" no la podremos usar tampoco como nombre de variable (pero no vamos a incluir ahora una lista de palabras reservadas de C#, ya nos iremos encontrando con ellas). De momento, intentaremos usar nombres de variables que a nosotros nos resulten claros, y que no parezca que puedan ser alguna orden de C#. Hay que recordar que en C# las maysculas y minsculas se consideran diferentes, de modo que si intentamos hacer PrimerNumero = 0; primernumero = 0; o cualquier variacin similar, el compilador protestar y nos dir que no conoce esa variable, porque la habamos declarado como int primerNumero;

Comentarios
Podemos escribir comentarios, que el compilador ignora, pero que pueden servir para aclararnos cosas a nosotros. Se escriben entre /* y */: int suma; /* Porque guardar el valor de la suma para usarlo ms tarde */ Es conveniente escribir comentarios que aclaren la misin de las partes de nuestros programas que puedan resultar menos claras a simple vista. Incluso suele ser aconsejable que el programa comience con un comentario, que nos recuerde qu hace el programa sin que necesitemos mirarlo de arriba a abajo. Un ejemplo casi exagerado: /* ---- Ejemplo en C#: sumar dos nmeros prefijados ---- */ public class Ejemplo02b { public static void Main()

- 29 -

Programacin de Dispositivos Mviles

int primerNumero = 234; int segundoNumero = 567; int suma; /* Guardar el valor para usarlo ms tarde */ /* Primero calculo la suma */ suma = primerNumero + segundoNumero; /* Y despus muestro su valor */ System.Console.WriteLine("La suma de {0} y {1} es {2}", primerNumero, segundoNumero, suma);

} }

Un comentario puede empezar en una lnea y terminar en otra distinta, as: /* */ Tambin es posible declarar otro tipo de comentarios, que comienzan con doble barra y terminan cuando se acaba la lnea (estos comentarios, claramente, no podrn ocupar ms de una lnea). Son los "comentarios al estilo de C++": // Este es un comentario "al estilo C++" Esto es un comentario que ocupa ms de una lnea

Datos por el usuario: ReadLine


Si queremos que sea el usuario de nuestro programa quien teclee los valores, necesitamos una nueva orden, que nos permita leer desde teclado. Pues bien, al igual que tenemos System.Console.WriteLine ("escribir lnea), tambin existe System.Console.ReadLine ("leer lnea"). Para leer textos, haramos texto = System.Console.ReadLine(); pero eso ocurrir en el prximo tema, cuando veamos cmo manejar textos. De momento, nosotros slo sabemos manipular nmeros enteros, as que deberemos convertir ese dato a un nmero entero, usando Convert.ToInt32: primerNumero = System.Convert.ToInt32(System.Console.ReadLine()); Un ejemplo de programa que sume dos nmeros tecleados por el usuario sera: public class Ejemplo03 { public static void Main() { int primerNumero; int segundoNumero; int suma; System.Console.WriteLine("Introduce el primer nmero"); primerNumero = System.Convert.ToInt32( System.Console.ReadLine()); System.Console.WriteLine("Introduce el segundo nmero"); segundoNumero = System.Convert.ToInt32( System.Console.ReadLine()); suma = primerNumero + segundoNumero; System.Console.WriteLine("La suma de {0} y {1} es {2}", primerNumero, segundoNumero, suma); } }

Va siendo hora de hacer una pequea mejora: no es necesario repetir "System." al principio de la mayora de las rdenes que tienen que ver con el sistema (por ahora, las de consola y las de conversin), si al principio del programa utilizamos "using System": using System; public class Ejemplo04 { public static void Main() {

- 30 -

Programacin de Dispositivos Mviles

int primerNumero; int segundoNumero; int suma; Console.WriteLine("Introduce el primer nmero"); primerNumero = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Introduce el segundo nmero"); segundoNumero = Convert.ToInt32(Console.ReadLine()); suma = primerNumero + segundoNumero; Console.WriteLine("La suma de {0} y {1} es {2}", primerNumero, segundoNumero, suma); } }

Ejercicios propuestos: 1. El usuario teclear dos nmeros (x e y), y el programa deber calcular cual es el resultado de su divisin y el resto de esa divisin. El usuario teclear dos nmeros (a y b), y el programa mostrar el resultado de la operacin (a+b)*(a-b) y el resultado de la operacin a2-b2. Pedir al usuario un nmero y mostrar su tabla de multiplicar. Por ejemplo, si el nmero es el 3, debera escribirse algo como:

2.
3.

3 x 0 = 0 3 x 1 = 3 ... 3 x 10 = 30

Tipos de datos bsicos Tipo de datos entero


Hemos hablado de nmeros enteros, de cmo realizar operaciones sencillas y de cmo usar variables para reservar espacio y poder trabajar con datos cuyo valor no sabemos de antemano. Empieza a ser el momento de refinar, de dar ms detalles. El primer "matiz" importante que nos hemos saltado es el tamao de los nmeros que podemos emplear, as como su signo (positivo o negativo). Por ejemplo, un dato de tipo "int" puede guardar nmeros de hasta unas nueve cifras, tanto positivos como negativos, y ocupa 4 bytes en memoria. Pero no es la nica opcin. Por ejemplo, si queremos guardar la edad de una persona, no necesitamos usar nmeros negativos, y nos bastara con 3 cifras, as que es de suponer que existir algn tipo de datos ms adecuado, que desperdicie menos memoria. Tambin existe el caso contrario: un banco puede necesitar manejar nmeros con ms de 9 cifras, as que un dato "int" se les quedara corto. Siendo estrictos, si hablamos de valores monetarios, necesitaramos usar decimales, pero eso lo dejamos para el siguiente apartado.

Tipos de datos para nmeros enteros


Los tipos de datos enteros que podemos usar en C#, junto con el espacio que ocupan en memoria y el rango de valores que os permiten almacenar son: Nombre Del Tipo Tamao (bytes) Rango de valores sbyte byte short ushort int uint long ulong 1 1 2 2 4 4 8 8 -128 a 127 0 a 255 -32768 a 32767 0 a 65535 -2147483648 a 2147483647 0 a 4294967295 -9223372036854775808 a 9223372036854775807 0 a 18446744073709551615

Como se puede observar en esta tabla, el tipo de dato ms razonable para guardar edades sera "byte", que permite valores entre 0 y 255, y ocupa 3 bytes menos que un "int".

Conversiones de cadena a entero

- 31 -

Programacin de Dispositivos Mviles

Si queremos obtener estos datos a partir de una cadena de texto, no siempre nos servir Convert.ToInt32, porque no todos los datos son enteros de 32 bits (4 bytes). Para datos de tipo "byte" usaramos Convert.ToByte (sin signo) y ToSByte (con signo), para datos de 2 bytes tenemos ToInt16 (con signo) y ToUInt16 (sin signo), y para los de 8 bytes existen ToInt64 (con signo) y ToUInt64 (sin signo).

Incremento y decremento
Conocemos la forma de realizar las operaciones aritmticas ms habituales. Peor tambin existe una operacin que es muy frecuente cuando se crean programas, y que no tiene un smbolo especfico para representarla en matemticas: incrementar el valor de una variable en una unidad: a = a + 1; Pues bien, en C#, existe una notacin ms compacta para esta operacin, y para la opuesta (el decremento): a++; a--; es lo mismo que es lo mismo que a = a+1; a = a-1;

Pero esto tiene ms misterio todava del que puede parecer en un primer vistazo: podemos distinguir entre "preincremento" y "postincremento". En C# es posible hacer asignaciones como b = a++; As, si "a" vala 2, lo que esta instruccin hace es dar a "b" el valor de "a" y aumentar el valor de "a". Por tanto, al final tenemos que b=2 y a=3 (postincremento: se incrementa "a" tras asignar su valor). En cambio, si escribimos b = ++a; y "a" vala 2, primero aumentamos "a" y luego los asignamos a "b" (preincremento), de modo que a=3 y b=3. Por supuesto, tambin podemos distinguir postdecremento (a--) y predecremento (--a). Y ya que estamos hablando de las asignaciones, hay que comentar que en C# es posible hacer asignaciones mltiples: a = b = c = 1;

Operaciones abreviadas: +=
Pero an hay ms. Tenemos incluso formas reducidas de escribir cosas como "a = a+5". All van a += b ; es lo mismo que a = a+b; a -= b ; es lo mismo que a = a-b; a *= b ; es lo mismo que a = a*b; a /= b ; es lo mismo que a = a/b; a %= b ; es lo mismo que a = a%b;

Tipo de datos real


Cuando queremos almacenar datos con decimales, no nos sirve el tipo de datos "int". Necesitamos otro tipo de datos que s est preparado para guardar nmeros "reales" (con decimales). En el mundo de la informtica hay dos formas de trabajar con nmeros reales:

Coma fija: el nmero mximo de cifras decimales est fijado de antemano, y el nmero de cifras enteras tambin. Por ejemplo, con un formato de 3 cifras enteras y 4 cifras decimales, el nmero 3,75 se almacenara correctamente, el nmero 970,4361 tambin, pero el 5,678642 se guardara como 5,6786 (se perdera a partir de la cuarta cifra decimal) y el 1010 no se podra guardar (tiene ms de 3 cifras enteras). Coma flotante: el nmero de decimales y de cifras enteras permitido es variable, lo que importa es el nmero de cifras significativas (a partir del ltimo 0). Por ejemplo, con 5 cifras significativas se podran almacenar nmeros como el 13405000000 o como el 0,0000007349 pero no se guardara correctamente el 12,0000034, que se redondeara a un nmero cercano.

Simple y doble precisin


Tenemos tres tamaos para elegir, segn si queremos guardar nmeros con mayor cantidad de cifras o con menos. Para nmeros con pocas cifras significativas (un mximo de 7, lo que se conoce como "un dato real de simple precisin") existe el tipo "float" y para nmeros

- 32 -

Programacin de Dispositivos Mviles

que necesiten ms precisin (unas 15 cifras, "doble precisin") tenemos el tipo "double". En C# existe un tercer tipo de nmeros reales, con mayor precisin todava, que es el tipo "decimal": float Tamao en bits Valor ms grande 32 3,41038 double 64 decimal 128

Valor ms pequeo -1,510-45 5,010-324 1,010-28 1,710308 7,91028 15-16 28-29 Cifras significativas 7

Para definirlos, se hace igual que en el caso de los nmeros enteros: float x; o bien, si queremos dar un valor inicial en el momento de definirlos (recordando que para las cifras decimales no debemos usar una coma, sino un punto): float x = 12.56;

Mostrar en pantalla nmeros reales


Al igual que hacamos con los enteros, podemos leer como cadena de texto, y convertir cuando vayamos a realizar operaciones aritmticas. Ahora usaremos Convert.ToDouble cuando se trate de un dato de doble precisin y Convert.ToSingle cuando sea un dato de simple precisin (float): using System; public class Ejemplo05 { public static void Main() { float primerNumero; float segundoNumero; float suma; Console.WriteLine("Introduce el primer nmero"); primerNumero = Convert.ToSingle(Console.ReadLine()); Console.WriteLine("Introduce el segundo nmero"); segundoNumero = Convert.ToSingle(Console.ReadLine()); suma = primerNumero + segundoNumero; Console.WriteLine("La suma de {0} y {1} es {2}", primerNumero, segundoNumero, suma); } }

Cuidado al probar este programa: aunque en el fuente debemos escribir los decimales usando un punto, como 123.456, al poner el ejecutable en marcha parte del trabajo se le encarga al sistema operativo, de modo que si ste sabe que en nuestro pas se usa la coma para los decimales, considere la coma el separador correcto y no el punto, como ocurre si introducimos estos datos en la versin espaola de Windows XP: ejemplo05 Introduce el primer nmero 23,6 Introduce el segundo nmero 34.2 La suma de 23,6 y 342 es 365,6

Formatear nmeros
En ms de una ocasin nos interesar formatear los nmeros para mostrar una cierta cantidad de decimales: por ejemplo, nos puede interesar que una cifra que corresponde a dinero se muestre siempre con dos cifras decimales, o que una nota se muestre redondeada, sin decimales. Una forma de conseguirlo es crear una cadena de texto a partir del nmero, usando "ToString". A esta orden se le puede indicar un dato adicional, que es el formato numrico que queremos usar, por ejemplo: suma.ToString("0.00")

- 33 -

Programacin de Dispositivos Mviles

Algunos de los cdigos de formato que se pueden usar son:

Un cero (0) indica una posicin en la que debe aparecer un nmero, y se mostrar un 0 si no hay ninguno. Una almohadilla (#) indica una posicin en la que puede aparecer un nmero, y no se escribir nada si no hay nmero. Un punto (.) indica la posicin en la que deber aparecer la coma decimal.

Alternativamente, se pueden usar otros formatos abreviados: por ejemplo, N2 quiere decir "con dos cifras decimales" y N5 es "con cinco cifras decimales". Vamos a probarlos en un ejemplo: using System; public class Ejemplo06 { public static void Main() { double numero = 12.34; Console.WriteLine( Console.WriteLine( Console.WriteLine( Console.WriteLine( Console.WriteLine( Console.WriteLine( } } numero.ToString("N1") ); numero.ToString("N3") ); numero.ToString("0.0") ); numero.ToString("0.000") ); numero.ToString("#.#") ); numero.ToString("#.###") );

El resultado de este ejemplo sera: 12,3 12,340 12,3 12,340 12,3 12,34 Como se puede ver, ocurre lo siguiente:

Si indicamos menos decimales de los que tiene el nmero, se redondea.

Si indicamos ms decimales de los que tiene el nmero, se mostrarn ceros si usamos como formato Nx o 0.000, y no se mostrar nada si usamos #.### Si indicamos menos cifras antes de la coma decimal de las que realmente tiene el nmero, aun as se muestran todas ellas. Ejercicios propuestos:

4. 5.

El usuario de nuestro programa podr teclear dos nmeros enteros. El programa deber mostrar el resultado de dividir el primer nmero entre el segundo, utilizando dos cifras decimales. Crear un programa que use tres variables x,y,z. Las tres sern nmeros reales, y nos bastar con dos cifras decimales. Deber pedir al usuario los valores para las tres variables y mostrar en pantalla el valor de x2 + y - z (con exactamente dos cifras decimales).

Tipo de datos carcter


Tambin tenemos un tipo de datos que nos permite almacenar una nica letra, el tipo "char": char letra; Asignar valores es sencillo: el valor se indica entre comillas simples letra = 'a';

- 34 -

Programacin de Dispositivos Mviles

Para leer valores desde teclado, lo podemos hacer de forma similar a los casos anteriores: leemos toda una frase con ReadLine y convertimos a tipo "char" usando Convert.ToChar: letra = Convert.ToChar(Console.ReadLine()); As, un programa que de un valor inicial a una letra, la muestre, lea una nueva letra tecleada por el usuario, y la muestre, podra ser: using System; public class Ejemplo07 { public static void Main() { char letra; letra = 'a'; Console.WriteLine("La letra es {0}", letra); Console.WriteLine("Introduce una nueva letra"); letra = Convert.ToChar(Console.ReadLine()); Console.WriteLine("Ahora la letra es {0}", letra);

} }

Secuencias de escape: \n y otras.


Como hemos visto, los textos que aparecen en pantalla se escriben con WriteLine, indicados entre parntesis y entre comillas dobles. Entonces surge una dificultad: cmo escribimos una comilla doble en pantalla? La forma de conseguirlo es usando ciertos caracteres especiales, lo que se conoce como "secuencias de escape". Existen ciertos caracteres especiales que se pueden escribir despus de una barra invertida (\) y que nos permiten conseguir escribir esas comillas dobles y algn otro carcter poco habitual. Por ejemplo, con \" se escribirn unas comillas dobles, y con \' unas comillas simples, o con \n se avanzar a la lnea siguiente de pantalla. Estas secuencias especiales son las siguientes: Secuencia Significado \a \b \f \n \r \t \v \' \" \\ \0 Emite un pitido Retroceso (permite borrar el ltimo carcter) Avance de pgina (expulsa una hoja en la impresora) Avanza de lnea (salta a la lnea siguiente) Retorno de carro (va al principio de la lnea) Salto de tabulacin horizontal Salto de tabulacin vertical Muestra una comilla simple Muestra una comilla doble Muestra una barra invertida Carcter nulo (NULL)

Vamos a ver un ejemplo que use los ms habituales: using System; public class Ejemplo08 { public static void Main() { Console.WriteLine("Esta es una frase"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("y esta es otra, separada dos lineas"); Console.WriteLine("\n\nJuguemos mas:\n\notro salto"); Console.WriteLine("Comillas dobles: \" y simples \', y barra \\");

} }

- 35 -

Programacin de Dispositivos Mviles

Su resultado sera este: Esta es una frase y esta es otra, separada dos lineas Juguemos mas: otro salto Comillas dobles: " y simples ', y barra \ En algunas ocasiones puede ser incmodo manipular estas secuencias de escape. Por ejemplo, cuando usemos estructuras de directorios: c:\\datos\\ejemplos\\curso\\ejemplo1. En este caso, se puede usar una arroba (@) antes del texto sin las barras invertidas: ruta = @"c:\datos\ejemplos\curso\ejemplo1" En este caso, el problema est si aparecen comillas en medio de la cadena. Para solucionarlo, se duplican las comillas, as: orden = @"copy ""documento de ejemplo"" f:"

Toma de contacto con las cadenas de texto


Las cadenas de texto son tan fciles de manejar como los dems tipos de datos que hemos visto, con apenas tres diferencias:

Se declaran con "string". Si queremos dar un valor inicial, ste se indica entre comillas dobles. Cuando leemos con ReadLine, no hace falta convertir el valor obtenido.

As, un ejemplo que diera un valor a un "string", lo mostrara (entre comillas, para practicar las secuencias de escape que hemos visto en el apartado anterior) y leyera un valor tecleado por el usuario podra ser: using System; public class Ejemplo09 { public static void Main() { string frase; frase = "Hola, como estas?"; Console.WriteLine("La frase es \"{0}\"", frase); Console.WriteLine("Introduce una nueva frase"); frase = Console.ReadLine(); Console.WriteLine("Ahora la frase es \"{0}\"", frase); } }

Se pueden hacer muchas ms operaciones sobre cadenas de texto: convertir a maysculas o a minsculas, eliminar espacios, cambiar una subcadena por otra, dividir en trozos, etc. Pero ya volveremos a las cadenas ms adelante, cuando conozcamos las estructuras de control bsicas. Ejercicios propuestos: 6. Realizar un programa el cal se deben de introducir los datos del usuario en las variables que se van a declarar a continuacn: Nombre, Domicilio y Telfono de tipo string; Sexo de carcter; Edad de tipo numrico; despus, mostrar el valor de las variables en pantalla.

Los valores "booleanos"


En C# tenemos tambin un tipo de datos llamado "booleano" ("bool"), que puede tomar dos valores: verdadero o falso: bool encontrado; encontrado = true;

- 36 -

Programacin de Dispositivos Mviles

Este tipo de datos har que podamos escribir de forma sencilla algunas condiciones que podran resultar complejas, pero eso lo veremos en el tema 3.

Estructuras de control Estructuras alternativas if


Vamos a ver cmo podemos comprobar si se cumplen condiciones. La primera construccin que usaremos ser "si ... entonces ...". El formato es if (condicin) sentencia; Vamos a verlo con un ejemplo: /*---------------------------*/ /* Ejemplo en C# n 10: */ /* ejemplo10.cs */ /* */ /* Condiciones con if */ /*---------------------------*/ using System; public class Ejemplo10 { public static void Main() { int numero; Console.WriteLine("Introduce un nmero"); numero = Convert.ToInt32(Console.ReadLine()); if (numero>0) Console.WriteLine("El nmero es positivo.");

} }

Este programa pide un nmero al usuario. Si es positivo (mayor que 0), escribe en pantalla "El nmero es positivo."; si es negativo o cero, no hace nada. Como se ve en el ejemplo, para comprobar si un valor numrico es mayor que otro, usamos el smbolo ">". Para ver si dos valores son iguales, usaremos dos smbolos de "igual": if (numero==0). Las dems posibilidades las veremos algo ms adelante. En todos los casos, la condicin que queremos comprobar deber indicarse entre parntesis. Este programa comienza por un comentario que nos recuerda de qu se trata. Como nuestros fuentes irn siendo cada vez ms complejos, a partir de ahora incluiremos comentarios que nos permitan recordar de un vistazo qu pretendamos hacer.

if y sentencias compuestas
Habamos dicho que el formato bsico de "if" es if (condicin) sentencia; Esa "sentencia" que se ejecuta si se cumple la condicin puede ser una sentencia simple o una compuesta. Las sentencias compuestas se forman agrupando varias sentencias simples entre llaves ( { y } ), como en este ejemplo: /*---------------------------*/ /* Ejemplo en C# n 11: */ /* ejemplo11.cs */ /* */ /* Condiciones con if (2) */ /* Sentencias compuestas */ /*---------------------------*/ using System; public class Ejemplo11 { public static void Main() { int numero; Console.WriteLine("Introduce un nmero"); numero = Convert.ToInt32(Console.ReadLine());

- 37 -

Programacin de Dispositivos Mviles

if (numero>0) { Console.WriteLine("El nmero es positivo."); Console.WriteLine("Recuerde que tambin puede usar negativos."); } /* Aqui acaba el "if" */ } /* Aqui acaba "Main" */ } /* Aqui acaba "Ejemplo11" */ En este caso, si el nmero es negativo, se hacen dos cosas: escribir un texto y luego... escribir otro! (Claramente, en este ejemplo, esos dos "WriteLine" podran ser uno solo, en el que los dos textos estuvieran separados por un "\n"; ms adelante iremos encontrando casos en lo que necesitemos hacer cosas "ms serias" dentro de una sentencia compuesta). Como se ve en este ejemplo, cada nuevo "bloque" se suele escribir un poco ms a la derecha que los anteriores, para que sea fcil ver dnde comienza y termina cada seccin de un programa. Por ejemplo, el contenido de "Ejemplo11" est un poco ms a la derecha que la cabecera "public class Ejemplo11", y el contenido de "Main" algo ms a la derecha, y la sentencia compuesta que se debe realizar si se cumple la condicin del "if" est algo ms a la derecha que la orden "if". Este "sangrado" del texto se suele llamar "escritura indentada". Un tamao habitual para el sangrado es de 4 espacios, aunque en este texto habitualmente usaremos slo dos espacios, para no llegar al margen derecho del papel con mucha facilidad.

Operadores relacionales: <, <=, >, >=, ==, !=


Hemos visto que el smbolo ">" es el que se usa para comprobar si un nmero es mayor que otro. El smbolo de "menor que" tambin es sencillo, pero los dems son un poco menos evidentes, as que vamos a verlos: Operador Operacin < > <= >= == != Menor que Mayor que Menor o igual que Mayor o igual que Igual a No igual a (distinto de)

Y un ejemplo, que diga si un nmero NO ES cero: /*---------------------------*/ /* Ejemplo en C# n 12: */ /* ejemplo12.cs */ /* */ /* Condiciones con if (3) */ /* */ /* Introduccion a C#, */ /* Nacho Cabanes */ /*---------------------------*/ using System; public class Ejemplo12 { public static void Main() { int numero; Console.WriteLine("Introduce un nmero"); numero = Convert.ToInt32(Console.ReadLine()); if (numero != 0) Console.WriteLine("El nmero no es cero.");

} }

Ejercicios propuestos: 7. Crear un programa que multiplique dos nmeros enteros de la siguiente forma: pedir al usuario un primer nmero entero. Si el nmero que se que teclee es 0, escribir en pantalla "El producto de 0 por cualquier nmero es 0". Si se ha tecleado un nmero distinto de cero, se pedir al usuario un segundo nmero y se mostrar el producto de ambos. Crear un programa que pida al usuario dos nmeros reales. Si el segundo no es cero, mostrar el resultado de dividir entre el primero y el segundo. Por el contrario, si el segundo nmero es cero, escribir "Error: No se puede dividir entre cero".

8.

- 38 -

Programacin de Dispositivos Mviles

if-else
Podemos indicar lo que queremos que ocurra en caso de que no se cumpla la condicin, usando la orden "else" (en caso contrario), as: /*---------------------------*/ /* Ejemplo en C# n 13: */ /* ejemplo13.cs */ /* */ /* Condiciones con if (4) */ /*---------------------------*/ using System; public class Ejemplo13 { public static void Main() { int numero; Console.WriteLine("Introduce un nmero"); numero = Convert.ToInt32(Console.ReadLine()); if (numero > 0) Console.WriteLine("El nmero es positivo."); else Console.WriteLine("El nmero es cero o negativo.");

} }

Podramos intentar evitar el uso de "else" si utilizamos un "if" a continuacin de otro, as: /*---------------------------*/ /* Ejemplo en C# n 14: */ /* ejemplo14.cs */ /* */ /* Condiciones con if (5) */ /*---------------------------*/ using System; public class Ejemplo14 { public static void Main() { int numero; Console.WriteLine("Introduce un nmero"); numero = Convert.ToInt32(Console.ReadLine()); if (numero > 0) Console.WriteLine("El nmero es positivo."); if (numero <= 0) Console.WriteLine("El nmero es cero o negativo."); } }

Pero el comportamiento no es el mismo: en el primer caso (ejemplo 13) se mira si el valor es positivo; si no lo es, se pasa a la segunda orden, pero si lo es, el programa ya ha terminado. En el segundo caso (ejemplo 14), aunque el nmero sea positivo, se vuelve a realizar la segunda comprobacin para ver si es negativo o cero, por lo que el programa es algo ms lento. Podemos enlazar los "if" usando "else", para decir "si no se cumple esta condicin, mira a ver si se cumple esta otra": /*---------------------------*/ /* Ejemplo en C# n 15: */ /* ejemplo15.cs */ /* */ /* Condiciones con if (6) */ /*---------------------------*/ using System; public class Ejemplo15 { public static void Main() {

- 39 -

Programacin de Dispositivos Mviles

int numero; Console.WriteLine("Introduce un nmero"); numero = Convert.ToInt32(Console.ReadLine()); if (numero > 0) Console.WriteLine("El nmero es positivo."); else if (numero < 0) Console.WriteLine("El nmero es negativo."); else Console.WriteLine("El nmero es cero.");

} }

Operadores lgicos: &&, ||, !


Estas condiciones se puede encadenar con "y", "o", etc., que se indican de la siguiente forma Operador && || ! Significado Y O No

De modo que podremos escribir cosas como if ((opcion==1) && (usuario==2)) ... if ((opcion==1) || (opcion==3)) ... if ((!(opcion==opcCorrecta)) || (tecla==ESC)) Ejercicios propuestos: 9. Crear un programa que pida una letra al usuario y diga si se trata de una vocal. 10. Crear un programa que pida al usuario dos nmeros enteros cortos y diga si son iguales o, en caso contrario, cul es el mayor de ellos.

...

El peligro de la asignacin en un "if"


Cuidado con el operador de igualdad: hay que recordar que el formato es "if (a==b)" Si no nos acordamos y escribimos "if (a=b)", estamos intentando asignar a "a" el valor de "b". En algunos compiladores de lenguaje C, esto podra ser un problema serio, porque se considera vlido hacer una asignacin dentro de un "if" (aunque la mayora de compiladores modernos nos avisaran de que quiz estemos asignando un valor por error). En el caso del lenguaje C#, la "condicin" debe ser algo cuyo resultado sea "verdadero" o "falso" (un dato de tipo "bool"), de modo que obtendramos un mensaje de error "Cannot implicitly convert type 'int' to 'bool'" (no puedo convertir un "int" a "bool"), en casos como el del siguiente programa: /*---------------------------*/ /* Ejemplo en C# n 16: */ /* ejemplo16.cs */ /* */ /* Condiciones con if (7) */ /* comparacion incorrecta */ /*---------------------------*/ using System; public class Ejemplo16 { public static void Main() { int numero; Console.WriteLine("Introduce un nmero"); numero = Convert.ToInt32(Console.ReadLine()); if (numero = 0) Console.WriteLine("El nmero es cero."); else if (numero < 0)

- 40 -

Programacin de Dispositivos Mviles

} }

Console.WriteLine("El nmero es negativo."); else Console.WriteLine("El nmero es positivo.");

Comparaciones y variables de tipo "bool"


En muchas ocasiones, cuando las condiciones que aparecen dentro de un "if" sean complejas, el programa resultar ms legible si empleamos variables de tipo "bool" (verdadero o falso), de forma que ciertos fragmentos de nuestro programa no sean "if ((vidas==0) || (tiempo == 0) || ((enemigos ==0) && (nivel == ultimoNivel)))" sino simplemente "if (partidaTerminada) ..." A las variables "bool" se les da un valor casi como a cualquier otra variable, con la diferencia de que en la parte derecha de la asignacin aparece "true" , "false" o una comparacin, as: partidaTerminada = false; partidaTerminada = (enemigos ==0) && (nivel == ultimoNivel); if (vidas ==0) partidaTerminada = true; Lo emplearemos a partir de ahora en los fuentes que usen condiciones un poco complejas. Un ejemplo que pida una letra y diga si es una vocal, una cifra numrica u otro smbolo, usando variables "bool" podra ser: /*---------------------------*/ /* Ejemplo en C# n 17: */ /* ejemplo17.cs */ /* */ /* Condiciones con if (8) */ /* Variables bool */ /*---------------------------*/ using System; public class Ejemplo17 { public static void Main() { char letra; bool esVocal, esCifra; Console.WriteLine("Introduce una letra"); letra = Convert.ToChar(Console.ReadLine()); esCifra = (letra >= '0') && (letra <='9'); esVocal = (letra == 'a') || (letra == 'e') || (letra == 'i') || (letra == 'o') || (letra == 'u'); if (esCifra) Console.WriteLine("Es una cifra numrica."); else if (esVocal) Console.WriteLine("Es una vocal."); else Console.WriteLine("Es una consonante u otro nmero.");

} }

Operador condicional: ?
En C# hay otra forma de asignar un valor segn se d una condicin o no. Es el "operador condicional" ? : que se usa nombreVariable = condicion ? valor1 : valor2;

y equivale a decir "si se cumple la condicin, toma el valor v1; si no, toma el valor v2". Un ejemplo de cmo podramos usarlo sera numeroMayor = (a>b) ? a : b;

que, aplicado a un programa sencillo, podra ser

- 41 -

Programacin de Dispositivos Mviles

/*---------------------------*/ /* Ejemplo en C# n 18: */ /* ejemplo18.cs */ /* */ /* El operador condicional */ /*---------------------------*/ using System; public class Ejemplo18 { public static void Main() { int a, b, mayor; Console.Write("Escriba un nmero: "); a = Convert.ToInt32(Console.ReadLine()); Console.Write("Escriba otro: "); b = Convert.ToInt32(Console.ReadLine()); mayor = (a>b) ? } } (La orden Console.Write, empleada en el ejemplo anterior, escribe un texto sin avanzar a la lnea siguiente, de modo que el prximo texto que escribamos o introduzcamos- quedar a continuacin de ste). Un segundo ejemplo, que sume o reste dos nmeros segn la opcin que se escoja, sera: /*---------------------------*/ /* Ejemplo en C# n 19: */ /* ejemplo19.cs */ /* */ /* Operador condicional - 2 */ /*---------------------------*/ using System; public class Ejemplo19 { public static void Main() { int a, b, operacion, resultado; Console.Write("Escriba un nmero: "); a = Convert.ToInt32(Console.ReadLine()); Console.Write("Escriba otro: "); b = Convert.ToInt32(Console.ReadLine()); Console.Write("Escriba una operacin (1 = resta; otro = suma): "); operacion = Convert.ToInt32(Console.ReadLine()); resultado = (operacion == 1) ? } a-b : a+b; a : b;

Console.WriteLine("El mayor de los nmeros es {0}.", mayor);

Console.WriteLine("El resultado es {0}.\n", resultado); }

Ejercicios propuestos: 11. Crear un programa que use el operador condicional para mostrar un el valor absoluto de un nmero de la siguiente forma: si el nmero es positivo, se mostrar tal cual; si es negativo, se mostrar cambiado de signo. 12. Crear un programa que use el operador condicional para dar a una variable llamada "iguales" (booleana) el valor "true" si los dos nmeros que ha tecleado el usuario son iguales, o "false" si son distintos.

- 42 -

Programacin de Dispositivos Mviles

switch
Si queremos ver varios posibles valores, sera muy pesado tener que hacerlo con muchos "if" seguidos o encadenados. La alternativa es la orden "switch", cuya sintaxis es switch (expresin) { case valor1: sentencia1; break; case valor2: sentencia2; sentencia2b; break; ... case valorN: sentenciaN; break; default: otraSentencia; break; }; Es decir, se escribe tras "switch" la expresin a analizar, entre parntesis. Despus, tras varias rdenes "case" se indica cada uno de los valores posibles. Los pasos (porque pueden ser varios) que se deben dar si se trata de ese valor se indican a continuacin, terminando con "break". Si hay que hacer algo en caso de que no se cumpla ninguna de las condiciones, se detalla tras "default". Si dos casos tienen que hacer lo mismo, se aade "goto case" a uno de ellos para indicarlo. Vamos con un ejemplo, que diga si la tecla que pulsa el usuario es una cifra numrica, un espacio u otro smbolo: /*---------------------------*/ /* Ejemplo en C# n 20: */ /* ejemplo20.cs */ /* */ /* La orden "switch" (1) */ /*---------------------------*/ using System; public class Ejemplo20 { public static void Main() { char letra; Console.WriteLine("Introduce una letra"); letra = Convert.ToChar(Console.ReadLine()); switch (letra) { case ' ': Console.WriteLine("Espacio."); break; case '1': goto case '0'; case '2': goto case '0'; case '3': goto case '0'; case '4': goto case '0'; case '5': goto case '0'; case '6': goto case '0'; case '7': goto case '0'; case '8': goto case '0'; case '9': goto case '0'; case '0': Console.WriteLine("Dgito."); break; default: Console.WriteLine("Ni espacio ni dgito."); break; } } }

Cuidado quien venga del lenguaje C: en C se puede dejar que un caso sea manejado por el siguiente, lo que se consigue si no se usa "break", mientras que C# siempre obliga a usar "break" o "goto" en cada caso, para evitar errores difciles de detectar. El fragmento anterior en C habra sido:

- 43 -

Programacin de Dispositivos Mviles

switch (tecla) { case ' ': printf("Espacio.\n"); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': printf("Dgito.\n"); break; default: printf("Ni espacio ni dgito.\n"); } En el lenguaje C, que es ms antiguo, slo se poda usar "switch" para comprobar valores de variables "simples" (numricas y caracteres); en C#, que es un lenguaje ms evolucionado, se puede usar tambin para comprobar valores de "strings". Por ejemplo, un programa que nos salude de forma personalizada si somos "Juan" o "Pedro" podra ser: /*---------------------------*/ /* Ejemplo en C# n 21: */ /* ejemplo21.cs */ /* */ /* La orden "switch" (2) */ /*---------------------------*/ using System; public class Ejemplo21 { public static void Main() { string nombre; Console.WriteLine("Introduce tu nombre"); nombre = Console.ReadLine(); switch (nombre) { case "Juan": Console.WriteLine("Bienvenido, Juan."); break; case "Pedro": Console.WriteLine("Que tal estas, Pedro."); break; default: Console.WriteLine("Procede con cautela, desconocido."); break; } } }

Ejercicios propuestos: 13. Crear un programa que lea una letra tecleada por el usuario y diga si se trata de una vocal, una cifra numrica o una consonante. 14. Crear un programa que lea una letra tecleada por el usuario y diga si se trata de un signo de puntuacin, una cifra numrica o algn otro carcter.

Estructuras repetitivas
Hemos visto cmo comprobar condiciones, pero no cmo hacer que una cierta parte de un programa se repita un cierto nmero de veces o mientras se cumpla una condicin (lo que llamaremos un "bucle"). En C# tenemos varias formas de conseguirlo.

while
Si queremos hacer que una seccin de nuestro programa se repita mientras se cumpla una cierta condicin, usaremos la orden "while". Esta orden tiene dos formatos distintos, segn comprobemos la condicin al principio o al final.

- 44 -

Programacin de Dispositivos Mviles

En el primer caso, su sintaxis es while (condicin) sentencia; Es decir, la sentencia se repetir mientras la condicin sea cierta. Si la condicin es falsa ya desde un principio, la sentencia no se ejecuta nunca. Si queremos que se repita ms de una sentencia, basta agruparlas entre { y }. Un ejemplo que nos diga si cada nmero que tecleemos es positivo o negativo, y que pare cuando tecleemos el nmero 0, podra ser: /*---------------------------*/ /* Ejemplo en C# n 22: */ /* ejemplo22.cs */ /* */ /* La orden "while" */ /*---------------------------*/ using System; public class Ejemplo22 { public static void Main() { int numero; Console.Write("Teclea un nmero (0 para salir): "); numero = Convert.ToInt32(Console.ReadLine()); while (numero != 0) { if (numero > 0) Console.WriteLine("Es positivo"); else Console.WriteLine("Es negativo"); Console.WriteLine("Teclea otro nmero (0 para salir): "); numero = Convert.ToInt32(Console.ReadLine()); } } }

En este ejemplo, si se introduce 0 la primera vez, la condicin es falsa y ni siquiera se entra al bloque del "while", terminando el programa inmediatamente. Ejercicios propuestos: 15. Crear un programa que pida al usuario su contrasea. Deber terminar cuando introduzca como contrasea la palabra "clave", pero volvrsela a pedir tantas veces como sea necesario. 16. Crea un programa que escriba en pantalla los nmeros del 1 al 10, usando "while". 17. Crea un programa que escriba en pantalla los nmeros pares del 26 al 10 (descendiendo), usando "while". 18. Crear un programa calcule cuantas cifras tiene un nmero entero positivo (pista: se puede hacer dividiendo varias veces entre 10).

do ... while
Este es el otro formato que puede tener la orden "while": la condicin se comprueba al final. El punto en que comienza a repetirse se indica con la orden "do", as: do sentencia; while (condicin); Al igual que en el caso anterior, si queremos que se repitan varias rdenes (es lo habitual), deberemos encerrarlas entre llaves. Como ejemplo, vamos a ver cmo sera el tpico programa que nos pide una clave de acceso y no nos deja entrar hasta que tecleemos la clave correcta:

- 45 -

Programacin de Dispositivos Mviles

/*---------------------------*/ /* Ejemplo en C# n 23: */ /* ejemplo23.cs */ /* */ /* La orden "do..while" */ /*---------------------------*/ using System; public class Ejemplo23 { public static void Main() { int valida = 711; int clave; do { Console.Write("Introduzca su clave numrica: "); clave = Convert.ToInt32(Console.ReadLine()); if (clave != valida) Console.WriteLine("No vlida!\n"); } while (clave != valida); Console.WriteLine("Aceptada.\n"); } }

En este caso, se comprueba la condicin al final, de modo que se nos preguntar la clave al menos una vez. Mientras que la respuesta que demos no sea la correcta, se nos vuelve a preguntar. Finalmente, cuando tecleamos la clave correcta, el ordenador escribe "Aceptada" y termina el programa. Si preferimos que la clave sea un texto en vez de un nmero, los cambios al programa son mnimos: /*---------------------------*/ /* Ejemplo en C# n 24: */ /* ejemplo24.cs */ /* */ /* La orden "do..while" (2) */ /*---------------------------*/ using System; public class Ejemplo24 { public static void Main() { string valida = "secreto"; string clave; do { Console.Write("Introduzca su clave: "); clave = Console.ReadLine(); if (clave != valida) Console.WriteLine("No vlida!\n"); } while (clave != valida); Console.WriteLine("Aceptada.\n"); } }

Ejercicios propuestos: 19. Crear un programa que pida nmeros positivos al usuario, y vaya calculando la suma de todos ellos (terminar cuando se teclea un nmero negativo o cero).

- 46 -

Programacin de Dispositivos Mviles

20. Crea un programa que escriba en pantalla los nmeros del 1 al 10, usando "do..while". 21. Crea un programa que escriba en pantalla los nmeros pares del 26 al 10 (descendiendo), usando "do..while". 22. Crea un programa que pida al usuario su nombre y su contrasea, y no le permita seguir hasta que introduzca como nombre "Pedro" y como contrasea "Peter".

for
sta es la orden que usaremos habitualmente para crear partes del programa que se repitan un cierto nmero de veces. El formato de "for" es for (valorInicial; CondicinRepeticin; Incremento) Sentencia; As, para contar del 1 al 10, tendramos 1 como valor inicial, <=10 como condicin de repeticin, y el incremento sera de 1 en 1. Por tanto, el programa quedara: /*---------------------------*/ /* Ejemplo en C# n 25: */ /* ejemplo25.cs */ /* */ /* Uso bsico de "for" */ /*---------------------------*/ using System; public class Ejemplo25 { public static void Main() { int contador; for (contador=1; contador<=10; contador++) Console.Write("{0} ", contador); } } Recordemos que "contador++" es una forma abreviada de escribir "contador=contador+1", de modo que en este ejemplo aumentamos la variable de uno en uno. Ejercicios propuestos: 23. Crear un programa que muestre los nmeros del 15 al 5, descendiendo (pista: en cada pasada habr que descontar 1, por ejemplo haciendo i--).

24. Crear un programa que muestre los primeros ocho nmeros pares (pista: en cada pasada habr que aumentar de 2 en
2, o bien mostrar el doble del valor que hace de contador). En un "for", realmente, la parte que hemos llamado "Incremento" no tiene por qu incrementar la variable, aunque se es su uso ms habitual. Es simplemente una orden que se ejecuta cuando se termine la "Sentencia" y antes de volver a comprobar si todava se cumple la condicin de repeticin. Por eso, si escribimos la siguiente lnea: for (contador=1; contador<=10; ) la variable "contador" no se incrementa nunca, por lo que nunca se cumplir la condicin de salida: nos quedamos encerrados dando vueltas dentro de la orden que siga al "for". Un caso todava ms exagerado de algo a lo que se entra y de lo que no se sale sera la siguiente orden: for ( ; ; ) Los bucles "for" se pueden anidar (incluir uno dentro de otro), de modo que podramos escribir las tablas de multiplicar del 1 al 5 con:

- 47 -

Programacin de Dispositivos Mviles

/*---------------------------*/ /* Ejemplo en C# n 26: */ /* ejemplo26.cs */ /* */ /* "for" anidados */ /*---------------------------*/ using System; public class Ejemplo26 { public static void Main() { int tabla, numero; for (tabla=1; tabla<=5; tabla++) for (numero=1; numero<=10; numero++) Console.WriteLine("{0} por {1} es {2}", tabla, numero, tabla*numero); } } En estos ejemplos que hemos visto, despus de "for" haba una nica sentencia. Si queremos que se hagan varias cosas, basta definirlas como un bloque (una sentencia compuesta) encerrndolas entre llaves. Por ejemplo, si queremos mejorar el ejemplo anterior haciendo que deje una lnea en blanco entre tabla y tabla, sera: /*---------------------------*/ /* Ejemplo en C# n 27: */ /* ejemplo27.cs */ /* */ /* "for" anidados (2) */ /*---------------------------*/ using System; public class Ejemplo27 { public static void Main() { int tabla, numero; for (tabla=1; tabla<=5; tabla++) { for (numero=1; numero<=10; numero++) Console.WriteLine("{0} por {1} es {2}", tabla, numero, tabla*numero); Console.WriteLine(); } } }

Para "contar" no necesariamente hay que usar nmeros. Por ejemplo, podemos contar con letras as: /*---------------------------*/ /* Ejemplo en C# n 28: */ /* ejemplo28.cs */ /* */ /* "for" que usa "char" */ /*---------------------------*/ using System; public class Ejemplo28 { public static void Main() {

- 48 -

Programacin de Dispositivos Mviles

char letra; for (letra='a'; letra<='z'; letra++) Console.Write("{0} ", letra);

} }

En este caso, empezamos en la "a" y terminamos en la "z", aumentando de uno en uno. Si queremos contar de forma decreciente, o de dos en dos, o como nos interese, basta indicarlo en la condicin de finalizacin del "for" y en la parte que lo incrementa: /*---------------------------*/ /* Ejemplo en C# n 29: */ /* ejemplo29.cs */ /* */ /* "for" que descuenta */ /*---------------------------*/ using System; public class Ejemplo29 { public static void Main() { char letra; for (letra='z'; letra>='a'; letra--) Console.Write("{0} ", letra); } }

Ejercicios propuestos: 25. Crear un programa que muestre las letras de la Z (mayscula) a la A (mayscula, descendiendo). 26. Crear un programa que escriba en pantalla los nmeros del 1 al 50 que sean mltiplos de 3 (pista: habr que recorrer todos esos nmeros y ver si el resto de la divisin entre 3 resulta 0).

Sentencia break: termina el bucle


Podemos salir de un bucle "for" antes de tiempo con la orden "break": /*---------------------------*/ /* Ejemplo en C# n 30: */ /* ejemplo30.cs */ /* */ /* "for" interrumpido con */ /* "break" */ /*---------------------------*/ using System; public class Ejemplo30 { public static void Main() { int contador; for (contador=1; contador<=10; contador++) { if (contador==5) break; Console.Write("{0} ", contador); } } }

- 49 -

Programacin de Dispositivos Mviles

El resultado de este programa es: 1 2 3 4 (en cuanto se llega al valor 5, se interrumpe el "for", por lo que no se alcanza el valor 10).

Sentencia continue: fuerza la siguiente iteracin


Podemos saltar alguna repeticin de un bucle con la orden "continue": /*---------------------------*/ /* Ejemplo en C# n 31: */ /* ejemplo31.cs */ /* */ /* "for" interrumpido con */ /* "continue" */ /*---------------------------*/ using System; public class Ejemplo31 { public static void Main() { int contador; for (contador=1; contador<=10; contador++) { if (contador==5) continue; Console.Write("{0} ", contador); } } }

El resultado de este programa es: 1 2 3 4 6 7 8 9 10 En l podemos observar que no aparece el valor 5.

Sentencia goto
El lenguaje C# tambin permite la orden "goto", para hacer saltos incondicionales. Su uso indisciplinado est muy mal visto, porque puede ayudar a hacer programas llenos de saltos, difciles de seguir. Pero en casos concretos puede ser muy til, por ejemplo, para salir de un bucle muy anidado (un "for" dentro de otro "for" que a su vez est dentro de otro "for": en este caso, "break" slo saldra del "for" ms interno). El formato de "goto" es goto donde; y la posicin de salto se indica con su nombre seguido de dos puntos (:) donde: como en el siguiente ejemplo: /*---------------------------*/ /* Ejemplo en C# n 32: */ /* ejemplo32.cs */ /* */ /* "for" y "goto" */ /*---------------------------*/

- 50 -

Programacin de Dispositivos Mviles

using System; public class Ejemplo32 { public static void Main() { int i, j; for (i=0; i<=5; i++) for (j=0; j<=20; j+=2) { if ((i==1) && (j>=7)) goto salida; Console.WriteLine("i vale {0} y j vale {1}.", i, j); } salida: Console.Write("Fin del programa"); } } El resultado de este programa es: i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 0 y j vale i vale 1 y j vale i vale 1 y j vale i vale 1 y j vale i vale 1 y j vale Fin del programa 0. 2. 4. 6. 8. 10. 12. 14. 16. 18. 20. 0. 2. 4. 6.

Vemos que cuando i=1 y j>=7, se sale de los dos "for". Ejercicios propuestos: 27. Crear un programa que d al usuario la oportunidad de adivinar un nmero del 1 al 100 (prefijado en el programa) en un mximo de 6 intentos. En cada pasada deber avisar de si se ha pasado o se ha quedado corto. 28. Crear un programa que descomponga un nmero (que teclee el usuario) como producto de su factores primos. Por ejemplo, 60 = 2 2 3 5

Arrays, estructuras y cadenas de texto Conceptos bsicos sobre arrays o tablas, Definicin de un array y acceso a los datos
Una tabla, vector o array (que algunos autores traducen por "arreglo") es un conjunto de elementos, todos los cuales son del mismo tipo. Estos elementos tendrn todos el mismo nombre, y ocuparn un espacio contiguo en la memoria. Por ejemplo, si queremos definir un grupo de nmeros enteros, el tipo de datos que usaremos para declararlo ser "int[]". Si sabemos desde el principio cuantos datos tenemos (por ejemplo 4), les reservaremos espacio con "= new int[4]", as int[] ejemplo = new int[4]; Podemos acceder a cada uno de los valores individuales indicando su nombre (ejemplo) y el nmero de elemento que nos interesa, pero con una precaucin: se empieza a numerar desde 0, as que en el caso anterior tendramos 4 elementos, que seran ejemplo[0], ejemplo[1], ejemplo[2], ejemplo[3].

- 51 -

Programacin de Dispositivos Mviles

Como ejemplo, vamos a definir un grupo de 5 nmeros enteros y hallar su suma: /*---------------------------*/ /* Ejemplo en C# n 33: */ /* ejemplo33.cs */ /* */ /* Primer ejemplo de tablas */ /*---------------------------*/ using System; public class Ejemplo33 { public static void Main() { int[] numero = new int[5]; /* Un array de 5 nmeros enteros */ int suma; /* Un entero que ser la suma */ numero[0] = 200; /* Les damos valores */ numero[1] = 150; numero[2] = 100; numero[3] = -50; numero[4] = 300; suma = numero[0] + numero[1] + numero[2] + numero[3] + numero[4]; Console.WriteLine("Su suma es {0}", suma); /* Nota: esta es la forma ms ineficiente e incmoda */ /* Ya lo iremos mejorando */ } }

/* Y hallamos la suma */

Ejercicios propuestos: 29. Un programa que pida al usuario 4 nmeros, los memorice (utilizando una tabla), calcule su media aritmtica y la muestre en pantalla. 30. Un programa que pida al usuario 5 nmeros reales y luego los muestre en el orden contrario al que se introdujeron. 31. Un programa que pida al usuario 10 nmeros enteros y calcule (y muestre) cul es el mayor de ellos.

Valor inicial de un array


Al igual que ocurra con las variables "normales", podemos dar valor a los elementos de una tabla al principio del programa. Ser ms cmodo que dar los valores uno por uno, como hemos hecho antes, pero slo se podr hacer si conocemos todos los valores. En este caso, los indicaremos todos entre llaves, separados por comas: /*---------------------------*/ /* Ejemplo en C# n 34: */ /* ejemplo34.cs */ /* */ /* Segundo ejemplo de */ /* tablas */ /*---------------------------*/ using System; public class Ejemplo34 { public static void Main() { int[] numero = {200, 150, 100, -50, 300}; /* Un array de 5 nmeros enteros */ int suma; /* Un entero que ser la suma */ suma = numero[0] + numero[1] + numero[2] + numero[3] + numero[4]; /* Y hallamos la suma */ Console.WriteLine("Su suma es {0}", suma); /* Nota: esta forma es algo menos engorrosa, pero todava no */ /* est bien hecho. Lo seguiremos mejorando */ } }

- 52 -

Programacin de Dispositivos Mviles

Recorriendo los elementos de una tabla


Es de esperar que exista una forma ms cmoda de acceder a varios elementos de un array, sin tener siempre que repetirlos todos, como hemos hecho en suma = numero[0] + numero[1] + numero[2] + numero[3] + numero[4]; El "truco" consistir en emplear cualquiera de las estructuras repetitivas que ya hemos visto (while, do..while, for), por ejemplo as: suma = 0; /* Valor inicial de la suma */ for (i=0; i<=4; i++) /* Y hallamos la suma repetitiva */ suma += numero[i]; El fuente completo podra ser as: /*---------------------------*/ /* Ejemplo en C# n 35: */ /* ejemplo35.cs */ /* */ /* Tercer ejemplo de */ /* tablas */ /*---------------------------*/ using System; public class Ejemplo35 { public static void Main() { int[] numero = {200, 150, 100, -50, 300}; /* Un array de 5 nmeros enteros */ int suma; /* Un entero que ser la suma */ int i; /* Para recorrer los elementos */ suma = 0; /* Valor inicial de la suma */ for (i=0; i<=4; i++) /* Y hallamos la suma repetitiva */ suma += numero[i]; Console.WriteLine("Su suma es {0}", suma); } }

En este caso, que slo sumbamos 5 nmeros, no hemos escrito mucho menos, pero si trabajsemos con 100, 500 o 1000 nmeros, la ganancia en comodidad s que est clara.

Datos repetitivos introducidos por el usuario


Si queremos que sea el usuario el que introduzca datos a un array, usaramos otra estructura repetitiva ("for", por ejemplo) para pedrselos: /*---------------------------*/ /* Ejemplo en C# n 36: */ /* ejemplo36.cs */ /* */ /* Cuarto ejemplo de */ /* tablas */ /*---------------------------*/ using System; public class Ejemplo36 { public static void Main() { int[] numero = new int[5]; /* Un array de 5 nmeros enteros */ int suma; /* Un entero que ser la suma */ int i; /* Para recorrer los elementos */ for (i=0; i<=4; i++) /* Pedimos los datos */ { Console.Write("Introduce el dato numero {0}: ", i+1);

- 53 -

Programacin de Dispositivos Mviles

numero[i] = Convert.ToInt32(Console.ReadLine());

suma = 0; /* Valor inicial de la suma */ for (i=0; i<=4; i++) /* Y hallamos la suma repetitiva */ suma += numero[i]; Console.WriteLine("Su suma es {0}", suma); } }

Ejercicios propuestos: 32. Crear un programa que pida al usuario 10 nmeros y luego los muestre en orden inverso (del ltimo al primero). 33. Crear un programa que pida al usuario 10 nmeros, calcule su media y luego muestre los que estn por encima de la media. 34. Un programa que pida 10 nombres y los memorice (pista: esta vez se trata de un array de "string"). Despus deber pedir que se teclee un nombre y dir si se encuentra o no entre los 10 que se han tecleado antes. Volver a pedir otro nombre y a decir si se encuentra entre ellos, y as sucesivamente hasta que se teclee "fin". 35. Un programa que prepare espacio para un mximo de 100 nombres. El usuario deber ir introduciendo un nombre cada vez, hasta que se pulse Intro sin teclear nada, momento en el que dejarn de pedirse ms nombres y se mostrar en pantalla la lista de los nombres que se han introducido.

Tablas bidimensionales
Podemos declarar tablas de dos o ms dimensiones. Por ejemplo, si queremos guardar datos de dos grupos de alumnos, cada uno de los cuales tiene 20 alumnos, tenemos dos opciones:

Podemos usar int datosAlumnos[40] y entonces debemos recordar que los 20 primeros datos corresponden realmente a un grupo de alumnos y los 20 siguientes a otro grupo. Es "demasiado artesanal", as que no daremos ms detalles. O bien podemos emplear int datosAlumnos[2,20] y entonces sabemos que los datos de la forma datosAlumnos[0,i] son los del primer grupo, y los datosAlumnos[1,i] son los del segundo. Una alternativa, que puede sonar ms familiar a quien ya haya programado en C es emplear int datosAlumnos[2][20] pero en C# esto no tiene exactamente el mismo significado que [2,20], sino que se trata de dos arrays, cuyos elementos a su vez son arrays de 20 elementos. De hecho, podran ser incluso dos arrays de distinto tamao, como veremos en el segundo ejemplo. En cualquier caso, si queremos indicar valores iniciales, lo haremos entre llaves, igual que si fuera una tabla de una nica dimensin. Vamos a ver un primer ejemplo del uso con arrays de la forma [2,20], lo que podramos llamar el "estilo Pascal", en el usemos tanto arrays con valores prefijados, como arrays para los que reservemos espacio con "new" y a los que demos valores ms tarde: /*---------------------------*/ /* Ejemplo en C# n 37: */ /* ejemplo37.cs */ /* */ /* Array de dos dimensiones */ /* al estilo Pascal */ /*---------------------------*/ using System; public class Ejemplo37 { public static void Main() { int[,] notas1 = new int[2,2]; // 2 bloques de 2 datos notas1[0,0] = 1; notas1[0,1] = 2; notas1[1,0] = 3; notas1[1,1] = 4; int[,] notas2 = // 2 bloques de 10 datos { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {11, 12, 13, 14, 15, 16, 17, 18, 19, 20} };

- 54 -

Programacin de Dispositivos Mviles

} }

Console.WriteLine("La nota1 del segundo alumno del grupo 1 es {0}", notas1[0,1]); Console.WriteLine("La nota2 del tercer alumno del grupo 1 es {0}", notas2[0,2]);

Este tipo de tablas de varias dimensiones son las que se usan tambin para guardar matrices, cuando se trata de resolver problemas matemticos ms complejos que los que hemos visto hasta ahora. La otra forma de tener arrays multidimensionales son los "arrays de arrays", que, como ya hemos comentado, y como veremos en este ejemplo, pueden tener elementos de distinto tamao. En ese caso nos puede interesar saber su longitud, para lo que podemos usar "a.Length": /*---------------------------*/ /* Ejemplo en C# n 38: */ /* ejemplo38.cs */ /* */ /* Array de dos dimensiones */ /* al estilo C... o casi */ /*---------------------------*/ using System; public class Ejemplo38 { public static void Main() { int[][] notas; // Array de dos dimensiones notas = new int[3][]; // Seran 3 bloques de datos notas[0] = new int[10]; // 10 notas en un grupo notas[1] = new int[15]; // 15 notas en otro grupo notas[2] = new int[12]; // 12 notas en el ultimo // Damos valores de ejemplo for (int i=0;i<notas.Length;i++) { for (int j=0;j<notas[i].Length;j++) { notas[i][j] = i + j; } } // Y mostramos esos valores for (int i=0;i<notas.Length;i++) { for (int j=0;j<notas[i].Length;j++) { Console.Write(" {0}", notas[i][j]); } Console.WriteLine(); } } } La salida de este programa sera 0 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2 3 4 5 6 7 8 9 10 11 12 13 Ejercicios propuestos: 36. Un programa que al usuario dos bloques de 10 nmeros enteros (usando un array de dos dimensiones). Despus deber mostrar el mayor dato que se ha introducido en cada uno de ellos.

- 55 -

Programacin de Dispositivos Mviles

Estructuras o registros Definicin y acceso a los datos


Un registro es una agrupacin de datos, los cuales no necesariamente son del mismo tipo. Se definen con la palabra "struct". La serie de datos que van a formar. En C# (al contrario que en C), primero deberemos declarar cual va a ser la estructura de nuestro registro, lo que no se puede hacer dentro de "Main". Ms adelante, ya dentro de "Main", podremos declarar variables de ese nuevo tipo. Los datos que forman un "struct" pueden ser pblicos o privados. Por ahora, a nosotros nos interesar que sean accesibles desde el resto de nuestro programa, por lo que les aadiremos delante la palabra "public" para indicar que queremos que sean pblicos. Ya desde el cuerpo del programa, para acceder a cada uno de los datos que forman el registro, tanto si queremos leer su valor como si queremos cambiarlo, se debe indicar el nombre de la variable y el del dato (o campo) separados por un punto: /*---------------------------*/ /* Ejemplo en C# n 39: */ /* ejemplo39.cs */ /* */ /* Registros (struct) */ /*---------------------------*/ using System; public class Ejemplo39 { struct tipoPersona { public string nombre; public char inicial; public int edad; public float nota; } public static void Main() { tipoPersona persona; persona.nombre = "Juan"; persona.inicial = 'J'; persona.edad = 20; persona.nota = 7.5f; Console.WriteLine("La edad de {0} es {1}", persona.nombre, persona.edad); }

Nota: La notacin 7.5f se usa para detallar que se trata de un nmero real de simple precisin (un "float"), porque de lo contrario, 7.5 se considerara un nmero de doble precisin, y al tratar de compilar obtendramos un mensaje de error, diciendo que no se puede convertir de "double" a "float" sin prdida de precisin. Al aadir la "f" al final, estamos diciendo "quiero que ste nmero se tome como un float; s que habr una prdida de precisin pero es aceptable para m. Ejercicio propuesto

37. Realizar

un "struct" que almacene datos de una cancin en formato MP3: Artista, Ttulo, Duracin (en segundos), Tamao del fichero (en KB), el programa debe pedir los datos de una cancin al usuario, almacenarlos en dicho "struct" y despus mostrarlos en pantalla.

Arrays de estructuras
Hemos guardado varios datos de una persona. Se pueden almacenar los de varias personas si combinamos el uso de los "struct" con las tablas (arrays) que vimos anteriormente. Por ejemplo, si queremos guardar los datos de 100 personas podramos hacer: /*---------------------------*/ /* Ejemplo en C# n 40: */ /* ejemplo40.cs */

- 56 -

Programacin de Dispositivos Mviles

/* */ /* Array de struct */ /*---------------------------*/ using System; public class Ejemplo40 { struct tipoPersona { public string nombre; public char inicial; public int edad; public float nota; } public static void Main() { tipoPersona[] persona = new tipoPersona[100]; persona[0].nombre = "Juan"; persona[0].inicial = 'J'; persona[0].edad = 20; persona[0].nota = 7.5f; Console.WriteLine("La edad de {0} es {1}", persona[0].nombre, persona[0].edad); persona[1].nombre = "Pedro"; Console.WriteLine("La edad de {0} es {1}", persona[1].nombre, persona[1].edad); } } La inicial de la primera persona sera "persona[0].inicial", y la edad del ltimo sera "persona[99].edad". Al probar este programa obtenemos La edad de Juan es 20 La edad de Pedro es 0 Porque cuando reservamos espacio para los elementos de un "array" usando "new", sus valores se dejan "vacos" (0 para los nmeros, cadenas vacas para las cadenas de texto). Ejercicio propuesto: 38. Un programa que permita guardar datos de "imgenes" (ficheros de ordenador que contengan fotografas o cualquier otro tipo de informacin grfica). De cada imagen se debe guardar: nombre (texto), ancho en pxeles (por ejemplo 2000), alto en pxeles (por ejemplo, 3000), tamao en Kb (por ejemplo 145,6). El programa debe ser capaz de almacenar hasta 700 imgenes (deber avisar cuando su capacidad est llena). Debe permitir las opciones: aadir una ficha nueva, ver todas las fichas (nmero y nombre de cada imagen), buscar la ficha que tenga un cierto nombre.

Estructuras anidadas
Podemos encontrarnos con un registro que tenga varios datos, y que a su vez ocurra que uno de esos datos est formado por varios datos ms sencillos. Por ejemplo, una fecha de nacimiento podra estar formada por da, mes y ao. Para hacerlo desde C#, incluiramos un "struct" dentro de otro, as: /*---------------------------*/ /* Ejemplo en C# n 41: */ /* ejemplo41.cs */ /* */ /* Registros anidados */ /*---------------------------*/ using System; public class Ejemplo41 {

- 57 -

Programacin de Dispositivos Mviles

struct fechaNacimiento { public int dia; public int mes; public int anyo; } struct tipoPersona { public string nombre; public char inicial; public fechaNacimiento diaDeNacimiento; public float nota; } public static void Main() { tipoPersona persona; persona.nombre = "Juan"; persona.inicial = 'J'; persona.diaDeNacimiento.dia = 15; persona.diaDeNacimiento.mes = 9; persona.nota = 7.5f; Console.WriteLine("{0} naci en el mes {1}", persona.nombre, persona.diaDeNacimiento.mes); }

Cadenas de caracteres Definicin. Lectura desde teclado


Hemos visto cmo leer cadenas de caracteres (Console.ReadLine) y cmo mostrarlas en pantalla (Console.Write), as como la forma de darles un valor(=). Tambin podemos comparar cual es su valor, usando ==, o formar una cadena a partir de otras si las unimos con el smbolo de la suma (+): As, un ejemplo que nos pidiese nuestro nombre y nos saludase usando todas estas posibilidades podra ser: /*---------------------------*/ /* Ejemplo en C# n 42: */ /* ejemplo42.cs */ /* */ /* Cadenas de texto (1) */ /*---------------------------*/ using System; public class Ejemplo42 { public static void Main() { string saludo = "Hola"; string segundoSaludo; string nombre, despedida; segundoSaludo = "Que tal?"; Console.WriteLine("Dime tu nombre... "); nombre = Console.ReadLine(); Console.WriteLine("{0} {1}", saludo, nombre); Console.WriteLine(segundoSaludo); if (nombre == "Alberto") Console.WriteLine("Dices que eres Alberto?"); else Console.WriteLine("As que no eres Alberto?");

- 58 -

Programacin de Dispositivos Mviles

despedida = "Adios " + nombre + "!"; Console.WriteLine(despedida); } }

Cmo acceder a las letras que forman una cadena


Podemos leer (o modificar) una de las letras de una cadena de igual forma que leemos los elementos de cualquier array: si la cadena se llama "texto", el primer elemento ser texto[0], el segundo ser texto[1] y as sucesivamente. Eso s, las cadenas en C# no se pueden modificar letra a letra: no podemos hacer texto[0]=a. Para eso habr que usar una construccin auxiliar, que veremos ms adelante.

Longitud de la cadena.
Podemos saber cuantas letras forman una cadena con "cadena.Length". Esto permite que podamos recorrer la cadena letra por letra, usando construcciones como "for". Ejercicio propuesto: Un programa te pida tu nombre y lo muestre en pantalla separando cada letra de la siguiente con un espacio. Por ejemplo, si tu nombre es "Juan", debera aparecer en pantalla "J u a n".

Extraer una subcadena


Podemos extraer parte del contenido de una cadena con "Substring", que recibe dos parmetros: la posicin a partir de la que queremos empezar y la cantidad de caracteres que queremos obtener. El resultado ser otra cadena: saludo = frase.Substring(0,4); Podemos omitir el segundo nmero, y entonces se extraer desde la posicin indicada hasta el final de la cadena.

Buscar en una cadena


Para ver si una cadena contiene un cierto texto, podemos usar IndexOf ("posicin de"), que nos dice en qu posicin se encuentra (o devuelve el valor -1 si no aparece): if (nombre.IndexOf("Juan") >= 0) Console.Write("Bienvenido, Juan"); Podemos aadir un segundo parmetro opcional, que es la posicin a partir de la que queremos buscar: if (nombre.IndexOf("Juan", 5) >= 0) ... La bsqueda termina al final de la cadena, salvo que indiquemos que termine antes con un tercer parmetro opcional: if (nombre.IndexOf("Juan", 5, 15) >= 0) ... De forma similar, LastIndexOf ("ltima posicin de") indica la ltima aparicin (es decir, busca de derecha a izquierda).

Otras manipulaciones de cadenas


Ya hemos comentado que las cadenas en C# son inmutables, no se pueden modificar. Pero s podemos realizar ciertas operaciones sobre ellas para obtener una nueva cadena. Por ejemplo:

ToUpper() convierte a maysculas: nombreCorrecto = nombre.ToUpper(); ToLower() convierte a minsculas: password2 = password.ToLower();

Insert(int posicin, string subcadena): Insertar una subcadena en una cierta posicin de la cadena inicial: nombreFormal = nombre.Insert(0,"Don"); Remove(int posicin, int cantidad): Elimina una cantidad de caracteres en cierta posicin: apellidos = nombreCompleto.Remove(0,6); Replace(string textoASustituir, string cadenaSustituta): Sustituye una cadena (todas las veces que aparezca) por otra: nombreCorregido = nombre.Replace("Pepe", "Jose"); Un programa que probara todas estas posibilidades podra ser as: /*---------------------------*/ /* Ejemplo en C# n 43: */ /* ejemplo43.cs */

- 59 -

Programacin de Dispositivos Mviles

/* */ /* Cadenas de texto (2) */ /*---------------------------*/ using System; public class Ejemplo43 { public static void Main() { string ejemplo = "Hola, que tal estas"; Console.WriteLine("El texto es: {0}", ejemplo); Console.WriteLine("La primera letra es: {0}", ejemplo[0]); Console.WriteLine("Las tres primeras letras son: {0}", ejemplo.Substring(0,3)); Console.WriteLine("La longitud del texto es: {0}", ejemplo.Length); Console.WriteLine("La posicion de \"que\" es: {0}", ejemplo.IndexOf("que")); Console.WriteLine("La ultima A esta en la posicion: {0}", ejemplo.LastIndexOf("a")); Console.WriteLine("En maysculas: {0}", ejemplo.ToUpper()); Console.WriteLine("En minsculas: {0}", ejemplo.ToLower()); Console.WriteLine("Si insertamos \", tio\": {0}", ejemplo.Insert(4,", tio")); Console.WriteLine("Si borramos las 6 primeras letras: {0}", ejemplo.Remove(0, 6)); Console.WriteLine("Si cambiamos ESTAS por ESTAMOS: {0}", ejemplo.Replace("estas", "estamos")); } } Y su resultado sera El texto es: Hola, que tal estas La primera letra es: H Las tres primeras letras son: Hol La longitud del texto es: 19 La posicion de "que" es: 6 La ultima A esta en la posicion: 17 En maysculas: HOLA, QUE TAL ESTAS En minsculas: hola, que tal estas Si insertamos ", tio": Hola, tio, que tal estas Si borramos las 6 primeras letras: que tal estas Si cambiamos ESTAS por ESTAMOS: Hola, que tal estamos Otra posibilidad interesante, aunque un poco ms avanzada, es la de descomponer una cadena en trozos, que estn separados por una serie de delimitadores (por ejemplo, espacios o comas). Para ello se puede usar Split, que crea un array a partir de los fragmentos de la cadena, as:

- 60 -

Programacin de Dispositivos Mviles

/*---------------------------*/ /* Ejemplo en C# n 43b: */ /* ejemplo43b.cs */ /* */ /* Cadenas de texto (2b) */ /*---------------------------*/ using System; public class Ejemplo43b { public static void Main() { string ejemplo = "uno,dos.tres,cuatro"; char [] delimitadores = {',', '.'}; int i; string [] ejemploPartido = ejemplo.Split(delimitadores); for (i=0; i<ejemploPartido.Length; i++) Console.WriteLine("Fragmento {0}= {1}", i, ejemploPartido[i]); } } Que mostrara en pantalla lo siguiente: Fragmento Fragmento Fragmento Fragmento 0= 1= 2= 3= uno dos tres cuatro

Comparacin de cadenas
Sabemos comprobar si una cadena tiene exactamente un cierto valor, con el operador de igualdad (==), pero no sabemos comparar qu cadena es "mayor" que otra, algo que es necesario si queremos ordenar textos. El operador "mayor que" (>) que usamos con los nmeros no se puede aplicar directamente a las cadenas. En su lugar, debemos usar "CompareTo", que devolver un nmero mayor que 0 si la nuestra cadena es mayor que la que indicamos como parmetro (o un nmero negativo si nuestra cadena es menor, o 0 si son iguales): if (frase.CompareTo("hola") > 0) Console.WriteLine("Es mayor que hola"); Tambin podemos comparar sin distinguir entre maysculas y minsculas, usando String.Compare, al que indicamos las dos cadenas y un tercer dato "true" cuando queramos ignorar esa distincin: if (String.Compare(frase, "hola", true) > 0) Console.WriteLine("Es mayor que hola (mays o mins)"); Un programa completo de prueba podra ser as: /*---------------------------*/ /* Ejemplo en C# n 43c: */ /* ejemplo43c.cs */ /* */ /* Cadenas de texto (2c) */ /*---------------------------*/ using System; public class Ejemplo43c { public static void Main() {

- 61 -

Programacin de Dispositivos Mviles

string frase; Console.WriteLine("Escriba una palabra"); frase = Console.ReadLine(); // Compruebo si es exactamente hola if (frase == "hola") Console.WriteLine("Ha escrito hola"); // Compruebo si es mayor o menor if (frase.CompareTo("hola") > 0) Console.WriteLine("Es mayor que hola"); else if (frase.CompareTo("hola") < 0) Console.WriteLine("Es menor que hola"); // Comparo sin distinguir maysculas ni minsculas bool ignorarMays = true; if (String.Compare(frase, "hola", ignorarMays) > 0) Console.WriteLine("Es mayor que hola (mays o mins)"); else if (String.Compare(frase, "hola", ignorarMays) < 0) Console.WriteLine("Es menor que hola (mays o mins)"); else Console.WriteLine("Es hola (mays o mins)"); } }

Si tecleamos una palabra como "gol", que comienza por G, que alfabticamente est antes de la H de "hola", se nos dir que esa palabra es menor: Escriba una palabra gol Es menor que hola Es menor que hola (mays o mins) Si escribimos "hOLa", que coindice con "hola" salvo por las maysculas, una comparacin normal nos dir que es mayor (las maysculas se consideran "mayores" que las minsculas), y una comparacin sin considerar maysculas o minsculas nos dir que coinciden: Escriba una palabra hOLa Es mayor que hola Es hola (mays o mins)

Una cadena modificable: StringBuilder


Si tenemos la necesidad de poder modificar una cadena letra a letra, no podemos usar un "string" convencional, deberemos recurrir a un "StringBuilder", que s lo permiten pero son algo ms complejos de manejar: hay de reservarles espacio con "new" (igual que hacamos en ciertas ocasiones con los Arrays), y se pueden convertir a una cadena "convencional" usando "ToString": /*---------------------------*/ /* Ejemplo en C# n 44: */ /* ejemplo44.cs */ /* */ /* Cadenas modificables */ /* con "StringBuilder" */ /*---------------------------*/ using System; using System.Text; // Usaremos un System.Text.StringBuilder public class Ejemplo44 { public static void Main() { StringBuilder cadenaModificable = new StringBuilder("Hola"); cadenaModificable[0] = 'M'; Console.WriteLine("Cadena modificada: {0}", cadenaModificable); string cadenaNormal;

- 62 -

Programacin de Dispositivos Mviles

} }

cadenaNormal = cadenaModificable.ToString(); Console.WriteLine("Cadena normal a partir de ella: {0}", cadenaNormal);

Ejercicio propuesto: 39. Un programa que pida tu nombre, tu da de nacimiento y tu mes de nacimiento y lo junte todo en una cadena, separando el nombre de la fecha por una coma y el da del mes por una barra inclinada, as: "Juan, nacido el 31/12".

Recorriendo con "foreach"


Existe una construccin parecida a "for", pensada para recorrer ciertas estructuras de datos, como los arrays (y otras que veremos ms adelante). Se usa con el formato "foreach (variable in ConjuntoDeValores)": /*---------------------------*/ /* Ejemplo en C# n 45: */ /* ejemplo45.cs */ /* */ /* Ejemplo de "foreach" */ /*---------------------------*/ using System; public class Ejemplo45 { public static void Main() { int[] diasMes = {31, 28, 21}; foreach(int dias in diasMes) { Console.WriteLine("Dias del mes: {0}", dias); } string[] nombres = {"Alberto", "Andrs", "Antonio"}; foreach(string nombre in nombres) { Console.Write(" {0}", nombre); } Console.WriteLine(); string saludo = "Hola"; foreach(char letra in saludo) { Console.Write("{0}-", letra); } Console.WriteLine(); } }

Ejemplo completo
Vamos a hacer un ejemplo completo que use tablas ("arrays"), registros ("struct") y que adems manipule cadenas. La idea va a ser la siguiente: Crearemos un programa que pueda almacenar datos de hasta 1000 ficheros. Para cada fichero, debe guardar los siguientes datos: Nombre del fichero, Tamao (en KB, un nmero de 0 a 8.000.000.000). El programa mostrar un men que permita al usuario las siguientes operaciones:

12345-

Aadir datos de un nuevo fichero Mostrar los nombres de todos los ficheros almacenados Mostrar ficheros que sean de ms de un cierto tamao (por ejemplo, 2000 KB). Ver todos los datos de un cierto fichero (a partir de su nombre) Salir de la aplicacin (como no usamos ficheros, los datos se perdern).

- 63 -

Programacin de Dispositivos Mviles

No debera resultar difcil. Vamos a ver directamente una de las formas en que se podra plantear y luego comentaremos alguna de las mejoras que se podra (incluso se debera) hacer. Una opcin que podemos a tomar para resolver este problema es la de contar el nmero de fichas que tenemos almacenadas, y as podremos aadir de una en una. Si tenemos 0 fichas, deberemos almacenar la siguiente (la primera) en la posicin 0; si tenemos dos fichas, sern la 0 y la 1, luego aadiremos en la posicin 2; en general, si tenemos "n" fichas, aadiremos cada nueva ficha en la posicin "n". Por otra parte, para revisar todas las fichas, recorreremos desde la posicin 0 hasta la n-1, haciendo algo como for (i=0; i<=n-1; i++) { /* ... ms rdenes ... */ } o bien algo como for (i=0; i<n; i++) { /* ... ms rdenes ...} */ El resto del programa no es difcil: sabemos leer y comparar textos y nmeros, comprobar varias opciones con "switch", etc. Aun as, haremos una ltima consideracin: hemos limitado el nmero de fichas a 1000, as que, si nos piden aadir, deberamos asegurarnos antes de que todava tenemos hueco disponible. Con todo esto, nuestro fuente quedara as: /*---------------------------*/ /* Ejemplo en C# n 46: */ /* ejemplo46.cs */ /* */ /* Tabla con muchos struct */ /* y menu para manejarla */ /*---------------------------*/ using System; public class Ejemplo46 { struct tipoFicha { public string nombreFich; public long tamanyo; }; /* Nombre del fichero */ /* El tamao en bytes */

public static void Main() { tipoFicha[] fichas /* Los datos en si */ = new tipoFicha[1000]; int numeroFichas=0; /* Nmero de fichas que ya tenemos */ int i; /* Para bucles */ int opcion; /* La opcion del menu que elija el usuario */ string textoBuscar; /* Para cuando preguntemos al usuario */ long tamanyoBuscar; /* Para buscar por tamao */ do { /* Menu principal */ Console.WriteLine(); Console.WriteLine("Escoja una opcin:"); Console.WriteLine("1.- Aadir datos de un nuevo fichero"); Console.WriteLine("2.- Mostrar los nombres de todos los ficheros"); Console.WriteLine("3.- Mostrar ficheros que sean de mas de un cierto tamao"); Console.WriteLine("4.- Ver datos de un fichero"); Console.WriteLine("5.- Salir"); opcion = Convert.ToInt32( Console.ReadLine() ); /* Hacemos una cosa u otra segn la opcin escogida */ switch(opcion){ case 1: /* Aadir un dato nuevo */ if (numeroFichas < 1000) { /* Si queda hueco */ Console.WriteLine("Introduce el nombre del fichero: "); fichas[numeroFichas].nombreFich = Console.ReadLine(); Console.WriteLine("Introduce el tamao en KB: ");

- 64 -

Programacin de Dispositivos Mviles

fichas[numeroFichas].tamanyo = Convert.ToInt32( Console.ReadLine() ); /* Y ya tenemos una ficha ms */ numeroFichas++; } else /* Si no hay hueco para ms fichas, avisamos */ Console.WriteLine("Mximo de fichas alcanzado (1000)!"); break; case 2: /* Mostrar todos */ for (i=0; i<numeroFichas; i++) Console.WriteLine("Nombre: {0}; Tamao: {1} Kb", fichas[i].nombreFich, fichas[i].tamanyo); break; case 3: /* Mostrar segn el tamao */ Console.WriteLine("A partir de que tamao quieres que te muestre?"); tamanyoBuscar = Convert.ToInt64( Console.ReadLine() ); for (i=0; i<numeroFichas; i++) if (fichas[i].tamanyo >= tamanyoBuscar) Console.WriteLine("Nombre: {0}; Tamao: {1} Kb", fichas[i].nombreFich, fichas[i].tamanyo); break; case 4: /* Ver todos los datos (pocos) de un fichero */ Console.WriteLine("De qu fichero quieres ver todos los datos?"); textoBuscar = Console.ReadLine(); for (i=0; i<numeroFichas; i++) if ( fichas[i].nombreFich == textoBuscar ) Console.WriteLine("Nombre: {0}; Tamao: {1} Kb", fichas[i].nombreFich, fichas[i].tamanyo); break; case 5: /* Salir: avisamos de que salimos */ Console.WriteLine("Fin del programa"); break; default: /* Otra opcion: no vlida */ Console.WriteLine("Opcin desconocida!"); break; } } while (opcion != 5); /* Si la opcion es 5, terminamos */ } }

Funciona, y hace todo lo que tiene que hacer, pero es mejorable. Por supuesto, en un caso real es habitual que cada ficha tenga que guardar ms informacin que slo esos dos apartados de ejemplo que hemos previsto esta vez. Si nos muestra todos los datos en pantalla y se trata de muchos datos, puede ocurrir que aparezcan en pantalla tan rpido que no nos d tiempo a leerlos, as que sera deseable que parase cuando se llenase la pantalla de informacin (por ejemplo, una pausa tras mostrar cada 25 datos). Por supuesto, se nos pueden ocurrir muchas ms preguntas que hacerle sobre nuestros datos. Y adems, cuando salgamos del programa se borrarn todos los datos que habamos tecleado, pero eso es lo nico "casi inevitable", porque an no sabemos manejar ficheros. Ejercicios propuestos: 40. Un programa que sea capaz de almacenar los datos de 50 personas: nombre, direccin, telfono, edad (usando una tabla de structs). Deber ir pidiendo los datos uno por uno, hasta que un nombre se introduzca vaco (se pulse Intro sin teclear nada). Entonces deber aparecer un men que permita: Mostrar la lista de todos los nombres.

Mostrar las personas de una cierta edad. Mostrar las personas cuya inicial sea la que el usuario indique. Salir del programa (lgicamente, este men debe repetirse hasta que se escoja la opcin de "salir").

Ordenaciones simples
Es muy frecuente querer ordenar datos que tenemos en un array. Para conseguirlo, existen varios algoritmos sencillos, que no son especialmente eficientes, pero son fciles de programar. La falta de eficiencia se refiere a que la mayora de ellos se basan en dos bucles "for" anidados, de modo que en cada pasada quede ordenado un dato, y se dan tantas pasadas como datos existen, de modo que para un array con 1.000 datos, podran llegar a tener que hacerse un milln de comparaciones. Existen ligeras mejoras (por ejemplo, cambiar uno de los "for" por un "while", para no repasar todos los datos si ya estaban parcialmente ordenados), as como mtodos claramente ms efectivos, pero ms difciles de programar, alguno de los cuales veremos ms adelante.

- 65 -

Programacin de Dispositivos Mviles

Veremos tres de estos mtodos simples de ordenacin, primero mirando la apariencia que tiene el algoritmo, y luego juntando los tres en un ejemplo que los pruebe:

Mtodo de burbuja
(Intercambiar cada pareja consecutiva que no est ordenada) Para i=1 hasta n-1 Para j=i+1 hasta n Si A[i] > A[j] Intercambiar ( A[i], A[j]) (Nota: algunos autores hacen el bucle exterior creciente y otros decreciente, as:) Para i=n descendiendo hasta 2 Para j=2 hasta i Si A[j-1] > A[j] Intercambiar ( A[j-1], A[j])

Seleccin directa
(En cada pasada busca el menor, y lo intercambia al final de la pasada) Para i=1 hasta n-1 menor = i Para j=i+1 hasta n Si A[j] < A[menor] menor = j Si menor <> i Intercambiar ( A[i], A[menor]) Nota: el smbolo "<>" se suele usar en pseudocdigo para indicar que un dato es distinto de otro, de modo que equivale al "!=" de C#. La penltima lnea en C# saldra a ser algo como "if (menor !=i)"

Insercin directa
(Comparar cada elemento con los anteriores -que ya estn ordenados- y desplazarlo hasta su posicin correcta). Para i=2 hasta n j=i-1 mientras (j>=1) y (A[j] > A[j+1]) Intercambiar ( A[j], A[j+1]) j = j - 1 (Es mejorable, no intercambiando el dato que se mueve con cada elemento, sino slo al final de cada pasada, pero no entraremos en ms detalles). Un programa de prueba podra ser: /*---------------------------*/ /* Ejemplo en C# */ /* ordenar.cs */ /* */ /* Ordenaciones simples */ /*---------------------------*/ using System; public class Ordenar { public static void Main() { int[] datos = {5, 3, 14, 20, 8, 9, 1}; int i,j,datoTemporal; int n=7; // Numero de datos

- 66 -

Programacin de Dispositivos Mviles

// BURBUJA // (Intercambiar cada pareja consecutiva que no est ordenada) // Para i=1 hasta n-1 // Para j=i+1 hasta n // Si A[i] > A[j] // Intercambiar ( A[i], A[j]) Console.WriteLine("Ordenando mediante burbuja... "); for(i=0; i < n-1; i++) { foreach (int dato in datos) // Muestro datos Console.Write("{0} ",dato); Console.WriteLine(); for(j=i+1; j < n; j++) { { if (datos[i] > datos[j]) datoTemporal = datos[i]; datos[i] = datos[j]; datos[j] = datoTemporal;

} }

} Console.Write("Ordenado:"); foreach (int dato in datos) // Muestro datos finales Console.Write("{0} ",dato); Console.WriteLine(); // SELECCIN DIRECTA: // (En cada pasada busca el menor, y lo intercambia al final de la pasada) // Para i=1 hasta n-1 // menor = i // Para j=i+1 hasta n // Si A[j] < A[menor] // menor = j // Si menor <> i // Intercambiar ( A[i], A[menor]) Console.WriteLine("\nOrdenando mediante seleccin directa... "); int[] datos2 = {5, 3, 14, 20, 8, 9, 1}; for(i=0; i < n-1; i++) { foreach (int dato in datos2) // Muestro datos Console.Write("{0} ",dato); Console.WriteLine(); int menor = i; for(j=i+1; j < n; j++) if (datos2[j] < datos2[menor]) menor = j; if (i != menor) { datoTemporal = datos2[i]; datos2[i] = datos2[menor]; datos2[menor] = datoTemporal; }

} Console.Write("Ordenado:");

foreach (int dato in datos2) // Muestro datos finales Console.Write("{0} ",dato); Console.WriteLine(); // // // // // INSERCION DIRECTA: (Comparar cada elemento con los anteriores -que ya estn ordenadosy desplazarlo hasta su posicin correcta). Para i=2 hasta n j=i-1

- 67 -

Programacin de Dispositivos Mviles

// mientras (j>=1) y (A[j] > A[j+1]) // Intercambiar ( A[j], A[j+1]) // j = j - 1 Console.WriteLine("\nOrdenando mediante insercin directa... "); int[] datos3 = {5, 3, 14, 20, 8, 9, 1}; for(i=1; i < n; i++) { foreach (int dato in datos3) // Muestro datos Console.Write("{0} ",dato); Console.WriteLine(); j = i-1; while ((j>=0) && (datos3[j] > datos3[j+1])) { datoTemporal = datos3[j]; datos3[j] = datos3[j+1]; datos3[j+1] = datoTemporal; j--; } } Console.Write("Ordenado:"); foreach (int dato in datos3) // Muestro datos finales Console.Write("{0} ",dato); Console.WriteLine(); } }

Y su resultado sera: Ordenando mediante burbuja... 5 3 14 20 8 9 1 1 5 14 20 8 9 3 1 3 14 20 8 9 5 1 3 5 20 14 9 8 1 3 5 8 20 14 9 1 3 5 8 9 20 14 Ordenado:1 3 5 8 9 14 20 Ordenando mediante seleccin directa... 5 3 14 20 8 9 1 1 3 14 20 8 9 5 1 3 14 20 8 9 5 1 3 5 20 8 9 14 1 3 5 8 20 9 14 1 3 5 8 9 20 14 Ordenado:1 3 5 8 9 14 20 Ordenando mediante insercin directa... 5 3 14 20 8 9 1 3 5 14 20 8 9 1 3 5 14 20 8 9 1 3 5 14 20 8 9 1 3 5 8 14 20 9 1 3 5 8 9 14 20 1 Ordenado:1 3 5 8 9 14 20

Funciones Diseo modular de programas: Descomposicin modular


Hasta ahora hemos estado pensando los pasos que deberamos dar para resolver un cierto problema, y hemos creado programas a partir de cada uno de esos pasos. Esto es razonable cuando los problemas son sencillos, pero puede no ser la mejor forma de actuar cuando se trata de algo ms complicado. A partir de ahora vamos a empezar a intentar descomponer los problemas en trozos ms pequeos, que sean ms fciles de resolver. Esto nos puede suponer varias ventajas:

- 68 -

Programacin de Dispositivos Mviles

Cada "trozo de programa" independiente ser ms fcil de programar, al realizar una funcin breve y concreta.

El "programa principal" ser ms fcil de leer, porque no necesitar contener todos los detalles de cmo se hace cada cosa. Podremos repartir el trabajo, para que cada persona se encargue de realizar un "trozo de programa", y finalmente se integrar el trabajo individual de cada persona. Esos "trozos" de programa son lo que suele llamar "subrutinas", "procedimientos" o "funciones". En el lenguaje C y sus derivados, el nombre que ms se usa es el de funciones.

Conceptos bsicos sobre funciones


En C#, al igual que en C y los dems lenguajes derivados de l, todos los "trozos de programa" son funciones, incluyendo el propio cuerpo de programa, Main. De hecho, la forma bsica de definir una funcin ser indicando su nombre seguido de unos parntesis vacos, como hacamos con "Main", y precedindolo por ciertas palabras reservadas, como "public static void", cuyo significado iremos viendo muy pronto. Despus, entre llaves indicaremos todos los pasos que queremos que d ese "trozo de programa". Por ejemplo, podramos crear una funcin llamada "saludar", que escribiera varios mensajes en la pantalla: public static void saludar() { Console.WriteLine("Bienvenido al programa"); Console.WriteLine(" de ejemplo"); Console.WriteLine("Espero que ests bien"); } Ahora desde dentro del cuerpo de nuestro programa, podramos "llamar" a esa funcin: public static void Main() { saludar(); } As conseguimos que nuestro programa principal sea ms fcil de leer. Un detalle importante: tanto la funcin habitual "Main" como la nueva funcin "Saludar" seran parte de nuestra "class", es decir, el fuente completo sera as: /*---------------------------*/ /* Ejemplo en C# n 47: */ /* ejemplo47.cs */ /* */ /* Funcion "saludar" */ /*---------------------------*/ using System; public class Ejemplo47 { public static void Saludar() { Console.WriteLine("Bienvenido al programa"); Console.WriteLine(" de ejemplo"); Console.WriteLine("Espero que ests bien"); } public static void Main() { Saludar(); Console.WriteLine("Nada ms por hoy..."); } }

- 69 -

Programacin de Dispositivos Mviles

Como ejemplo ms detallado, la parte principal de una agenda podra ser simplemente: leerDatosDeFichero(); do { mostrarMenu(); pedirOpcion(); switch( opcion ) { case 1: buscarDatos(); break; case 2: modificarDatos(); break; case 3: anadirDatos(); break;

Parmetros de una funcin


Es muy frecuente que nos interese adems indicarle a nuestra funcin ciertos datos especiales con los que queremos que trabaje. Por ejemplo, si escribimos en pantalla nmeros reales con frecuencia, nos puede resultar til que nos los muestre con el formato que nos interese. Lo podramos hacer as: public static void escribeNumeroReal( float n ) { Console.WriteLine( n.ToString("#.###") ); } Y esta funcin se podra usar desde el cuerpo de nuestro programa as: escribeNumeroReal(2.3f); (recordemos que el sufijo "f" es para indicar al compilador que trate ese nmero como un "float", porque de lo contrario, al ver que tiene cifras decimales, lo tomara como "double", que permite mayor precisin... pero a cambio nosotros tendramos un mensaje de error en nuestro programa, diciendo que estamos dando un dato "double" a una funcin que espera un "float"). El programa completo podra quedar as: /*---------------------------*/ /* Ejemplo en C# n 48: */ /* ejemplo48.cs */ /* */ /* Funcion */ /* "escribeNumeroReal" */ /*---------------------------*/ using System; public class Ejemplo48 { public static void escribeNumeroReal( float n ) { Console.WriteLine( n.ToString("#.###") ); } public static void Main() { float x; x= 5.1f; Console.WriteLine("El primer numero real es: "); escribeNumeroReal(x); Console.WriteLine(" y otro distinto es: "); escribeNumeroReal(2.3f);

} }

Estos datos adicionales que indicamos a la funcin es lo que llamaremos sus "parmetros". Como se ve en el ejemplo, tenemos que indicar un nombre para cada parmetro (puede haber varios) y el tipo de datos que corresponde a ese parmetro. Si hay ms de un parmetro, deberemos indicar el tipo y el nombre para cada uno de ellos, y separarlos entre comas:

- 70 -

Programacin de Dispositivos Mviles

public static void sumar ( int x, int y ) { ... }

Valor devuelto por una funcin. El valor "void".


Cuando queremos dejar claro que una funcin no tiene que devolver ningn valor, podemos hacerlo indicando al principio que el tipo de datos va a ser "void" (nulo), como hacamos hasta ahora con "Main" y como hicimos con nuestra funcin "saludar". Pero eso no es lo que ocurre con las funciones matemticas que estamos acostumbrados a manejar: s devuelven un valor, el resultado de una operacin. De igual modo, para nosotros tambin ser habitual que queramos que nuestra funcin realice una serie de clculos y nos "devuelva" (return, en ingls) el resultado de esos clculos, para poderlo usar desde cualquier otra parte de nuestro programa. Por ejemplo, podramos crear una funcin para elevar un nmero entero al cuadrado as: public static int cuadrado ( int n ) { return n*n; } y podramos usar el resultado de esa funcin como si se tratara de un nmero o de una variable, as: resultado = cuadrado( 5 ); Un programa ms detallado de ejemplo podra ser: /*---------------------------*/ /* Ejemplo en C# n 49: */ /* ejemplo49.cs */ /* */ /* Funcion "cuadrado" */ /*---------------------------*/ using System; public class Ejemplo49 { public static int cuadrado ( int n ) { return n*n; } public static void Main() { int numero; int resultado; numero= 5; resultado = cuadrado(numero); Console.WriteLine("El cuadrado del numero {0} es {1}", numero, resultado); Console.WriteLine(" y el de 3 es {0}", cuadrado(3));

} }

Podemos hacer una funcin que nos diga cual es el mayor de dos nmeros reales as: public static float mayor ( float n1, float n2 ) { if (n1 > n2) return n1; else return n2;

- 71 -

Programacin de Dispositivos Mviles

Ejercicios propuestos: 42. Crear una funcin que calcule el cubo de un nmero real (float). El resultado deber ser otro nmero real. Probar esta funcin para calcular el cubo de 3.2 y el de 5. 43. Crear una funcin que calcule cual es el menor de dos nmeros enteros. El resultado ser otro nmero entero.

Variables locales y variables globales


Hasta ahora, hemos declarado las variables dentro de "Main". Ahora nuestros programas tienen varios "bloques", as que se comportarn de forma distinta segn donde declaremos las variables. Las variables se pueden declarar dentro de un bloque (una funcin), y entonces slo ese bloque las conocer, no se podrn usar desde ningn otro bloque del programa. Es lo que llamaremos "variables locales". Por el contrario, si declaramos una variable al comienzo del programa, fuera de todos los "bloques" de programa, ser una "variable global", a la que se podr acceder desde cualquier parte. Vamos a verlo con un ejemplo. Crearemos una funcin que calcule la potencia de un nmero entero (un nmero elevado a otro), y el cuerpo del programa que la use. La forma de conseguir elevar un nmero a otro ser a base de multiplicaciones, es decir: 3 elevado a 5 = 3 3 3 3 3

(multiplicamos 5 veces el 3 por s mismo). En general, como nos pueden pedir cosas como "6 elevado a 100" (o en general nmeros que pueden ser grandes), usaremos la orden "for" para multiplicar tantas veces como haga falta: /*---------------------------*/ /* Ejemplo en C# n 50: */ /* ejemplo50.cs */ /* */ /* Ejemplo de funcin con */ /* variables locales */ /*---------------------------*/ using System; public class Ejemplo50 { public static int potencia(int nBase, int nExponente) { int temporal = 1; /* Valor que voy hallando */ int i; /* Para bucles */ for(i=1; i<=nExponente; i++) temporal *= nBase; } return temporal; /* Multiplico "n" veces */ /* Y calculo el valor temporal */ /* Tras las multiplicaciones, */ /* obtengo el valor que buscaba */

public static void Main() { int num1, num2; Console.WriteLine("Introduzca la base: "); num1 = Convert.ToInt32( Console.ReadLine() ); Console.WriteLine("Introduzca el exponente: "); num2 = Convert.ToInt32( Console.ReadLine() ); Console.WriteLine("{0} elevado a {1} vale {2}", num1, num2, potencia(num1,num2));

- 72 -

Programacin de Dispositivos Mviles

} } En este caso, las variables "temporal" e "i" son locales a la funcin "potencia": para "Main" no existen. Si en "Main" intentramos hacer i=5; obtendramos un mensaje de error. De igual modo, "num1" y "num2" son locales para "main": desde la funcin "potencia" no podemos acceder a su valor (ni para leerlo ni para modificarlo), slo desde "main". En general, deberemos intentar que la mayor cantidad de variables posible sean locales (lo ideal sera que todas lo fueran). As hacemos que cada parte del programa trabaje con sus propios datos, y ayudamos a evitar que un error en un trozo de programa pueda afectar al resto. La forma correcta de pasar datos entre distintos trozos de programa es usando los parmetros de cada funcin, como en el anterior ejemplo. Ejercicios propuestos: 44. Crear una funcin "escribirTablaMultiplicar", que reciba como parmetro un nmero entero, y escriba la tabla de multiplicar de ese nmero (por ejemplo, para el 3 deber llegar desde 3x0=0 hasta 3x10=30). 45. Crear una funcin "esPrimo", que reciba un nmero y devuelva el valor booleano "true" si es un nmero primo o "false" en caso contrario. 46. Crear una funcin que reciba una cadena y una letra, y devuelva la cantidad de veces que dicha letra aparece en la cadena. Por ejemplo, si la cadena es "Barcelona" y la letra es 'a', debera devolver 2 (aparece 2 veces). 47. Crear una funcin que reciba un numero cualquiera y que devuelva como resultado la suma de sus dgitos. Por ejemplo, si el nmero fuera 123 la suma sera 6. 48. Crear una funcin que reciba una letra y un nmero, y escriba un "tringulo" formado por esa letra, que tenga como anchura inicial la que se ha indicado. Por ejemplo, si la letra es * y la anchura es 4, debera escribir **** *** ** *

Los conflictos de nombres en las variables


Qu ocurre si damos el mismo nombre a dos variables locales? Vamos a comprobarlo con un ejemplo: /*---------------------------*/ /* Ejemplo en C# n 51: */ /* ejemplo51.cs */ /* */ /* Dos variables locales */ /* con el mismo nombre */ /*---------------------------*/ using System; public class Ejemplo51 { public static void cambiaN() { int n = 7; n ++; } public static void Main() { int n = 5; Console.WriteLine("n vale {0}", n); cambiaN(); Console.WriteLine("Ahora n vale {0}", n); } }

- 73 -

Programacin de Dispositivos Mviles

El resultado de este programa es: n vale 5 Ahora n vale 5 Por qu? Sencillo: tenemos una variable local dentro de "duplica" y otra dentro de "main". El hecho de que las dos tengan el mismo nombre no afecta al funcionamiento del programa, siguen siendo distintas. Si la variable es "global", declarada fuera de estas funciones, s ser accesible por todas ellas: /*---------------------------*/ /* Ejemplo en C# n 52: */ /* ejemplo52.cs */ /* */ /* Una variable global */ /*---------------------------*/ using System; public class Ejemplo52 { static int n = 7; public static void cambiaN() { n ++; } public static void Main() { Console.WriteLine("n vale {0}", n); cambiaN(); Console.WriteLine("Ahora n vale {0}", n); } } Dentro de poco, hablaremos de por qu cada uno de los bloques de nuestro programa, e incluso las "variables globales", tienen delante la palabra "static". Ser cuando tratemos la "Programacin Orientada a Objetos", en el prximo tema.

Modificando parmetros
Podemos modificar el valor de un dato que recibamos como parmetro, pero posiblemente el resultado no ser el que esperamos. Vamos a verlo con un ejemplo: /*---------------------------*/ /* Ejemplo en C# n 53: */ /* ejemplo53.cs */ /* */ /* Modificar una variable */ /* recibida como parmetro */ /*---------------------------*/ using System; public class Ejemplo53 { public static void duplica(int x) { Console.WriteLine(" El valor recibido vale {0}", x); x = x * 2; Console.WriteLine(" y ahora vale {0}", x); } public static void Main() { int n = 5; Console.WriteLine("n vale {0}", n); duplica(n); Console.WriteLine("Ahora n vale {0}", n); }

- 74 -

Programacin de Dispositivos Mviles

} El resultado de este programa ser: n vale 5 El valor recibido vale 5 y ahora vale 10 Ahora n vale 5 Vemos que al salir de la funcin, los cambios que hagamos a esa variable que se ha recibido como parmetro no se conservan. Esto se debe a que, si no indicamos otra cosa, los parmetros "se pasan por valor", es decir, la funcin no recibe los datos originales, sino una copia de ellos. Si modificamos algo, estamos cambiando una copia de los datos originales, no dichos datos. Si queremos que los cambios se conserven, basta con hacer un pequeo cambio: indicar que la variable se va a pasar "por referencia", lo que se indica usando la palabra "ref", tanto en la declaracin de la funcin como en la llamada, as: /*---------------------------*/ /* Ejemplo en C# n 54: */ /* ejemplo54.cs */ /* */ /* Modificar una variable */ /* recibida como parmetro */ /*---------------------------*/ using System; public class Ejemplo54 { public static void duplica(ref int x) { Console.WriteLine(" El valor recibido vale {0}", x); x = x * 2; Console.WriteLine(" y ahora vale {0}", x); } public static void Main() { int n = 5; Console.WriteLine("n vale {0}", n); duplica(ref n); Console.WriteLine("Ahora n vale {0}", n); } } En este caso s se modifica la variable n: n vale 5 El valor recibido vale 5 y ahora vale 10 Ahora n vale 10 El hecho de poder modificar valores que se reciban como parmetros abre una posibilidad que no se podra conseguir de otra forma: con "return" slo se puede devolver un valor de una funcin, pero con parmetros pasados por referencia podramos devolver ms de un dato. Por ejemplo, podramos crear una funcin que intercambiara los valores de dos variables: public static void intercambia(ref int x, ref int y) La posibilidad de pasar parmetros por valor y por referencia existe en la mayora de lenguajes de programacin. En el caso de C# existe alguna posibilidad adicional que no existe en otros lenguajes, como los "parmetros de salida". Las veremos ms adelante.

- 75 -

Programacin de Dispositivos Mviles

El orden no importa
En algunos lenguajes, una funcin debe estar declarada antes de usarse. Esto no es necesario en C#. Por ejemplo, podramos rescribir el fuente anterior, de modo que "Main" aparezca en primer lugar y "duplica" aparezca despus, y seguira compilando y funcionando igual: /*---------------------------*/ /* Ejemplo en C# n 55: */ /* ejemplo55.cs */ /* */ /* Funcin tras Main */ /*---------------------------*/ using System; public class Ejemplo55 { public static void Main() { int n = 5; Console.WriteLine("n vale {0}", n); duplica(ref n); Console.WriteLine("Ahora n vale {0}", n); } public static void duplica(ref int x) { Console.WriteLine(" El valor recibido vale {0}", x); x = x * 2; Console.WriteLine(" y ahora vale {0}", x); } }

Algunas funciones tiles Nmeros aleatorios


En un programa de gestin o una utilidad que nos ayuda a administrar un sistema, no es habitual que podamos permitir que las cosas ocurran al azar. Pero los juegos se encuentran muchas veces entre los ejercicios de programacin ms completos, y para un juego s suele ser conveniente que haya algo de azar, para que una partida no sea exactamente igual a la anterior. Generar nmeros al azar ("nmeros aleatorios") usando C# no es difcil: debemos crear un objeto de tipo "Random", y luego llamaremos a "Next" para obtener valores entre dos extremos: // Creamos un objeto random Random r = new Random(); // Generamos un nmero entre dos valores dados int aleatorio = r.Next(1, 100);

Podemos hacer que sea realmente un poco ms aleatorio si en la primera orden le indicamos que tome como semilla el instante actual: Random r = new Random(DateTime.Now.Millisecond); De hecho, una forma muy simple de obtener un nmero "casi al azar" entre 0 y 999 es tomar las milsimas de segundo de la hora actual: int falsoAleatorio = DateTime.Now.Millisecond; Vamos a ver un ejemplo, que muestre en pantalla un nmero al azar entre 1 y 10: /*---------------------------*/ /* Ejemplo en C# n 56: */ /* ejemplo56.cs */ /* */ /* Nmeros al azar */ /*---------------------------*/

- 76 -

Programacin de Dispositivos Mviles

using System; public class Ejemplo56 { public static void Main() { Random r = new Random(DateTime.Now.Millisecond); int aleatorio = r.Next(1, 10); Console.WriteLine("Un nmero entre 1 y 10: {0}", aleatorio);

} }

Ejercicios propuestos: 49. Crear un programa que genere un nmero al azar entre 1 y 100. El usuario tendr 6 oportunidades para acertarlo.

Funciones matemticas
En C# tenemos muchas funciones matemticas predefinidas, como:

Abs(x): Valor absoluto Acos(x): Arco coseno Asin(x): Arco seno Atan(x): Arco tangente Atan2(y,x): Arco tangente de y/x (por si x o y son 0) Ceiling(x): El valor entero superior a x y ms cercano a l Cos(x): Coseno Cosh(x): Coseno hiperblico Exp(x): Exponencial de x (e elevado a x) Floor(x): El mayor valor entero que es menor que x Log(x): Logaritmo natural (o neperiano, en base "e") Log10(x): Logaritmo en base 10 Pow(x,y): x elevado a y Round(x, cifras): Redondea un nmero Sin(x): Seno Sinh(x): Seno hiperblico Sqrt(x): Raz cuadrada Tan(x): Tangente Tanh(x): Tangente hiperblica

(casi todos ellos usan parmetros X e Y de tipo "double") y una serie de constantes como

E, el nmero "e", con un valor de 2.71828... PI, el nmero "Pi", 3.14159...

Todas ellas se usan precedidas por "Math." La mayora de ellas son especficas para ciertos problemas matemticos, especialmente si interviene la trigonometra o si hay que usar logaritmos o exponenciales. Pero vamos a destacar las que s pueden resultar tiles en situaciones ms variadas:

La raz cuadrada de 4 se calculara haciendo x = Math.Sqrt(4); La potencia: para elevar 2 al cubo haramos y = Math.Pow(2, 3); El valor absoluto: para trabajar slo con nmeros positivos usaramos n = Math.Abs(x);

- 77 -

Programacin de Dispositivos Mviles

Pero hay muchas ms funciones


Pero en C# hay muchas ms funciones de lo que parece. De hecho, salvo algunas palabras reservadas (int, float, string, if, switch, for, do, while...), gran parte de lo que hasta ahora hemos llamado "rdenes", son realmente "funciones", como Console.ReadLine o Console.WriteLine. Nos iremos encontrando con otras funciones a medida que avancemos.

Recursividad
Una funcin recursiva es aquella que se define a partir de ella misma. Dentro de las matemticas tenemos varios ejemplos. Uno clsico es el "factorial de un nmero": n! = n (n-1) (n-2) ... 3 2 1 (por ejemplo, el factorial de 4 es 4 3 2 1 = 24) Si pensamos que el factorial de n-1 es (n-1)! = (n-1) (n-2) (n-3) ... 3 2 1 Entonces podemos escribir el factorial de un nmero a partir del factorial del siguiente nmero: n! = n (n-1)! Esta es la definicin recursiva del factorial, ni ms ni menos. Esto, programando, se hara: /*---------------------------*/ /* Ejemplo en C# n 57: */ /* ejemplo57.cs */ /* */ /* Funciones recursivas: */ /* factorial */ /*---------------------------*/ using System; public class Ejemplo57 { public static long fact(int n) { if (n==1) // Aseguramos que termine return 1; return n * fact (n-1); // Si no es 1, sigue la recursin } public static void Main() { int num; Console.WriteLine("Introduzca un nmero entero: "); num = System.Convert.ToInt32(System.Console.ReadLine()); Console.WriteLine("Su factorial es: {0}", fact(num)); } } Dos consideraciones importantes:

Atencin a la primera parte de la funcin recursiva: es MUY IMPORTANTE comprobar que hay salida de la funcin, para que nuestro programa no se quede dando vueltas todo el tiempo y deje el ordenador (o la tarea actual) "colgado". Los factoriales crecen rpidamente, as que no conviene poner nmeros grandes: el factorial de 16 es 2.004.189.184, luego a partir de 17 podemos obtener resultados errneos, si usamos nmeros enteros "normales". Qu utilidad tiene esto? Pues ms de la que parece: muchos problemas complicados se pueden expresar a partir de otro ms sencillo. En muchos de esos casos, ese problema se podr expresar de forma recursiva. Ms adelante veremos algn otro ejemplo.

- 78 -

Programacin de Dispositivos Mviles

Parmetros y valor de retorno de "Main"


Es muy frecuente que un programa que usamos desde la "lnea de comandos" tenga ciertas opciones que le indicamos como argumentos. Por ejemplo, bajo Linux o cualquier otro sistema operativo de la familia Unix, podemos ver la lista detallada de ficheros que terminan en .c haciendo ls l *.c En este caso, la orden sera "ls", y las dos opciones (argumentos o parmetros) que le indicamos son "-l" y "*.c". La orden equivalente en MsDos y en el intrprete de comandos de Windows sera dir *.c Ahora la orden sera "dir", y el parmetro es "*.c". Pues bien, estas opciones que se le pasan al programa se pueden leer desde C#. Se hace indicando un parmetro especial en Main, un array de strings: static void Main(string[] args) Para conocer esos parmetros lo haramos de la misma forma que se recorre habitualmente un array cuyo tamao no conocemos: con un "for" que termine en la longitud ("Length") del array:

for (int i = 0; i < args.Length; i++) { System.Console.WriteLine("El parametro {0} es: {1}", i, args[i]); } Por otra parte, si queremos que nuestro programa se interrumpa en un cierto punto, podemos usar la orden "Environment.Exit". Su manejo habitual es algo como Environment.Exit(1); Es decir, entre parntesis indicamos un cierto cdigo, que suele ser (por convenio) un 0 si no ha habido ningn error, u otro cdigo distinto en caso de que s exista algn error. Este valor se podra comprobar desde el sistema operativo. Por ejemplo, en MsDos y Windows se lee con "IF ERRORLEVEL", as: IF ERRORLEVEL 1 ECHO Ha habido un error en el programa Una forma alternativa de que "Main" indique errores al sistema operativo es no declarndolo como "void", sino como "int", y empleando entonces la orden "return" cuando nos interese: public static int Main(string[] args) { ... return 1; } Un ejemplo que pusiera todo esto en prueba podra ser: /*---------------------------*/ /* Ejemplo en C# n 58: */ /* ejemplo58.cs */ /* */ /* Parmetros y valor de */ /* retorno de "Main" */ /*---------------------------*/

- 79 -

Programacin de Dispositivos Mviles

using System; public class Ejemplo58 { public static int Main(string[] args) { Console.WriteLine("Parmetros: {0}", args.Length); for (int i = 0; i < args.Length; i++) { Console.WriteLine("El parmetro {0} es: {1}", i, args[i]); } if (args.Length == 0) { Console.WriteLine("Escriba algn parmetro!"); Environment.Exit(1); } return 0; } }

Programacin orientada a objetos Por qu los objetos?


Hasta ahora hemos estado "cuadriculando" todo para obtener algoritmos: tratbamos de convertir cualquier cosa en una funcin que pudiramos emplear en nuestros programas. Cuando tenamos claros los pasos que haba que dar, buscbamos las variables necesarias para dar esos pasos. Pero no todo lo que nos rodea es tan fcil de cuadricular. Supongamos por ejemplo que tenemos que introducir datos sobre una puerta en nuestro programa. Nos limitamos a programar los procedimientos AbrirPuerta y CerrarPuerta? Al menos, deberamos ir a la zona de declaracin de variables, y all guardaramos otras datos como su tamao, color, etc. No est mal, pero es "antinatural": una puerta es un conjunto: no podemos separar su color de su tamao, o de la forma en que debemos abrirla o cerrarla. Sus caractersticas son tanto las fsicas (lo que hasta ahora llambamos variables) como sus comportamientos en distintas circunstancias (lo que para nosotros eran las funciones). Todo ello va unido, formando un "objeto". Por otra parte, si tenemos que explicar a alguien lo que es el portn de un garaje, y ese alguien no lo ha visto nunca, pero conoce cmo es la puerta de su casa, le podemos decir "se parece a una puerta de una casa, pero es ms grande para que quepan los coches, est hecha de metal en vez de madera...". Es decir, podemos describir unos objetos a partir de lo que conocemos de otros. Finalmente, conviene recordar que "abrir" no se refiere slo a una puerta. Tambin podemos hablar de abrir una ventana o un libro, por ejemplo. Con esto, hemos comentado casi sin saberlo las tres caractersticas ms importantes de la Programacin Orientada a Objetos (OOP):

Encapsulacin: No podemos separar los comportamientos de las caractersticas de un objeto. Los comportamientos sern funciones, que en OOP llamaremos mtodos. Las caractersticas de un objeto sern variables, como las que hemos usado siempre (las llamaremos atributos). La apariencia de un objeto en C#, como veremos un poco ms adelante, recordar a un registro o "struct". Herencia: Unos objetos pueden heredar mtodos y datos de otros. Esto hace ms fcil definir objetos nuevos a partir de otros que ya tenamos anteriormente (como ocurra con el portn y la puerta) y facilitar la reescritura de los programas, pudiendo aprovechar buena parte de los anteriores... si estn bien diseados. Polimorfismo: Un mismo nombre de un mtodo puede hacer referencia a comportamientos distintos (como abrir una puerta o un libro). Igual ocurre para los datos: el peso de una puerta y el de un portn los podemos llamar de igual forma, pero obviamente no valdrn lo mismo. Otro concepto importante es el de "clase": Una clase es un conjunto de objetos que tienen caractersticas comunes. Por ejemplo, tanto mi puerta como la de mi vecino son puertas, es decir, ambas son objetos que pertenecen a la clase "puerta". De igual modo, tanto un Ford Focus como un Honda Civic o un Toyota Corolla son objetos concretos que pertenecen a la clase "coche".

- 80 -

Programacin de Dispositivos Mviles

Objetos y clases en C#
Vamos con los detalles. Las clases en C# se definen de forma parecida a los registros (struct), slo que ahora tambin incluirn funciones. As, la clase "Puerta" que mencionbamos antes se podra declarar as: public class Puerta { int ancho; int alto; int color; bool abierta; // // // // Ancho en centimetros Alto en centimetros Color en formato RGB Abierta o cerrada

public void Abrir() { abierta = true; } public void Cerrar() { abierta = false; } public void MostrarEstado() { Console.WriteLine("Ancho: {0}", ancho); Console.WriteLine("Alto: {0}", alto); Console.WriteLine("Color: {0}", color); Console.WriteLine("Abierta: {0}", abierta); } } // Final de la clase Puerta Como se puede observar, los objetos de la clase "Puerta" tendrn un ancho, un alto, un color, y un estado (abierta o no abierta), y adems se podrn abrir o cerrar (y adems, nos pueden "mostrar su estado, para comprobar que todo funciona correctamente). Para declarar estos objetos que pertenecen a la clase "Puerta", usaremos la palabra "new", igual que hacamos con los "arrays": Puerta p = new Puerta(); p.Abrir(); p.MostrarEstado(); Vamos a completar un programa de prueba que use un objeto de esta clase (una "Puerta"): /*---------------------------*/ /* Ejemplo en C# n 59: */ /* ejemplo59.cs */ /* */ /* Primer ejemplo de clases */ /*---------------------------*/ using System; public class Puerta { int ancho; int alto; int color; bool abierta; // // // // Ancho en centimetros Alto en centimetros Color en formato RGB Abierta o cerrada

public void Abrir() { abierta = true; } public void Cerrar() {

- 81 -

Programacin de Dispositivos Mviles

abierta = false;

public void MostrarEstado() { Console.WriteLine("Ancho: {0}", ancho); Console.WriteLine("Alto: {0}", alto); Console.WriteLine("Color: {0}", color); Console.WriteLine("Abierta: {0}", abierta); } } // Final de la clase Puerta public class Ejemplo59 { public static void Main() { Puerta p = new Puerta(); Console.WriteLine("Valores iniciales..."); p.MostrarEstado(); Console.WriteLine("\nVamos a abrir..."); p.Abrir(); p.MostrarEstado();

} }

Este fuente ya no contiene una nica clase (class), como todos nuestros ejemplos anteriores, sino dos clases distintas:

La clase "Puerta", que son los nuevos objetos con los que vamos a practicar. La clase "Ejemplo59", que representa a nuestra aplicacin.

El resultado de ese programa es el siguiente: Valores iniciales... Ancho: 0 Alto: 0 Color: 0 Abierta: False Vamos a abrir... Ancho: 0 Alto: 0 Color: 0 Abierta: True Se puede ver que en C#, al contrario que en otros lenguajes, las variables que forman parte de una clase (los "atributos") tienen un valor inicial predefinido: 0 para los nmeros, una cadena vaca para las cadenas de texto, o "False" para los datos booleanos. Vemos tambin que se accede a los mtodos y a los datos precediendo el nombre de cada uno por el nombre de la variable y por un punto, como hacamos con los registros (struct). Aun as, en nuestro caso no podemos hacer directamente "p.abierta = true", por dos motivos:

El atributo "abierta" no tiene delante la palabra "public"; por lo que no es pblico, sino privado, y no ser accesible desde otras clases (en nuestro caso, desde Ejemplo59). Los puristas de la Programacin Orientada a Objetos recomiendan que no se acceda directamente a los atributos, sino que siempre se modifiquen usando mtodos auxiliares (por ejemplo, nuestro "Abrir"), y que se lea su valor tambin usando una funcin. Esto es lo que se conoce como "ocultacin de datos". Supondr ventajas como que podremos cambiar los detalles internos de nuestra clase sin que afecte a su uso. Tambin puede desconcertar que en "Main" aparezca la palabra "static", mientras que no lo hace en los mtodos de la clase "Puerta". Veremos este detalle un poco ms adelante.

- 82 -

Programacin de Dispositivos Mviles

La herencia. Visibilidad
Vamos a ver ahora cmo definir una nueva clase de objetos a partir de otra ya existente. Por ejemplo, vamos a crear una clase "Porton" a partir de la clase "Puerta". Un portn tendr las mismas caractersticas que una puerta (ancho, alto, color, abierto o no), pero adems se podr bloquear, lo que supondr un nuevo atributo y nuevos mtodos para bloquear y desbloquear: public class Porton: Puerta { bool bloqueada; public void Bloquear() { bloqueada = true; } public void Desbloquear() { bloqueada = false; } Con "public class Porton: Puerta" indicamos que Porton debe "heredar" todo lo que ya habamos definido para Puerta. Por eso, no hace falta indicar nuevamente que un Portn tendr un cierto ancho, o un color, o que se puede abrir: todo eso lo tiene por ser un "descendiente" de Puerta. No tenemos por qu heredar todo; tambin podemos "redefinir" algo que ya exista. Por ejemplo, nos puede interesar que "MostrarEstado" ahora nos diga tambin si la puerta est bloqueada. Para eso, basta con volverlo a declarar y aadir la palabra "new" para indicar al compilador de C# que sabemos que ya existe ese mtodo y que sabemos seguro que lo queremos redefinir: public new void MostrarEstado() { Console.WriteLine("Ancho: {0}", ancho); Console.WriteLine("Alto: {0}", alto); Console.WriteLine("Color: {0}", color); Console.WriteLine("Abierta: {0}", abierta); Console.WriteLine("Bloqueada: {0}", bloqueada); } Aun as, esto todava no funciona: los atributos de una Puerta, como el "ancho" y el "alto" estaban declarados como "privados" (es lo que se considera si no decimos los contrario), por lo que no son accesibles desde ninguna otra clase, ni siquiera desde Porton. La solucin ms razonable no es declararlos como "public", porque no queremos que sean accesibles desde cualquier sitio. Slo querramos que esos datos estuvieran disponibles para todos los tipos de Puerta, incluyendo sus "descendientes", como un Porton. Esto se puede conseguir usando otro mtodo de acceso: "protected". Todo lo que declaremos como "protected" ser accesible por las clases derivadas de la actual, pero por nadie ms: public class Puerta { protected protected protected protected int ancho; int alto; int color; bool abierta; // // // // Ancho en centimetros Alto en centimetros Color en formato RGB Abierta o cerrada

public void Abrir() ... (Si quisiramos dejar claro que algn elemento de una clase debe ser totalmente privado, podemos usar la palabra "private", en vez de "public" o "protected"). Un fuente completo que declarase la clase Puerta, la clase Porton a partir de ella, y que adems contuviese un pequeo "Main" de prueba podra ser: /*---------------------------*/ /* Ejemplo en C# n 60: */ /* ejemplo60.cs */

- 83 -

Programacin de Dispositivos Mviles

/* */ /* Segundo ejemplo de */ /* clases: herencia */ /*---------------------------*/ using System; // ------------------------------public class Puerta { protected protected protected protected int ancho; int alto; int color; bool abierta; // // // // Ancho en centimetros Alto en centimetros Color en formato RGB Abierta o cerrada

public void Abrir() { abierta = true; } public void Cerrar() { abierta = false; } public void MostrarEstado() { Console.WriteLine("Ancho: {0}", ancho); Console.WriteLine("Alto: {0}", alto); Console.WriteLine("Color: {0}", color); Console.WriteLine("Abierta: {0}", abierta); } } // Final de la clase Puerta // ------------------------------public class Porton: Puerta { bool bloqueada; public void Bloquear() { bloqueada = true; } public void Desbloquear() { bloqueada = false; } public new void MostrarEstado() { Console.WriteLine("Ancho: {0}", ancho); Console.WriteLine("Alto: {0}", alto); Console.WriteLine("Color: {0}", color); Console.WriteLine("Abierta: {0}", abierta); Console.WriteLine("Bloqueada: {0}", bloqueada); } } // Final de la clase Porton // ------------------------------public class Ejemplo60 { public static void Main() { Porton p = new Porton();

- 84 -

Programacin de Dispositivos Mviles

Console.WriteLine("Valores iniciales..."); p.MostrarEstado(); Console.WriteLine("\nVamos a bloquear y a abrir..."); p.Bloquear(); p.MostrarEstado(); Console.WriteLine("\nVamos a desbloquear y a abrir..."); p.Abrir(); p.Desbloquear(); p.MostrarEstado(); } }

Cmo se disean las clases?


En estos primeros ejemplos, hemos "pensado" qu objetos necesitaramos, y hemos empezado a teclear directamente para implementarlos. Esto no es lo habitual. Normalmente, se usan herramientas grficas que nos ayuden a visualizar las clases y las relaciones que existen entre ellas. Tambin se puede dibujar directamente en papel para aclararnos las ideas, pero el empleo de herramientas informticas tiene una ventaja adicional: algunas de ellas nos permiten generar automticamente un esqueleto del programa. La metodologa ms extendida actualmente para disear estos objetos y sus interacciones (adems de otras muchas cosas) se conoce como UML (Unified Modelling Language, lenguaje de modelado unificado). El estndar UML propone distintos tipos de diagramas para representar los posibles "casos de uso" de una aplicacin, la secuencia de acciones que se debe seguir, las clases que la van a integrar (es lo que a nosotros nos interesa en este momento), etc. Vamos a ver la apariencia que tendra un "diagrama de clases". En concreto, vamos a ver un ejemplo usando ArgoUML, que es una herramienta gratuita de modelado UML, que est creada en Java, por lo que se puede utilizar desde multitud de sistemas operativos. Ampliando el ejemplo anterior, vamos a suponer que queremos hacer un sistema "domtico", para automatizar ciertas funciones en una casa: apertura y cierre de ventanas y puertas, encendido de calefaccin, etc. Las ideas iniciales de las que partiremos son:

La casa es el conjunto ("agregacin") de varios elementos: puertas, ventanas y calefactores. Cada puerta se puede abrir y cerrar. Cada ventana se puede abrir, cerrar. Adems, las ventanas tienen persianas, que se pueden subir y bajar. Cada calefactor puede encenderse, apagarse o se puede programar para que trabaje a una cierta temperatura.

Con estas posibilidades bsicas, el diagrama de clases podra ser as:

Este diagrama es una forma ms simple de ver las clases existentes y las relaciones entre ellas. Si generamos las clases a partir del diagrama, tendremos parte del trabajo hecho: ya "slo" nos quedar rellenar los detalles de mtodos como "Abrir", pero el esqueleto de todas las clases ya estar "escrito" para nosotros.

- 85 -

Programacin de Dispositivos Mviles

La palabra "static"
Desde un principio, nos hemos encontrado con que "Main" siempre iba acompaado de la palabra "static". En cambio, los mtodos (funciones) que pertenecen a nuestros objetos no los estamos declarando como "static". Vamos a ver el motivo: La palabra "static" delante de un atributo (una variable) de una clase, indica que es una "variable de clase", es decir, que su valor es el mismo para todos los objetos de la clase. Por ejemplo, si hablamos de coches convencionales, podramos suponer que el atributo "numeroDeRuedas" va a valer 4 para cualquier objeto que pertenezca a esa clase (cualquier coches). Por eso, se podra declarar como "static". De igual modo, si un mtodo (una funcin) est precedido por la palabra "static", indica que es un "mtodo de clase", es decir, un mtodo que se podra usar sin necesidad de declarar ningn objeto de la clase. Por ejemplo, si queremos que se pueda usar la funcin "BorrarPantalla" de una clase "Hardware" sin necesidad de crear primero un objeto perteneciente a esa clase, lo podramos conseguir as: public class Hardware { ... public static void BorrarPantalla () { ... } que desde dentro de "Main" (incluso perteneciente a otra clase) se usara con el nombre de la clase delante: public class Juego { ... public ComienzoPartida() { Hardware.BorrarPantalla (); ... Desde una funcin "static" no se puede llamar a otras funciones que no lo sean. Por eso, como nuestro "Main" debe ser static, deberemos siempre elegir entre:

Que todas las dems funciones de nuestro fuente tambin estn declaradas como "static", por lo que podrn ser utilizadas desde "Main". Declarar un objeto de la clase correspondiente, y entonces s podremos acceder a sus mtodos desde "Main": public class Ejemplo { ... public LanzarJuego () Juego j = new Juego(); j.ComienzoPartida (); ... {

Constructores y destructores.
Hemos visto que al declarar una clase, se dan valores por defecto para los atributos. Por ejemplo, para un nmero entero, se le da el valor 0. Pero puede ocurrir que nosotros deseemos dar valores iniciales que no sean cero. Esto se puede conseguir declarando un "constructor" para la clase. Un constructor es una funcin especial, que se pone en marcha cuando se crea un objeto de una clase, y se suele usar para dar esos valores iniciales, para reservar memoria si fuera necesario, etc. Se declara usando el mismo nombre que el de la clase, y sin ningn tipo de retorno. Por ejemplo, un "constructor" para la clase Puerta que le diera los valores iniciales de 100 para el ancho, 200 para el alto, etc., podra ser as: public Puerta() { ancho = 100; alto = 200;

- 86 -

Programacin de Dispositivos Mviles

color = 0xFFFFFF; abierta = false; } Podemos tener ms de un constructor, cada uno con distintos parmetros. Por ejemplo, puede haber otro constructor que nos permita indicar el ancho y el alto: public Puerta(int an, int al) { ancho = an; alto = al; color = 0xFFFFFF; abierta = false; } Ahora, si declaramos un objeto de la clase puerta con "Puerta p = new Puerta();" tendr de ancho 100 y de alto 200, mientras que si lo declaramos con "Puerta p2 = new Puerta(90,220);" tendr 90 como ancho y 220 como alto. Un programa de ejemplo que usara estos dos constructores para crear dos puertas con caractersticas iniciales distintas podra ser: /*---------------------------*/ /* Ejemplo en C# n 61: */ /* ejemplo61.cs */ /* */ /* Tercer ejemplo de clases */ /* Constructores */ /*---------------------------*/ using System; public class Puerta { int ancho; int alto; int color; bool abierta; // // // // Ancho en centimetros Alto en centimetros Color en formato RGB Abierta o cerrada

public Puerta() { ancho = 100; alto = 200; color = 0xFFFFFF; abierta = false; } public Puerta(int an, int al) { ancho = an; alto = al; color = 0xFFFFFF; abierta = false; } public void Abrir() { abierta = true; } public void Cerrar() { abierta = false; } public void MostrarEstado() { Console.WriteLine("Ancho: {0}", ancho); Console.WriteLine("Alto: {0}", alto); Console.WriteLine("Color: {0}", color);

- 87 -

Programacin de Dispositivos Mviles

Console.WriteLine("Abierta: {0}", abierta);

} // Final de la clase Puerta public class Ejemplo61 { public static void Main() { Puerta p = new Puerta(); Puerta p2 = new Puerta(90,220); Console.WriteLine("Valores iniciales..."); p.MostrarEstado(); Console.WriteLine("\nVamos a abrir..."); p.Abrir(); p.MostrarEstado(); Console.WriteLine("Para la segunda puerta..."); p2.MostrarEstado();

} }

Nota: al igual que existen los "constructores", tambin podemos indicar un "destructor" para una clase, que se encargue de liberar la memoria que pudiramos haber reservado en nuestra clase (no es nuestro caso, porque an no sabemos manejar memoria dinmica) o para cerrar ficheros abiertos (que tampoco sabemos). Un "destructor" se llama igual que la clase, pero precedido por el smbolo "~", no tiene tipo de retorno, y no necesita ser "public", como ocurre en este ejemplo: ~Puerta() { // Liberar memoria // Cerrar ficheros }

Polimorfismo y sobrecarga
Esos dos constructores "Puerta()" y "Puerta(int ancho, int alto)", que se llaman igual pero reciben distintos parmetros, y se comportan de forma que puede ser distinta, son ejemplos de "polimorfismo" (funciones que tienen el mismo nombre, pero distintos parmetros, y que quiz no se comporten de igual forma). Un concepto muy relacionado con el polimorfismo es el de "sobrecarga": dos funciones estn sobrecargadas cuando se llaman igual, reciben el mismo nmero de parmetros, pero se aplican a objetos distintos, as: puerta.Abrir (); libro.Abrir (); En este caso, la funci&oacute;n &quot;Abrir&quot; est&aacute; sobrecargada: se usa tanto para referirnos a abrir un libro como para abrir una puerta. Se trata de dos acciones que no son exactamente iguales, que se aplican a objetos distintos, pero que se llaman igual.

Constructores
Cuando creamos objetos de una clase derivada, antes de llamar a su constructor se llama a los constructores de las clases base, empezando por la ms general y terminando por la ms especfica. Por ejemplo, si creamos una clase "GatoSiams", que deriva de una clase "Gato", que a su vez procede de una clase "Animal", el orden de ejecucin de los constructores sera: Animal, Gato, GatoSiames, como se ve en este ejemplo: /*---------------------------*/ /* Ejemplo en C# n 62: */ /* ejemplo62.cs */ /* */ /* Cuarto ejemplo de clases */ /* Constructores y herencia */ /*---------------------------*/

- 88 -

Programacin de Dispositivos Mviles

using System; public class Animal { public Animal() { Console.WriteLine("Ha nacido un animal"); }

// -----------------public class Perro: Animal { public Perro() { Console.WriteLine("Ha nacido un perro"); } } // -----------------public class Gato: Animal { public Gato() { Console.WriteLine("Ha nacido un gato"); }

// -----------------public class GatoSiames: Gato { public GatoSiames() { Console.WriteLine("Ha nacido un gato siams"); }

// -----------------public class Ejemplo62 { public static void Main() { Animal a1 = new Animal(); GatoSiames a2 = new GatoSiames(); Perro a3 = new Perro(); Gato a4 = new Gato(); } } El resultado de este programa es: Ha Ha Ha Ha Ha Ha Ha Ha nacido nacido nacido nacido nacido nacido nacido nacido un un un un un un un un animal animal gato gato siams animal perro animal gato

- 89 -

Programacin de Dispositivos Mviles

Ejercicio propuesto: 50. Crear un nico fuente que contenga las siguientes clases:

o o

Una clase Trabajador, cuyo constructor escriba en pantalla "Soy un trabajador". Una clase Programador, que derive de Trabajador, cuyo constructor escriba en pantalla "Soy programador". o Una clase Analista, que derive de Trabajador, cuyo constructor escriba en pantalla "Soy analista". o Una clase Ingeniero, que derive de Trabajador, cuyo constructor escriba en pantalla "Soy ingeniero". o Una clase IngenieroInformatico, que derive de Ingeniero, cuyo constructor escriba en pantalla "Soy ingeniero informtico". o Una clase "PruebaDeTrabajadores", que cree un objeto perteneciente a cada una de esas clases.

Arrays de objetos
Es muy frecuente que no nos baste con tener un objeto de cada clase, sino que necesitemos manipular varios objetos pertenecientes a la misma clase. En ese caso, deberemos reservar memoria primero para el array, y luego para cada uno de los elementos. Por ejemplo, podramos tener un array de 5 perros, que crearamos de esta forma: Perro[] misPerros = new Perro[5]; for (byte i = 0; i < 5; i ++) misPerros[i] = new Perro(); Un fuente completo de ejemplo podra ser /*---------------------------*/ /* Ejemplo en C# n 63: */ /* ejemplo63.cs */ /* */ /* Quinto ejemplo de clases */ /* Array de objetos */ /*---------------------------*/ using System; public class Animal { public Animal() { Console.WriteLine("Ha nacido un animal"); } } // -----------------public class Perro: Animal { public Perro() { Console.WriteLine("Ha nacido un perro"); }

// -----------------public class Ejemplo63 {

- 90 -

Programacin de Dispositivos Mviles

public static void Main() { Perro[] misPerros = new Perro[5]; for (byte i = 0; i < 5; i ++) misPerros[i] = new Perro(); } } y su salida en pantalla, parecida a la del ejemplo anterior, sera Ha Ha Ha Ha Ha Ha Ha Ha Ha Ha nacido nacido nacido nacido nacido nacido nacido nacido nacido nacido un un un un un un un un un un animal perro animal perro animal perro animal perro animal perro

Adems, existe una peculiaridad curiosa: podemos crear un array de "Animales", pero luego indicar que unos de ellos son perros, otros gatos, etc., Animal[] misAnimales = new Animal[3]; misAnimales[0] = new Perro(); misAnimales[1] = new Gato(); misAnimales[2] = new GatoSiames(); Un ejemplo ms detallado: /*---------------------------*/ /* Ejemplo en C# n 64: */ /* ejemplo64.cs */ /* */ /* Ejemplo de clases */ /* Array de objetos de */ /* varias subclases */ /*---------------------------*/ using System; public class Animal { public Animal() { Console.WriteLine("Ha nacido un animal"); }

// -----------------public class Perro: Animal { public Perro() { Console.WriteLine("Ha nacido un perro"); } } // -----------------public class Gato: Animal {

- 91 -

Programacin de Dispositivos Mviles

public Gato() { Console.WriteLine("Ha nacido un gato"); }

// -----------------public class GatoSiames: Gato { public GatoSiames() { Console.WriteLine("Ha nacido un gato siams"); }

// -----------------public class Ejemplo64 { public static void Main() { Animal[] misAnimales = new Animal[8]; misAnimales[0] = new Perro(); misAnimales[1] = new Gato(); misAnimales[2] = new GatoSiames(); for (byte i=3; i<7; i++) misAnimales[i] = new Perro(); misAnimales[7] = new Animal(); } } La salida de este programa sera: Ha Ha Ha Ha Ha Ha Ha Ha Ha Ha Ha Ha Ha Ha Ha Ha nacido nacido nacido nacido nacido nacido nacido nacido nacido nacido nacido nacido nacido nacido nacido nacido un un un un un un un un un un un un un un un un animal perro animal gato animal gato gato siams animal perro animal perro animal perro animal perro animal

Funciones virtuales. La palabra "override"


En el ejemplo anterior hemos visto cmo crear un array de objetos, usando slo la clase base, pero insertando realmente objetos de cada una de las clases derivadas que nos interesaba, y hemos visto que los constructores se llaman correctamente... pero con los mtodos puede haber problemas. Vamos a verlo con un ejemplo, que en vez de tener constructores va a tener un nico mtodo "Hablar", que se redefine en cada una de las clases hijas, y despus comentaremos qu ocurre al ejecutarlo: /*---------------------------*/ /* Ejemplo en C# n 65: */

- 92 -

Programacin de Dispositivos Mviles

/* ejemplo65.cs */ /* */ /* Ejemplo de clases */ /* Array de objetos de */ /* varias subclases con */ /* metodos */ /*---------------------------*/ using System; public class Animal { public void Hablar() { Console.WriteLine("Estoy comunicndome..."); }

// -----------------public class Perro: Animal { public new void Hablar() { Console.WriteLine("Guau!"); } } // -----------------public class Gato: Animal { public new void Hablar() { Console.WriteLine("Miauuu"); }

// -----------------public class Ejemplo65 { public static void Main() { // Primero creamos un animal de cada tipo Perro miPerro = new Perro(); Gato miGato = new Gato(); Animal miAnimal = new Animal(); miPerro.Hablar(); miGato.Hablar(); miAnimal.Hablar(); // Linea en blanco, por legibilidad Console.WriteLine(); // Ahora los creamos desde un array Animal[] misAnimales = new Animal[3]; misAnimales[0] = new Perro(); misAnimales[1] = new Gato(); misAnimales[2] = new Animal(); misAnimales[0].Hablar(); misAnimales[1].Hablar(); misAnimales[2].Hablar();

- 93 -

Programacin de Dispositivos Mviles

} } La salida de este programa es: Guau! Miauuu Estoy comunicndome... Estoy comunicndome... Estoy comunicndome... Estoy comunicndome... La primera parte era de esperar: si creamos un perro, debera decir "Guau", un gato debera decir "Miau" y un animal genrico debera comunicarse. Eso es lo que se consigue con este fragmento: Perro miPerro = new Perro(); Gato miGato = new Gato(); Animal miAnimal = new Animal(); miPerro.Hablar(); miGato.Hablar(); miAnimal.Hablar(); En cambio, si creamos un array de animales, no se comporta correctamente, a pesar de que despus digamos que el primer elemento del array es un perro: Animal[] misAnimales = new Animal[3]; misAnimales[0] = new Perro(); misAnimales[1] = new Gato(); misAnimales[2] = new Animal(); misAnimales[0].Hablar(); misAnimales[1].Hablar(); misAnimales[2].Hablar(); Es decir, como la clase base es "Animal", el primer elemento hace lo que corresponde a un Animal genrico (decir "Estoy comunicndome"), a pesar de que hayamos dicho que se trata de un Perro. Generalmente, no ser esto lo que queramos. Sera interesante no necesitar crear un array de perros y otros de gatos, sino poder crear un array de animales, y que contuviera animales de distintos tipos. Para conseguir este comportamiento, debemos indicar a nuestro compilador que el mtodo "Hablar" que se usa en la clase Animal puede que sea redefinido por otras clases hijas, y que en ese caso debe prevalecer lo que indiquen las clases hijas. La forma de hacerlo es declarando ese mtodo "Hablar" como "virtual", y empleando en las clases hijas la palabra "override" en vez de "new", as: /*---------------------------*/ /* Ejemplo en C# n 66: */ /* ejemplo66.cs */ /* */ /* Ejemplo de clases */ /* Array de objetos de */ /* varias subclases con */ /* metodos virtuales */ /*---------------------------*/ using System; public class Animal {

- 94 -

Programacin de Dispositivos Mviles

public virtual void Hablar() { Console.WriteLine("Estoy comunicndome..."); } } // -----------------public class Perro: Animal { public override void Hablar() { Console.WriteLine("Guau!"); }

// -----------------public class Gato: Animal { public override void Hablar() { Console.WriteLine("Miauuu"); } } // -----------------public class Ejemplo66 { public static void Main() { // Primero creamos un animal de cada tipo Perro miPerro = new Perro(); Gato miGato = new Gato(); Animal miAnimal = new Animal(); miPerro.Hablar(); miGato.Hablar(); miAnimal.Hablar(); // Linea en blanco, por legibilidad Console.WriteLine(); // Ahora los creamos desde un array Animal[] misAnimales = new Animal[3]; misAnimales[0] = new Perro(); misAnimales[1] = new Gato(); misAnimales[2] = new Animal(); misAnimales[0].Hablar(); misAnimales[1].Hablar(); misAnimales[2].Hablar(); } } El resultado de este programa ya s es el que posiblemente desebamos: tenemos un array de animales, pero cada uno "Habla" como corresponde a su especie: Guau! Miauuu Estoy comunicndome... Guau!

- 95 -

Programacin de Dispositivos Mviles

Miauuu Estoy comunicndome...

Llamando a un mtodo de la clase "padre"


Puede ocurrir que en un mtodo de una clase hija no nos interese redefinir por completo las posibilidades del mtodo equivalente, sino ampliarlas. En ese caso, no hace falta que volvamos a teclear todo lo que haca el mtodo de la clase base, sino que podemos llamarlo directamente, precedindolo de la palabra "base". Por ejemplo, podemos hacer que un Gato Siams hable igual que un Gato normal, pero diciendo "Pfff" despus, as: public new void Hablar() { base.Hablar(); Console.WriteLine("Pfff"); } Este podra ser un fuente completo: /*---------------------------*/ /* Ejemplo en C# n 67: */ /* ejemplo67.cs */ /* */ /* Ejemplo de clases */ /* Llamar a la superclase */ /*---------------------------*/ using System; public class Animal { } // -----------------public class Gato: Animal { public void Hablar() { Console.WriteLine("Miauuu"); } } // -----------------public class GatoSiames: Gato { public new void Hablar() { base.Hablar(); Console.WriteLine("Pfff"); } } // -----------------public class Ejemplo67 { public static void Main() { Gato miGato = new Gato(); GatoSiames miGato2 = new GatoSiames(); miGato.Hablar(); Console.WriteLine(); miGato2.Hablar(); } // Linea en blanco

- 96 -

Programacin de Dispositivos Mviles

} Su resultado sera Miauuu Miauuu Pfff

Sobrecarga de operadores
Los "operadores" son los smbolos que se emplean para indicar ciertas operaciones. Por ejemplo, el operador "+" se usa para indicar que queremos sumar dos nmeros. Pues bien, en C# se puede "sobrecargar" operadores, es decir, redefinir su significado, para poder sumar (por ejemplo) objetos que nosotros hayamos creado, de forma ms cmoda y legible. Por ejemplo, para sumar dos matrices, en vez de hacer algo como "matriz3 = suma( matriz1, matriz2 )" podramos hacer simplemente " matriz3 = matriz1 + matriz2" No entraremos en detalle, pero la idea est en que redefiniramos un mtodo llamado "operador +", y que devolvera un dato del tipo con el que estamos (por ejemplo, una Matriz) y recibira dos datos de ese mismo tipo como parmetros: public static Matriz operator +(Matriz mat1, Matriz mat2) { Matriz nuevaMatriz = new Matriz(); for (int x=0; x < tamanyo; x++) for (int y=0; y < tamanyo; y++) nuevaMatriz[x, y] = mat1[x, y] + mat2[x, y]; } return nuevaMatriz;

Desde "Main", calcularamos una matriz como suma de otras dos haciendo simplemente Matriz matriz3 = matriz1 + matriz2;

- 97 -

Programacin de Dispositivos Mviles

Windows Mobile 5.0 (aplicable a Windows Mobile 6.5)


Windows Mobile 5.0 y Windows Mobile 6.5 corresponden a la siguiente generacin de Windows para dispositivos mviles. Con Windows Mobile llegan nuevas herramientas, APIS y tecnologas para el desarrollo de aplicaciones nativas o manejadas. No obstante, la guerra por los mviles se ha recrudecido en los ltimos aos con la aparicin del dispositivo mvil iPhone de Apple, por su entorno de desarrollo propietario XCode, y por el empuje hacia esta rea que est llevando a cabo Google con sus dispositivos mviles y con Android como sistema operativo abierto sobre el cual desarrollar aplicaciones. Se puede decir ya, que estamos frente a una nueva rea de lucha, el mercado de los dispositivos mviles, que se populariz especialmente con la Palm y los PocketPC y que ahora tiene por protagonistas a los dispositivos mviles ms puros. Siempre y sin perder de vista, la web como teln de fondo. Microsoft ha renovado por ello Windows Mobile 6.5 y se prepara para el asalto a lo que es la nueva guerra tecnolgica de la que los usuarios y los programadores seremos los ms beneficiados. An y as, Windows Mobile tal y como lo conocemos an, no tiene los das contados como muchos quieren hacer ver, y tiene todava un presente muy interesante, que obviamente cambiar en los prximos aos debido a los cambios tecnolgicos y las demandas cambiantes.

Uso de Visual Studio 2005


Cuadro de herramientas
El cuadro o barra de herramientas de Visual Studio 2010, nos permite utilizar los distintos componentes que tenemos a nuestra disposicin. En visual Studio 2010 tenemos una gran cantidad de controles dispuestos en distintas categorias. En la figura 1 podemos ver la barra de herramientas de Visual Studio 2010.

Cuadro de Herramientas de Visual Studio 2005 (aplicable a Visual Studio 2010) Cuando iniciamos un nuevo proyecto en Visual Studio 2005 este cuadro de herramientas queda rellenado con los controles que tenemos disponibles para el tipo de proyecto que hemos seleccionado. En la figura 2 se muestra la caja de herramientas con los controles disponibles para un poryecto WinForm de Compact Framework.

- 98 -

Programacin de Dispositivos Mviles

Cuadro de Herramientas de Visual Studio (aplicable a Visual Studio 2010)

Explorador de bases de datos


Desde el explorador de bases de datos un programador puede acceder a los distintos recursos del sistema. El principal y ms importante recurso es el que tiene que ver con la bases de datos. Ya sea Sql Server Sql Server Mobile Edition o Microsoft Access ,etc.

Explorador de servidores en Visual Studio 2005 (aplicable a Visual Studio 2010) Desde esta misma ventana podemos crear nuevas bases de datos y/o manejar las bases de datos existentes. En la Figura 2 se muestra el proceso para agregar una nueva conexin de Microsoft SQL Server Mobile Edition.

- 99 -

Programacin de Dispositivos Mviles

Nueva conexin en el explorador de servidores en Visual Studio 2005 (aplicable a Visual Studio 2010)

Explorador de soluciones
Podramos decir que un proyecto en Visual Studio 2010 equivale a una solucin sin embargo esto no es cierto. Una solucin puede constar de uno o varios proyectos de cualquier tipo o de recursos varios. Los conceptos de proyecto y solucin son sencillos de entender y para nada debe hacernos pensar que es algo complejo y dificil de dominar. En la Figura podemos ver el explorador de soluciones en Visual Studio 2010 con dos poryectos en una solucin, un proyecto de WindowsForms para un dispositivo mvil y un proyecto de biblioteca de clases.

Explorador de soluciones en Visual Studio 2005 (aplicable a Visual Studio 2010) Si queremos aadir un nuevo elemento a un proyecto nicamente tenemos que hacer clic con el botn derecho encima del proyecto en el explorador de soluciones e ir a Agregar elemento. Nota: Para abrir un recurso de la solucin, basta con situarnos en el recurso determinado, por ejemplo un formulario Windows de nombre Form1.cs y hacer doble clic sobre l. El recurso se abrir automticamente en Visual Studio. Adems, en Visual Studio 2010 sabremos en todo momento sobre qu recurso estamos trabajando en un momento dado

Propiedades
La ventana de propiedades nos permitir acceder a las propiedades de los objetos seleccionados tal y como se muestra en la Figura.

- 100 -

Programacin de Dispositivos Mviles

Ventana de propiedades en Visual Studio 2005 (aplicable a Visual Studio 2010) Nota: Para acceder a las propiedades de un objeto nicamente es necesario seleccionarlo y presionar la tecla F4

Mens y barras de botones


Respecto de los mens y barras de botones del entorno Visual Studio 2005, son muchas las opciones que tenemos disponibles. Las barras de botones son configurables con lo que podemos elegir aquellas que deseemos que siempre estn visibles al arrancar el entorno. El contenido del menu vara en funcin del elemento que tengamos seleccionado y se mostrarn las partes que sean relevantes para el. Algunas de estas opciones que tenemos en los mens tambin las tendremos disponibles usando los mens contextuales y como es de esperar tambin son diferentes segn el elemento seleccionado.

Mens y barras de botones en Visual Studio 2005 (aplicable a Visual Studio 2010) Nota: Para acceder a las propiedades de un objeto nicamente es necesario seleccionarlo y presionar la tecla F4

Device Emulator Manager


El 'Manager' de los emuladores ( Device Emulator Manager ) nos permit trabajar con los distinos emuladores existentes en nuestro sistema, desde emuladores de Phone Edition 2003-SE o WM 5.0 hasta dispositivos Windows CE 5.0. Este 'Manager' nos va a permitir trabajar con los emuladores como si realmente lo estuviramos haciendo con un dispositivo real. Para activar esta herramienta nicamente tenemos que dirigirnos al menu 'Tools' ( Herramientas ) tal y como podemos observar en la Figura 1.

- 101 -

Programacin de Dispositivos Mviles

Activacin de 'Device Emulator Manager' Una vez que activado el 'Device Emulator Manager' este nos muestra los distintos emuladores que tenemos a nuestra disposicin en el sistema puediendo activar uno o otro o varios emuladores a la vez.

Device Emulator manager Para activar un emulador basta con hacer clic con el botn derecho sobre el emulador a activar y en el men contextual seleccionar 'Conectar'.

- 102 -

Programacin de Dispositivos Mviles

Conectando un emulador con Device Emulator Manager Una Vez activado el emulador seleccionado tendremos a nuestra disposicin la posibilidad de conectarlo con Microsoft Active Sync de igual forma que lo haramos con un dispositivo real lo que nos proporcionar la posibilidad de realizar todas las tareas que pudiramos hacer con un dispositivo conectado al PC.

Cradle de un emulador Una vez activado el emulador ya lo tenemos a nuestra disposicin y en el puede probarse el resultado de nuestros desarrollos de un forma rpida y sencialla.

Emulador Otra de las posibilidades que nos ofrece Visual Studio 2010 es la de agregar ciertos parmetros de configuracin de nuestros emuladores de tal forma que podemos por ejemplo, especificar por ejemplo el grupo de favoritos, el estado de Bluetooth etc.

- 103 -

Programacin de Dispositivos Mviles

Una vez tengamos listo nuestro archivo de configuracin nos dirigimos a Visual Studio 2005 y en el men Herramientas-Opciones y en la opcin Herramientas de dispositivos seleccionamos el emulador para el cual queremos proveer una determinada configuracin.

Provisionamiento de configuracin con Visual Studio 2005 (aplicable a Visual Studio 2010) Una vez tengamos seleccionado el emulador para el cual queremos proveer una configuracin especfica hacemos clic en el botn 'Propiedades' y establecemos la ruta del archivo de configuracin que deseamos aplicar seleccionando el mismo en el botn Configurar.

Provisionamiento de configuracin con Visual Studio 2005 (aplicable a Visual Studio 2010)

Controles en Compact Framework


Una vez familiarizados con el entorno de diseo de nuestra herramienta de trabajo el siguiente pas ser el de conocer el amplio y variado conjunto de controles de los que disponemos en Visual Studio 2005. En nuestro entorno de desarrollo encontraremos direrentes grupos de controles o componentes dispuestos para ser utilizados tal y como se muestra en la figura.

- 104 -

Programacin de Dispositivos Mviles

Figura 1. Grupo de controles en Visual Studio 2005 (aplicable a Visual Studio 2010) Estos controles se dividen en los grupos representandos en la figura anterior. A continuacin veremos los ms representativos.

Datos
El grupo 'Datos' corresponde con el grupo cuyos controles tiene relacin directa con los componentes de acceso a datos, tal y como se muestra en la Figura.

Cuadro de Herramientas de Visual Studio 2005, grupo de datos (aplicable a Visual Studio 2010) Para muchos desarrolladores los controles, componentes y mtodos de acceso a datos son la principal dificultad a la hora de desarrollar una aplicacin. No se preocupe, aprenderemos a utilizarlos a base de prctica y lo que es ms importante los dominaremos rpidamente. A modo de introduccin vemos un ejemplo del control DataGrid situado en el grupo de datos,en el vemos como mostrar los contactos del dispositivo mvil en el control y su resultado en un dispositivo PocketPC y SmartPhone.

- 105 -

Programacin de Dispositivos Mviles

Ejemplo de control DataGrid en PocketPC

Ejemplo de control DataGrid en SmartPhone

Componentes
Visual Studio 2010 trae consigo un conjunto variados de componentes.En la Figura puede ver estos componentes.

Cuadro de Herramientas de Visual Studio 2005, grupos de componentes (aplicable a Visual Studio 2010)

- 106 -

Programacin de Dispositivos Mviles

El comportamiento de los componentes es distinto al de los controles comunes. Si hacemos por ejemplo doble clic en el componente Timer para insertarlo en el formulario, este quedar dispuesto en la parte inferior del mismo tal y com se puede observar en la Figura 2. Los componentes no son visibles en tiempo de ejecucin al contrario que los controles.

Componente Timer

Controles Comunes
Con este nombre, se aglutinan los controles ms generales y variados que podemos utilizar en nuestras aplicaciones. Sera algo as, como el resto de controles y componentes no contenidos en ninguna de las secciones que hemos visto anteriormente, aunque esto no es siempre as. Por esa razn si encuentra dos controles o componentes iguales en dos o ms secciones, no lo tenga en consideracin. En esta solapa, encontraremos por lo tanto los controles que utilizamos con ms frecuencia. En la Figura podemos observar alguno de estos controles.

Grupo de controles comunes El abanico de controles en esta seccin es muy amplio pudindose encontrar en esta seccin los controles necesarios para realizar la mayor parte de las aplicaciones. Cada uno de los controles tiene unas caractersticas y cualidades determinadas. Slo a base de prctica, aprenderemos a utilizarlos y lo nico que debemos saber, es cul de ellos usar en un momento dado.

Trabajo con los controles


En este momento ya conocemos un poco ms nuestra herramienta y la serie de ayudas que esta nos proporcionar en nuestros desarrollos por lo que ya estamos en disposicin de empezar el trabajo, en este mdulo veremos como usar los diversos controles que tenemos a nuestra disposicin y como aprovechar sus caractersticas en nuestros desarrollos. Aprenderemos como usar los controles disponibles en Visual Studio 2005 as como a crear nuestros propios controles si ninguno de los existentes se ajusta a nuestras necesidades. Para terminar veremos algunas consideraciones a tener en cuenta en el trabajo con los controles en Visual Studio 2005.

Dominando los controles en el entorno de trabajo


En las lecciones anteriores hemos visto como colocar un control en un formulario, pero quizs no sepamos como manejarlos de forma eficiente en nuestro formulario. Para ello vamos a realizar un sencillo ejemplo. Creamos un nuevo projecto para dispositivos mviles e insertamos en el formulario 3 controles Etiqueta tal y como puede verse en la Figura.

- 107 -

Programacin de Dispositivos Mviles

Controles en Visual Studio 2005 (aplicable a Visual Studio 2010) Como podemos observar estos controles estn dispuestos de una forma desordenada, ya que al insertarlos por ejemplo haciendo doble clic tres veces sobre un control Label, estos quedan dispuestos automticamente en el formulario. Nuestra primera tarea va a ser la de alinear estos controles, para ello seleccionamos los tres controles tal y como se puede ver en la Figura.

Seleccin de controles en Visual Studio 2005 (aplicable a Visual Studio 2010) Una vez seleccionados los tres controles en el men de Visual Studio 2010 seleccionamos Formato > Alinear > Lados Izquierdos tal y como se puede ver en la Figura.

- 108 -

Programacin de Dispositivos Mviles

Alineando los controles Una vez realizado podemos ver como estos controles ya estn alineados en sus lados izquierdos como puede verse en la Figura 4. De igual forma podemos hacer uso del resto de opciones que se nos permiten.

Controles alineados Este men de formato nos permite adems una serie de opciones que nos facilitaran el trabajo con los controles, establecer los espaciados (Horizontal o Vertical) entre los controles, marcar el mismo tamao de los controles etc. Truco: Suponiendo que tengamos tres controles Label de diferentes tamaos y que queramos que todos tengan el mismo tamao que el segundo de sus controles, seleccionaremos siempre como primer control, el control que queremos como base de tamao para el resto de controles, y posteriormente con la tecla Ctrl seleccionaremos uno a uno el resto de controles.

Creacin de controles en tiempo de ejecucin


Prcticamente todo en .Net son objetos, los controles tambin, as que para aadir un control en un formulario en tiempo de ejecucin, deberemos hacerlo tratndolo como un objeto. El siguiente ejemplo de cdigo crea un control Etiqueta en tiempo de ejecucin

- 109 -

Programacin de Dispositivos Mviles

private void CreateControl() { //Creamos el objeto control ( Etiqueta ) Label lblControl = new Label(); //Establecemos propiedades para el control lblControl.Name = "MiControlEtiqueta"; lblControl.Top = 70; lblControl.Left = 30; lblControl.Width = 30; lblControl.Height = 30; lblControl.Text = "Texto Etiqueta"; //Aadimos el control etiqueta al formulario this.Controls.Add(lblControl); } En la Figura podemos ver el resultado de la ejecucin del cdigo anterior:

Controles en Visual Studio 2005 (aplicable a Visual Studio 2010) En el ejemplo anterior hemos usado las propiedades Top y Left para establecer la posicin donde queremos que se aloje el control dentro del formulario y las propiedades Width y Height para establecer el tamao del mismo. Una forma ms rpida de escribir el tip anterior es el uso de Bounds para establecer estos parmetros, en el siguiente cdigo se puede ver como.

private void CreateControl() { //Creamos el objeto control ( Etiqueta ) Label lblControl = new Label(); //Establecemos propiedades para el control lblControl.Name = "MiControlEtiqueta"; lblControl.Bounds = new Rectangle(7, 14, 70, 30); lblControl.Text = "Texto Etiqueta"; //Aadimos el control etiqueta al formulario this.Controls.Add(lblControl); }

- 110 -

Programacin de Dispositivos Mviles

Hasta ahora hemos visto como crear controles en tiempo de ejecucin, sin embargo en muchas ocasiones es necesario adems asignar un evento al control creado dinmicamente. Como ejemplo de esto ltimo crearemos un control TextBox dinmicamente y manejaremos el evento 'TextChanged' que se produce cuando la propiedad Text del control cambia.

namespace DeviceApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); CreateControl(); } private void CreateControl() { //Creamos el objeto control ( Etiqueta ) TextBox txtControl = new TextBox(); //Establecemos propiedades para el control txtControl.Name = "MiControlCajaDeTexto"; txtControl.Bounds = new Rectangle(7, 14, 70, 30); txtControl.Text = "Texto Etiqueta"; //Agregamos una manejador para el evento txtControl.TextChanged += new EventHandler(txtControl_TextChanged); //Aadimos el control etiqueta al formulario this.Controls.Add(txtControl); } void txtControl_TextChanged(object sender, EventArgs e) { //Manejamos el vento ((TextBox)sender).Text = ((TextBox)sender).Text.ToUpper(); } } }

Creacin de nuevos controles


En ocasiones la variedad de controles que nos proporciona Visual Studio 2005 no es suficiente, por lo que se tendr que recurrir a la creacin de controles propios. Esta no es una tarea complicada ya que el entorno nos proporciona lo necesario para realizarla, adems de una gran facilidad para su posterior uso en nuestras aplicaciones. La mejor manera de ver todo esto es mediante un ejemplo, partimos de una aplicacin nueva para dispositivos mviles en este caso para WM 5.0 Pocket PC superior en la que vamos a crear un nuevo control. En el 'Explorador de soluciones' seleccionamos el proyecto y hacemos clic con el botn derecho y seleccionamos 'Agregar nuevo control de usuario' tal y como puede verse en la Figura.

- 111 -

Programacin de Dispositivos Mviles

Agregar un nuevo control de usuario al proyecto Una vez hecho esto escribimos el nombre que queremos dar a nuestro nuevo control en la ventana que se nos muestra a continuacin, ver Figura.

Figura 2. Estableciendo el nombre para el nuevo control de usuario Ya podemos empezar a trabajar en nuestro control, en este ejemplo haremos un simple control de validacin de los datos de usuario y contrasea para insertarlo posteriormente en un formulario. Lo primero que se nos presenta es el rea de trabajo, ver Figura dnde podemos trabajar, insertando controles y aadiendo funcionalidad a nuestro control de usuario.

- 112 -

Programacin de Dispositivos Mviles

rea de trabajo de nuestro control de usuario Una vez insertado los controles y aplicada la funcionalidad que necesitemos ya tendremos listo el nuevo control para ser usado dentro de nuestras aplicaciones, como ser ver despues, de una forma rpida y sencilla. El resultado final de nuestro control de usuario y el cdigo del mismo ser puede observar a continuacin.

Control de usuario terminado

using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace DeviceApplication1 { public partial class MyUserControl : UserControl { private bool acceso = true; /// <summary> /// Obtiene o establece un valor que indica si se va a permitir el acceso /// </summary> public bool Acceso { get { return acceso; } set { acceso = value; } } public MyUserControl() { InitializeComponent(); } } }

- 113 -

Programacin de Dispositivos Mviles

Como se puede observar en el cdigo anterior hemos includo una propiedad (Acceso) con la finalidad de mostrar como esta una vez que el control es insertado de un formulario de nuestra aplicacin es accesible mediante la ventana de propiedades de Visual Studio 2005 una vez seleccionado el control. En este momento ya tenemos creado nuestro nuevo control, ahora solamente queda ver como podemos hacer uso de el. Una vez terminada la realizacin del control el entorno de trabajo crea una nueva entrada en la caja de herramientas, ver Figura, donde podremos ver este nuevo control y arrastrarlo al formulario para su uso.

Control de usuario disponible en la caja de herramientas

Uso del control de usuario en un formulario Tal y como comentbamos en un prrafo anterior las propiedades del control son accesibles desde la ventana de propiedades del entorno, en nuestro caso hemos creado una propiedad 'Acceso' de tipo boleano que podremos modificar en esta ventana.

- 114 -

Programacin de Dispositivos Mviles

Ventana de propiedades del control de usuario Hemos visto en este captulo como en el caso de necesitar un nuevo control para una aplicacin el entorno de trabajo nos facilita en enorme medida la realizacin del mismo, desde la creacin del mismo, simplemente aadiendo un nuevo elemento de tipo UserControl a nuestro proyecto, hasta la utilizacin en la aplicacin arrastrando este control desde la caja de herramientas. Adems sin necesidad de escribir ninguna linea de cdigo adicional podemos tener acceso a las propiedades de nuestro control desde la ventana de propiedades, lo que sin lugar a dudas nos va a proporcionar una gran ventaja a la hora de trabajar con el.

Trabajando con imgenes


En este captulo veremos las partes ms generales en ele uso y generacin de imgenes y grficos en Compact Framework. Veremos un ejemplo sobre el uso de DirectX y nos adentraremos ms profundamente en el desarrollo de imgenes y grficos con GDI+.

Dibujando lineas con GDI+


Lo primero que aprenderemos ser como dibujar lineas simples con GDI+, empezemos por el principio, una linea en un plano es representada por dos puntos, estos puntos estn definidos por sus coordenadas X e Y, el primer punto representar el origen de la linea y el segundo punto el fin de la misma. Una vez que esta idea la tenemos clara veremos con la representacin de una linea mediante GDI+ es una tarea sencilla en Compact Framework.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing.Drawing2D; using System.Drawing; using System.Text; using System.Windows.Forms; namespace DeviceApplication1 { public partial class Form1 : Form { public Form1()

- 115 -

Programacin de Dispositivos Mviles

{ InitializeComponent(); } protected override void OnPaint(PaintEventArgs e) { DrawLine(e); base.OnPaint(e); } private void DrawLine(PaintEventArgs pea) { Pen lapiz = new Pen(Color.Blue, 10f); pea.Graphics.DrawLine( lapiz, 0, (int)(this.ClientSize.Height / 2), this.ClientSize.Width, (int)(this.ClientSize.Height / 2)); } } } Para la realizacin de esta tarea lo primero que debemos hacer tal y como se puede observar en el ejemplo de cdigo siguiente es crear el 'Lapiz' con el que deseamos pintar nuestra linea, en el especificamos el color asignado al mismo y el ancho que desemos para nuestra lenea. Una vez que hemos creado el 'Lapiz' con el que deseamos pintar la linea llamamos al mtodo DrawLine especificando los puntos de origen y final de la misma. El resultado puede observarse en la Figura.

Ejemplo de una linea pintada con GDI+ Truco: GDI+ en .Net Compact Framework incluye muchas de las funcionalidades de .NET Framework pero no todas estn soportadas. Otra de las posibilidades que tenemos es la de dibujar un camino de lineas especificando una serie de puntos que formarn la ruta a seguir. El proceso es igual de sencillo que en el caso anterior, basta con especificar el 'Lapiz' con el que se desea pintar y el conjunto de puntos que formarn la ruta como puede verse en el ejemplo de cdigo siguiente.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Text;

- 116 -

Programacin de Dispositivos Mviles

using System.Windows.Forms; namespace DeviceApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } protected override void OnPaint(PaintEventArgs e) { DrawRute(e); base.OnPaint(e); } private void DrawRute(PaintEventArgs pea) { Pen Lapiz = new Pen(Color.Red, 5f); Point[] puntos = new Point[] { new Point(15, 40), new Point(120, 40), new Point(120, 40), new Point(15, 7) }; pea.Graphics.DrawLines(Lapiz,puntos); } } } El resultado del cdigo anterior puede verse en la Figura.

Ejemplo de una camino de lineas

Representando polgonos con GDI+


La representancin de figuras como polgonos se asemaja a la representacin de lineas usando GDI+, a continuacin veremos algunos ejemplos de esto. Para realizar la reprensentacin de un polgono nuestra primera tarea es definir el 'Lpiz' con el que deseamos trazar sus lineas y ponsteriormente, tal y como se puede ver en el ejemplo de cdigo siguiente, especificar los puntos que representan al polgono.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Text; using System.Windows.Forms; namespace DeviceApplication1 {

- 117 -

Programacin de Dispositivos Mviles

public partial class Form1 : Form { public Form1() { InitializeComponent(); } protected override void OnPaint(PaintEventArgs e) { DrawPolygon(e); base.OnPaint(e); } private void DrawPolygon(PaintEventArgs pea) { //Creamos el lpiz con el que deseamos pintar el polgono Pen lapiz = new Pen(Color.Blue); Point[] puntosPoligono = new Point[] { new Point(30, 30), new Point(60, 30), new Point(30, 60), new Point(60, 60) }; pea.Graphics.DrawPolygon(lapiz, puntosPoligono); } } } En la Figura podemos ver el resultado de la ejecucin del cdigo anterior:

Dibujando polgonos con GDI+ GDI+ nos ofrece adems la posibilidad de rellenar estas figuras de una forma sencilla, como veremos la mayoria de los mtodos que usemos en GDI+ tienen asociado su mtodo Fill que nos permitir rellenar la forma que estemos representando. En el ejemplo de cdigo siguiente veremos un ejemplo de esto.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Text; using System.Windows.Forms; namespace DeviceApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

- 118 -

Programacin de Dispositivos Mviles

protected override void OnPaint(PaintEventArgs e) { DrawPolygon(e); base.OnPaint(e); } private void DrawPolygon(PaintEventArgs pea) { //Creamos el lpiz con el que deseamos pintar el polgono Pen lapiz = new Pen(Color.Blue); Point[] puntosPoligono = new Point[] { new Point(30, 30), new Point(60, 30), new Point(30, 60), new Point(60, 60) }; pea.Graphics.FillPolygon(new SolidBrush(Color.Yellow), puntosPoligono); } } } En la Figura podemos ver el resultado de la ejecucin del cdigo anterior.

Dibujando polgonos con GDI+ Si lo que queremos es rellenar un polgono pero realizar el borde de un color distinto llamaremos a los dos mtodos FillPolygon y DrawPolygon.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Text; using System.Windows.Forms; namespace DeviceApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } protected override void OnPaint(PaintEventArgs e) { DrawPolygon(e); base.OnPaint(e);

- 119 -

Programacin de Dispositivos Mviles

} private void DrawPolygon(PaintEventArgs pea) { //Creamos el lpiz con el que deseamos pintar el polgono Pen lapiz = new Pen(Color.Blue); Point[] puntosPoligono = new Point[] { new Point(30, 30), new Point(60, 30), new Point(30, 60), new Point(60, 60) }; pea.Graphics.FillPolygon(new SolidBrush(Color.Yellow), puntosPoligono); } } } El resultado del cdigo anterior se puede observar en la Figura.

Dibujando polgonos con GDI+

Dibujando cadenas de texto con GDI+


El mtodo DrawString nos va a permitir representar cadenas de forma grfica, al igual que dibujar lineas o polgonos esta es una tarea que no implica demasiada dificultad. En los siguientes ejemplos veremos como realizar esto, la primera tarea ser la de especificar la fuente y la 'brocha' de la cadena de texto a pintar.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Text; using System.Windows.Forms; namespace DeviceApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } protected override void OnPaint(PaintEventArgs e) { PintarTexto(e); base.OnPaint(e); } private void PintarTexto(PaintEventArgs pea)

- 120 -

Programacin de Dispositivos Mviles

{ //Creamos la fuente Font fuente = new Font("Arial", 8f, FontStyle.Regular); //Creamos la brocha SolidBrush brocha = new SolidBrush(Color.Red); SizeF sizeTexto = pea.Graphics.MeasureString("Hola Mundo", fuente); RectangleF marcoTexto = new RectangleF(30, 30, sizeTexto.Width, sizeTexto.Height); pea.Graphics.DrawString(" Hola Mundo", fuente, brocha, marcoTexto); } } }

En el ejemplo anterior hemos visto adems como se haca uso del mtodo MeasureString con la finalidad de obtener el tamao de dibujar el texto especificado con la fuente dada, esto nos facilita la creacin del marco en el cual se va a realizar el dibujo. Hemos usado adems como 'brocha' la clase SolidBrush, si nuestra intencin fuera la de dibujar esa cadena de texto usando una imagen de fondo podramos haber usado TextureBrush especificando dicha imagen de forma similar. El resultado del ejemplo anterior lo podemos ver en la Figura.

Dibujando cadenas de texto con GDI+ Nota: Si bien toda la fuerza de GDI+ no est contemplada en Compact Framework esta nos aporta la funcionalidad necesaria para nuestros desarrollos en dispositivos mviles

DirectX-Direct3D en Compact Framework


Tal y como dijimos en la introduccin de este mdulo no entraremos en detalle acerca del desarrollo sobre DirectX en Compact Framework si bien, hemos de hacer notar que esta posibilidad est a nuestro alcance. El espacio de nombre Microsoft.WindowsMobile.DirectX nos expone esta funcionalidad sobre la cual podemos incorporar nuestros desarrollos en DirectX a dispositivos mviles de una forma sencilla. Como ejemplo veremos un sencillo uso de Direct3D.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms;

- 121 -

Programacin de Dispositivos Mviles

using System.Runtime.InteropServices; using Microsoft.WindowsMobile.DirectX; using Microsoft.WindowsMobile.DirectX.Direct3D; namespace DirectX { public partial class Form1 : Form { Device device = null; VertexBuffer vertexBuffer = null; PresentParameters presentParams = new PresentParameters(); public Form1() { InitializeComponent(); this.Text = "Hola Mundo"; this.MinimizeBox = false; } public bool InitializeGraphics() { presentParams.Windowed = true; presentParams.SwapEffect = SwapEffect.Discard; device = new Device(0, DeviceType.Default, this, CreateFlags.None, presentParams); device.DeviceReset += new System.EventHandler( this.OnResetDevice); this.OnCreateDevice(device, null); this.OnResetDevice(device, null); return true; } void OnCreateDevice(object sender, EventArgs e) { Pool vertexBufferPool; Caps caps; Device dev = (Device)sender; // Obtenemos las capacidades del dispositivo caps = dev.DeviceCaps; if (caps.SurfaceCaps.SupportsVidVertexBuffer) vertexBufferPool = Pool.VideoMemory; else vertexBufferPool = Pool.SystemMemory; // Creamos el buffer vertexBuffer = new VertexBuffer( typeof(CustomVertex.PositionColored), 3, dev, 0, CustomVertex.PositionColored.Format, vertexBufferPool); vertexBuffer.Created += new System.EventHandler( this.OnCreateVertexBuffer); this.OnCreateVertexBuffer(vertexBuffer, null); } void OnResetDevice(object sender, EventArgs e) { Device dev = (Device)sender; dev.RenderState.CullMode = Cull.None; dev.RenderState.Lighting = false; } void OnCreateVertexBuffer(object sender, EventArgs e) { VertexBuffer vb = (VertexBuffer)sender; CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0); verts[0].X = -1.0f; verts[0].Y = -1.0f; verts[0].Z = 0.0f; verts[0].Color = System.Drawing.Color.DarkGoldenrod.ToArgb(); verts[1].X = 1.0f; verts[1].Y = -1.0f;

- 122 -

Programacin de Dispositivos Mviles

verts[1].Z = 0.0f; verts[1].Color = System.Drawing.Color.MediumOrchid.ToArgb(); verts[2].X = 0.0f; verts[2].Y = 1.0f; verts[2].Z = 0.0f; verts[2].Color = System.Drawing.Color.Cornsilk.ToArgb(); vb.Unlock(); } private void Render() { if (device != null) { //Limpia el buffer con el color azul device.Clear(ClearFlags.Target, System.Drawing.Color.Blue, 1.0f, 0); //Comienza la escena device.BeginScene(); device.SetStreamSource(0, vertexBuffer, 0); device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); //Finalizar la escena device.EndScene(); device.Present(); } } protected override void OnPaint(PaintEventArgs e) { this.Render(); this.Invalidate(); } protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e) { // Esc if ((int)(byte)e.KeyChar == (int)System.Windows.Forms.Keys.Escape) this.Close(); } protected override void OnPaintBackground(PaintEventArgs e) { //NO SE LLAMA A LA CASE PADRE } } } El resultado del ejemplo de cdigo anterior se puede observar en la Figura.

- 123 -

Programacin de Dispositivos Mviles

Trabajando con DirectX en dispositivos mviles

ADO.NET - Acceso a Datos


En este mdulo aprenderemos a trabajar con datos y fuentes de datos en dispositivos mviles. Sin lugar a dudas este es el punto en el que los desarrolladores encuentran sus mayores dificultades, pero no se preocupe, en este tutorial se abordaran las cuestiones ms importantes acerca del trabajo con fuentes de datos en dispositivos mviles.

Qu hay dentro de ADO.NET?


Dentro de ADO.NET tenemos dos partes importantes. La primera de ellas es la que corresponde con el nombre de espacio System.Data y que constituye los objetos y clases globales de ADO.NET. La otra parte es la que corresponde con los objetos que permiten el acceso a datos a una determinada fuente de datos desde ADO.NET y que utilizan as mismo, las clases del nombre de espacio System.Data. Esta ltima parte, queda constituida por las clases y objetos de los diferentes proveedores de acceso a datos como se muestra en la Figura.

Visin general de ADO.NET Para resumir de alguna forma lo que estamos comentando, diremos que el trabajo de conexin con la base de datos, la ejecucin de una instruccin SQL determinada, una vista, etc., la realiza el proveedor de acceso a datos. Recuperar esos datos para tratarlos, manipularlos o volcarlos a un determinado control o dispositivo, es accin de la capa superior que corresponde con el nombre de espacio System.Data. A continuacin veremos todo esto con ms detalle y comprenderemos de una forma ms clara cada una de las partes que componen el modelo de trabajo con ADO.NET.

Qu nos permite realmente ADO.NET cuando trabajamos con XML?


El entorno de Microsoft .NET Compact Framework nos proporciona el trabajo con estndares y con ello, la posibilidad de trabajar con diferentes tipos de aplicaciones, entornos, sistemas operativos y lenguajes sin necesidad de conocer lo que hay al otro lado de nuestra aplicacin. XML es sin lugar a dudas, el lenguaje de etiquetas por excelencia, vlido para llevar a cabo esta tarea sin tener un impacto relevante cuando trabajamos con diferentes soluciones en entornos dispares. Tanto la posibilidad de trabajar con Servicios Web XML como con documentos e informacin en XML, sobre todo al trabajar con fuentes de datos en ADO.NET, nos proporciona a los desarrolladores las posibilidades necesarias que nos permite hacer que la informacin con la que trabajamos, pueda ser tratada entre diferentes sistemas o entornos, sin que por ello nos preocupemos de lo que hay al otro lado.

SQL Mobile 2005 Mobile Edition ( superior)


SQL Server 2005 Mobile Edition ( superior) tiene varios alias, tambin llamado Sql Mobile y SQL CE 3.0 ( SQL CE 3.5 para la ltima versin) es el sucesor de SQL CE, aunque cabe decir que no es simplemente una extensin de este, ya que supone una autntica revolucin en las bases de datos para dispositivos mviles. A continuacin veremos alguno de los puntos a tener en cuenta en este novedoso motor de bases de datos.

- 124 -

Programacin de Dispositivos Mviles

Sql Mobile se presenta como una plataforma comn para distintos dispositivos como SmartPhone, PocketPC y TabletPC de tal forma que los desarrolladores podrn reutilizar el mismo cdigo en distintas plataformas sin necesidad de realizar ningn cambio. Sql Mobile permite la sincronizacin de datos contra Sql Server bajo el protocolo 'HTTP', adems estos datos a sincronizar se transmiten comprimidos lo que permite ahorrar trfico de red, cuestin muy importante si estas conexiones son GPRS, la compresin de datos adems aumenta la rapidez de los procesos de sincronizacin. Sql Mobile tiene soporte multi-usuario lo que permitira que en un mismo dispositivo varias aplicaciones se conecten a una base de datos al mismo tiempo. Otra de las grandes ventajas que nos proporciona SQL Sever 2005 Mobile Edition ( superior) es el manejo de las bases de datos en un dispositivo mvil mediante Sql Server Managment Studio. Desde el punto de vista del desarrollo, el que nos ocupa, el acceso a Sql Mobile est garantizado completamente mediante cdigo manejado lo que nos proporcionar una fuerza extraordinaria. En este mdulo aprenderemos a manejar Sql Mobile desde distintos dispositivos mviles, la creacin de una base de datos o el manejo de la misma tanto en entorno desconectado como conectado sern los temas a tratar.

El concepto de DataBinding
Ants de que veamos prcticamente los temas de acceso a datos es conveniente tener claro algunos conceptos, uno de ellos el de DataBinding que pasaremos a introducir brevemente a continuacin y con el que nos encontraremos a menudo en este mdulo.

El uso de DataBind
El DataBind nos va a proporcionar de una forma rpida y sencilla una mtodo para rellenar determinados controles con los datos contenidos en una base de datos. Muchos controles y clases proporcionan este mtodo al que le asignaremos un conjunto de datos con los que el usuario podr interactuar de forma directa. Si bien esto no es un concepto complicado es algo que veremos con mucha frecuencia y conviente tenerlo claro, durante este mdulo veremos muchos ejemplos de uso y veremos como realmete facilita las tareas de desarrollo.

SQL Server 2005 Mobile Edition


Una vez instalada la versin de Sql Server 2005 Mobile Edition ( superior) podremos conectarnos a ella, bien para crear una nueva base de datos o acceder a alguna existente desde SQL Server Management Studio, para ello y tal como puede verse en la Figura seleccionamos en el tipo de servidor Sql Server Mobile especificando la ruta de la base de datos a la que nos queremos conectar o bien <New Database> si lo que pretendemos es crear una nueva.

Conectando con Sql Mobile

- 125 -

Programacin de Dispositivos Mviles

Conectando con Sql Mobile Tal y como hemos dicho una vez seleccionado el tipo de servidor al que nos queremos conectar podemos acceder a una base de datos existente almacenada en nuestro equipo o bien va ActiveSync o crear una nueva base de datos. En este captulo realizaremos paso a paso las dos opciones.

Creando una nueva base de datos para Sql Mobile


Seleccionando la opcin <New Database>,ver Figura anterior, se nos presentara un cuadro de dilogo en el que especificaremos la ruta y el nombre de la nueva base de datos a crear, y la posibilidad de establecer una contrasea de acceso a dicha base de datos.

Creando una nueva base de datos en Sql Server 2005 Mobile Edition o superior (aplicable a Visual Studio 2010) En este punto ya estamos en disposicin de trabajar con nuestra base de datos Sql Mobile desde Sql Server Management Studio de tradicional, pudiendo modificar la estructura de la base de datos, la realizacin de consultas etc..

Trabajando con una base de datos de Sql Server 2005 Mobile Edition o superior (Aplicable a Visual Studio 2010)

- 126 -

Programacin de Dispositivos Mviles

Accediendo a una base de datos en un dispositivo mvil


Ya hemos aprendido a crear una nueva base de datos con Sql Server 2005 Mobile Edition o superior, ahora vamos a ver como conectarnos a una base de datos existente, para ello lo que haremos ser ver como podemos acceder a una base de datos de un dispositivo mvil. El primer paso es la sincronizacin va ActiveSync del dispositivo mvil.

Sincronizacin del dispositivo mvil Una vez sincronizado nuestro dispositivo mvil solamente nos queda seleccionar <Browse for more...> en el panel de conexin y buscar en el sistema de archivos del dispositivo mvil (el cual es accesible gracias a la sincronizacin del dispositivo) la base de datos a la que nos queremos conectar.

Seleccionando la base de datos en el dispositivo mvil

Manejando la base de datos en el dispositivo mvil

- 127 -

Programacin de Dispositivos Mviles

En este punto ya sabemos como crear y acceder a una base de datos desde Sql Server 2005 Mobile Edition ( superior) de una forma realmente sencilla. En siguientes captulos aprenderemos a trabajar con la base de datos desde el dispositivo mvil.

Trabajando con SQL Server Mobile


En el anterior captulo hemos visto como como crear o acceder a una base de datos Sql Mobile, sin embargo an no hemos aprendido como usar estas desde nuestras aplicaciones. Por ello, vamos a ver como integrar en nuestras aplicaciones una base de datos y posteriormente veremos como acceder a ella. Empezaremos por crear un nuevo proyecto para dispositivos mviles en Visual Studio 2005, para el ejemplo crearemos un nuevo proyecto para SmartPhone WM 5.0. Este proyecto necesitamos que trabaje con una base de datos que llamaremos cursoCF y que constar de una tabla llamada Usuarios. Una vez creado el proyecto arrancamos Sql Server Management Studio seleccionamos Sql Mobile como tipo de servidor y marcamos la opcin de crear nueva base de datos. Estableceremos la ruta de esta nueva base de datos dentro del directorio de nuestro proyecto.

Nueva base de datos de Sql Server 2005 Mobile Edition o superior (aplicable a Visual Studio 2010) A continuacin creamos la tabla 'Usuarios' para nuestra base de datos tal y como podemos observar en la Figura.

Creacin de la tabla Usuarios

- 128 -

Programacin de Dispositivos Mviles

Ya hemos creado la base de datos y la tabla con la que vamos a trabajar y la hemos situado en el directorio del proyecto para dispositivos mviles por lo que estamos en disposicin de empezar a trabajar con ella. En el explorador de soluciones de Visual Studio 2005, marcando la opcin de mostrar todos los archivos (' Show All Files') podremos ver el archivo 'cursoCF.sdf' correspondiente a nuestra base de datos

Visualizacin de la base de datos cursoCF Para trabajar con ella nicamente nos queda incluirla en el proyecto, para lo cual situaremos el cursor encima del archivo y haremos clic con el botn derecho y seleccionaremos en el menn contextual 'Incluir en el Proyecto'.

Incluyendo la base de datos en el proyecto A continuacin se nos presentar un pequeo asistente que nos permite seleccionar un conjunto de tablas,vistas para los que deseamos crear entidades, ms adelante trataremos este tema por lo que para empezar seleccionaremos 'Cancelar'. Una vez hecho esto ya tenemos includa en nuestra solucin la base de datos y las referencias necesarias para trabajar con ella tal y como podemos observar en la Figura.

- 129 -

Programacin de Dispositivos Mviles

Asistente de creacin de entidades

Explorador de soluciones con la base de datos includa en el proyecto Ahora solamente nos queda un ltimo paso, si bien ya tenemos incluida la base de datos en el proyecto si nosotros hicieramos uso de ella y probaramos nuestra aplicacin en el emulador comprobaramos como esta realmente no se incluy, para resolver esto una vez includa tendremos que especificar que este archivo se copie al directorio de salida. Para ello en la ventana de propiedades, una vez seleccionado cursoCF.sdf establecemos la propiedad 'Copy To Outout Directory' a 'Copy if Newer'.

Establecer lar propiedad Copy To Output Directory

- 130 -

Programacin de Dispositivos Mviles

Con este ltimo paso ya hemos realizado todo lo necesario para trabajar con esta base de datos de Sql Server 2005 Mobile Edition ( superior). En los siguientes captulos veremos como trabajar con esta base de datos tanto de forma conectada como de forma desconectada. Adems veremos que son y como trabajar con DataSet tipados.

Acceso conectado a la base de datos


En las lecciones anteriores hemos visto como trabajar con Sql Server 2005 Mobile Edition ( superior) para crear nuestras bases de datos para dispositivos mviles, acceder a ellas y como incluirlas dentro de un proyecto para dispositivos mviles. An as no hemos visto nada acerca del manejo de estas desde el dispositivo. En los siguientes captulos aprenderemos a manejar nuestras bases de datos de forma conectada, veremos las ventajas que esto nos ofrece y como resolver los posibles problemas con los que nos podamos encontrar.

Conociendo el objeto DataReader


El objeto DataReader nos permitir establecer una conexin con una fuente de datos y permanecer conectados a ella. Este objeto posee una serie de peculiaridades que es muy importante conocer para tener claro como funciona realmente.

DataReader es de solo lectura


Lo que hemos dicho anteriormente requiere que esta conexin se establezca en un modo de solo lectura, es decir, nicamente podemos leer datos de la fuente de datos a la que estemos conectados pero no modificar o insertar nuevos datos.

DataReader se maneja en una sola direccin


El objeto DataReader solamente permite que nos desplacemos por los datos en una nica direccin,sin vuelta atrs. Adems solamente podemos usar el objeto DataReader por conexiones establecidas en una sentencia SQL por ejemplo, pero no podemos variar estas.

DataReader es rpido
Debido a su naturaleza y caractersticas este objeto es rpido a la hora de trabajar con datos. Otra de sus ventajas es que consume pocos recursos y memoria.

Analizando el flujo de trabajo del objeto DataReader


Para trabajar con el objeto DataReader, se utilizarn los siguientes objetos.

Connection Command DataReader

Flujo de conectividad

Un primer contacto con el objeto DataReader


A continuacin veremos un ejemplo sencillo acerca del manejo del objeto DataReader Un ejemplo simple para entenderlo mejor En el siguiente ejemplo vamos a ver como usar el objeto DataReader para conectarnos a la base de datos creada en el mdulo anterior y que tenamos includa en el proyecto. Nuestra primera tarea ser la de definir nuestro objeto Connection, para ello debermos definir primero la cadena de conexin a la base de datos que queremos conectarnos. La cadena de conexin para Sql Mobile se define de la siguiente forma: "DataSource=RutaBaseDatos" dnde RutaBaseDatos representa la ruta a la base de datos. Lgicamente, nosotros debemos de disponer de una mtodo para averiguar la ruta de esta y para ello nos vamos a servir del especio de nombres System.IO, puesto que la base de datos la hemos includo en el

- 131 -

Programacin de Dispositivos Mviles

proyecto y esta se copiar al dispositivo mvil al lado de nuestro ejecutable, bastara con conocer el directorio dnde esta la aplicacin para poder conocer la ruta a nuestra base de datos. Esto lo podemos realizar de la siguiente forma.

//Creamos la cadena de conexion string pathDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string pathDB = System.IO.Path.Combine(pathDir, "cursoCF.sdf"); string connectionString = string.Empty; connectionString = string.Format(@"DataSource={0}",pathDB);

Mediante System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase obtenemos la ruta de la aplicacion que se esta ejecutando, de esta forma si esta ruta se la pasamos a GetDirectoryName obtendremos el directorio del ejecutable de la aplicacin que era realmente lo que estbamos buscando. Una vez que tenemos nuestra cadena de conexin ya podemos crear nuestro objeto 'Connection'.

//Creamos el objeto conexion SqlCeConnection conn = new SqlCeConnection(connectionString);

La idea de este ejemplo es la de recuperar los datos de la tabla 'usuarios' e incluirlos en un objeto ListView usando el objeto DataReader para ello, el diseo de nuestra aplicacin se puede ver en la Figura.

Diseo de la aplicacin Ahora nicamente nos queda crear el objeto 'Command' que contendr la consulta a realizar y el objeto DataReader mediante el cual leeremos los datos, recuerde que es de solo lectura y que nicamente se puede recorrer en una direccin.

//Creamos el objeto comando SqlCeCommand cmd = conn.CreateCommand(); cmd.CommandText = " select * from usuarios"; //Abrimos la conexion

- 132 -

Programacin de Dispositivos Mviles

if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); //Creamos el objeto DataReader SqlCeDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); Ya que vamos a trabajar de forma conectada, lgicamente ser necesario 'abrir' la conexin antes de realizar ninguna tarea. Como puede observar mediante el objeto comando hemos creado un nuevo objeto DataReader ( SqlCeDataReader ) el cual nos servir para llenar el control con los datos que deseamos obtener. En el siguiente ejemplo de cdigo veremos como recuperar los datos y rellenar el control.

ListViewItem listViewItem; while (dr.Read()) { listViewItem = new ListViewItem(); listViewItem.Text = dr["usuario"].ToString(); listViewItem.SubItems.Add(dr["password"].ToString()); //Aadimos el item al ListView listView1.Items.Add(listViewItem); } Como puede observarse mediante el objeto dr accedemos a cada una de las columnas de la fila en la que esta situado el objeto DataReader, una vez ledas en la siguiente iteracin del bucle el objeto DataReader se posiciona en la siguiente fila si esta existe y realizamos la misma tarea. El cdigo completo y el resultado del ejemplo se puede observar a continuacin.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.SqlServerCe; namespace SqlMobileExample1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void menuItemExit_Click(object sender, EventArgs e) { Application.Exit(); } private void menuItemLoadData_Click(object sender, EventArgs e) { //Creamos la cadena de conexion string pathDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string pathDB = System.IO.Path.Combine(pathDir, "cursoCF.sdf"); string connectionString = string.Empty; connectionString = string.Format(@"DataSource={0}",pathDB);

- 133 -

Programacin de Dispositivos Mviles

//Creamos el objeto conexion SqlCeConnection conn = new SqlCeConnection(connectionString); //Creamos el objeto comando SqlCeCommand cmd = conn.CreateCommand(); cmd.CommandText = " select * from usuarios"; //Abrimos la conexion if (conn.State == System.Data.ConnectionState.Closed) conn.Open(); //Creamos el objeto DataReader SqlCeDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); ListViewItem listViewItem; while (dr.Read()) { listViewItem = new ListViewItem(); listViewItem.Text = dr["usuario"].ToString(); listViewItem.SubItems.Add(dr["password"].ToString()); //Aadimos el item al ListView listView1.Items.Add(listViewItem); } } } }

Imagen de la aplicacin Nota: Recuerde que al incluir la base de datos en el proyecto se agregaron automticamente las referencias necesarias System.Data y System.Data.SqlServerCE, en el caso de que ests no estn presentes debe agregarlas.

- 134 -

Programacin de Dispositivos Mviles

Conociendo el objeto SqlCeResultSet


En los capitulos anteriores hemos visto y trabajado con el objeto DataReader,el cual nos aporta un gran rendimiento en nuestras consultas a una base de datos, sin embargo, este objeto posea varios inconvenientes, era un objeto de solo-lectura y adems nicamente permita moverse en una direccin, hacia adelante. Si lo que queremos es poseer una conexin a la base de datos y poder modificar o insertar elementos, adems de podernos mover lbremente lo que usaremos sera el objeto SqlCeResultSet del cual hablaremos detalladamente en este y en el prximo captulo. SqlCeResultSet se podra definir de la siguiente manera, " SqlCeResultSet representa un cursor actualizable, en el que nos podemos mover en ambas direcciones y que adems es enlazable " . Este objeto nos va a proporcionar una gran ayuda a la hora de trabajar con nuestra base de datos ya que no necesita de una gran cantidad de cdigo ni tampoco la duplicacin de datos en el dispositivo que tendramos si usaramos un DataSet (en los captulos siguientes hablaremos del objeto DataSet y del acceso desconectado a bases de datos). A lo largo del siguiente captulo veremos como como trabajar con este objeto tanto para obtener una serie de datos de una cosulta, insertar nuevos registros mediante este objeto y como enlazar diversos controles mediante SqlCeResultSetView.

Un primer contacto con el objeto SqlCeResultSet


Al igual que hicimos con el objeto DataReader la mejor manera de aprender es con la prctica, por lo tanto, a lo largo de este captulo veremos mediante sencillos ejemplos como manejar este objeto con el fin de sacarle el mayor provecho posible. Un ejemplo Sencillo para entenderlo mejor Para nuestro ejemplo seguiremos trabajando con la base de datos creada al comienzo de este mdulo. Nuestra primera tarea ser la de definir nuestro objeto Connection, para ello debermos definir primero la cadena de conexin a la base de datos que queremos conectarnos. La cadena de conexin para Sql Mobile se define de la siguiente forma: "DataSource=RutaBaseDatos" dnde RutaBaseDatos representa la ruta a la base de datos. Lgicamente, nosotros debemos de disponer de una mtodo para averiguar la ruta de esta y para ello nos vamos a servir del especio de nombres System.IO, puesto que la base de datos la hemos includo en el proyecto y esta se copiar al dispositivo mvil al lado de nuestro ejecutable, bastara con conocer el directorio dnde esta la aplicacin para poder conocer la ruta a nuestra base de datos. Esto lo podemos realizar de la siguiente forma.

//Creamos la cadena de conexion string pathDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string pathDB = System.IO.Path.Combine(pathDir, "cursoCF.sdf"); string connectionString = string.Empty; connectionString = string.Format(@"DataSource={0}",pathDB);

Mediante System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase obtenemos la ruta de la aplicacion que se esta ejecutando, de esta forma si esta ruta se la pasamos a GetDirectoryName obtendremos el directorio del ejecutable de la aplicacin que era realmente lo que estbamos buscando. Una vez que tenemos nuestra cadena de conexin ya podemos crear nuestro objeto 'Connection'.

//Creamos el objeto conexion SqlCeConnection conn = new SqlCeConnection(connectionString);

- 135 -

Programacin de Dispositivos Mviles

En el siguiente ejemplo veremos como realmente es posible navegar en ambas direcciones mediante el objeto SqlCeResultSet y adems veremos como actualizar e insertar nuevos registros. El aspecto de nuestra aplicacin lo podemos ver en la Figura.

Diseo de la aplicacin En las opciones del men introduciremos el cdigo necesario para navegar por los distintos registros usando para ello el objeto SqlCeResultSet.

Men de navegacin En este punto ya sabemos que queremos que haga nuestra aplicacin pero an no hemos visto nada acercar del objeto que nos ocupa, SqlCeResultSet, que es lo que haremos y explicaremos a continuacin. En el siguiente cdigo veremos como obtener un objeto SqlCeResultSet como resultado de un comando contra la base de datos.

private void LoadData() { //Creamos la cadena de conexion string pathDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string pathDB = System.IO.Path.Combine(pathDir, "cursoCF.sdf"); string connectionString = string.Empty; connectionString = string.Format(@"DataSource={0}", pathDB); //Creamos el objeto conexion conn = new SqlCeConnection(connectionString); //Abrimos la conexion if ( conn.State == ConnectionState.Closed ) conn.Open(); //Ejecutamos un comando SqlCeCommand cmd = conn.CreateCommand(); cmd.CommandType = CommandType.Text; cmd.CommandText = "SELECT usuario,password FROM usuarios"; try { //Obtenemos el objeto SqlCeResultSet

- 136 -

Programacin de Dispositivos Mviles

this.resultSet = cmd.ExecuteResultSet(ResultSetOptions.Scrollable); } catch (SqlCeException __ERR) { //Manejar el error } } El mtodo ExecuteResultSet del objeto comando ( SqlCeCommand ) nos permite obtener nuestro objeto de trabajo, adems nos permite especificar opciones sobre su comportamiento mediante el parmetro ResultSetOptions pasado al mtodo. Estas opciones son:

Insensitive None Updatable Scrollable Sensitive

La opcin Scrollable nos va a permitir navegar en ambos sentidos por la fuente de datos, que es en este caso lo que queremos. Por otro lado las opciones Sensitive e Insensitive establecen si el objeto SqlCeResultSet detecta cambios o no hechos en la fuente de datos. Nuestra aplicacin adems deseamos que permita actualizar datos por lo que tambin deberemos marcar la opcin Updatable, para ello basta con modificar el parmetro del mtodo ExecuteResultSet y establecerlo de la siguiente manera.

//Obtenemos el objeto SqlCeResultSet this.resultSet = cmd.ExecuteResultSet(ResultSetOptions.Scrollable|ResultSetOptions.Updatable); En estos momentos ya sabemos como crear nuestro objeto SqlCeResultSet, recordar aqu que estamos trabajando de forma conectada, por lo que mientras queramos hacer uso de este objeto la conexin siempre debe estar abierta. A continuacin nuestra tarea es la implementacin de las opciones del men, empezando por los elementos Siguiente y Anterior. En el siguiente cdigo veremos como navegar con el objeto SqlCeResultSet.

private void menuItemSiguiente_Click(object sender, EventArgs e) { //Mostrar el siguiente elemento if (this.resultSet != null) { if (this.resultSet.Read()) { txtUsuario.Text = this.resultSet["usuario"].ToString(); txtPassword.Text = this.resultSet["password"].ToString(); } } } private void menuItemAnterior_Click(object sender, EventArgs e) { //Mostrar el elemento anterior if (this.resultSet != null) { if (this.resultSet.ReadPrevious()) { txtUsuario.Text = this.resultSet["usuario"].ToString(); txtPassword.Text = this.resultSet["password"].ToString(); } } }

- 137 -

Programacin de Dispositivos Mviles

Cmo podemos observar la tarea es sencilla, es suficiente con usar los mtodos que el objeto SqlCeResultSet nos proporciana para ello, estos mtodos de navegacin los vemos con ms detalle en la siguiente lista.

Read: Posiciona el cursor en el siguiente registro si este existe ReadFirst: Posiciona el cursor en el primer elemento ReadLast: Posiciona el cursor en el ltimo elemento ReadPrevious: Posiciona el cursor en el elemento anterior si existe ReadRelative: Posiciona el cursor un nmero de posiciones especificas a partir de la posicin actual ReadAbsolute: Posiciona el cursor en un posicin especifica

Hasta este punto hemos visto como obtener un objeto SqlCeResultSet y como efectivamente podemos navegar en ambas direcciones de forma conectada, vamos por lo tanto a ver como podemos actualizar un registro o como aadir nuevos registros. En el siguiente ejemplo vemos como actualizar uno de los registros, bastar con modificar los datos del registro e invocar al mtodo Update para que estos cambios se vean reflejados automticamente en la base de datos.

private void menuItemActualizar_Click(object sender, EventArgs e) { if (this.resultSet != null) { if (this.resultSet.Updatable) { this.resultSet.SetString(0, txtUsuario.Text); this.resultSet.SetString(1, txtPassword.Text); this.resultSet.Update(); } } } El objeto SqlCeUpdatableRecord es el que nos va a permitir crear un nuevo registro e insertarlo a la base de datos una vez establecido sus valores, a continuacin vemos como:

private void menuItemNew_Click(object sender, EventArgs e) { SqlCeUpdatableRecord NuevoResgistro = this.resultSet.CreateRecord(); NuevoResgistro.SetString(0, txtUsuario.Text); NuevoResgistro.SetString(1, txtPassword.Text); this.resultSet.Insert(NuevoResgistro); } En la Figura 3 podemos ver la aplicacin funcionando.

- 138 -

Programacin de Dispositivos Mviles

La aplicacin de ejemplo funcionando

DataBinding con el objeto SqlCeResultSet


Como explicamos en la introduccin del mdulo, DataBinding es el proceso de enlace entre una fuente de datos y los controles. El objeto SqlCeResultSet nos permite enlazar una vista del mismo a los controles de nuestras aplicaciones sin necesitar muchas lineas de cdigo para realizar dicha tarea, esto se consigue gracias al objeto ResultSetView que nos va a proporcionar una interfaz entre el objeto SqlCeResultSet y los controles. ResultSetView nos va a permitir obtener una vista de los registros especificando bien el nombre de las columnas que queremos que se enlacen o bien la posicin que estas ocupan. En el siguente ejemplo vemos como enlazar un ResultSetView con un control DataGrid

using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.SqlServerCe; namespace SqlMobileExample1 { public partial class Form1 : Form { private SqlCeResultSet resultSet; private SqlCeConnection conn; public Form1() { InitializeComponent(); LoadData(); } private void menuItemExit_Click(object sender, EventArgs e) { Application.Exit(); } private void LoadData() { //Creamos la cadena de conexion string pathDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string pathDB = System.IO.Path.Combine(pathDir, "cursoCF.sdf"); string connectionString = string.Empty;

- 139 -

Programacin de Dispositivos Mviles

connectionString = string.Format(@"DataSource={0}", pathDB); //Creamos el objeto conexion conn = new SqlCeConnection(connectionString); //Abrimos la conexion if ( conn.State == ConnectionState.Closed ) conn.Open(); //Ejecutamos un comando SqlCeCommand cmd = conn.CreateCommand(); cmd.CommandType = CommandType.Text; cmd.CommandText = "SELECT usuario,password FROM usuarios"; try { //Obtenemos el objeto SqlCeResultSet this.resultSet = cmd.ExecuteResultSet(ResultSetOptions.Scrollable | ResultSetOptions.Updatable); } catch (SqlCeException) { //Manejar el error } } private void menuItemBindData_Click(object sender, EventArgs e) { ResultSetView rview = this.resultSet.ResultSetView; rview.Ordinals = new int[] { 0, 1 }; this.dataGrid1.DataSource = rview; } } } El resultado puede verse a continuacin En la Figura podemos ver la aplicacin funcionando.

Enlazando el objeto SqlCeResultSet

Acceso desconectado.
En anteriores captulos hemos visto como crear nuestras base de datos con Sql Mobile Edition y posteriormente trabajar con ellas de forma conectada. Al igual que en .Net Framework tambin existe la posibilidad de trabajar de forma desconectada de las mismas haciendo uso del objeto DataSet y de los componentes de acceso a datos que nos facilitarn esta tarea como los objetos DataAdapter.

- 140 -

Programacin de Dispositivos Mviles

Esquema general de la estructura desconectada de acceso a datos


La clase DataSet est pensada y diseada para trabajar con fuentes de datos desconectadas. Indudablemente, en este punto, debemos tener clara la estructura general de como funciona el acceso desconectado con fuentes de datos. En la siguiente figura podemos ver una imagen del esquema que nos ocupa.

Esquema general de la estrucura de acceso desconectado

Connection,DataAdapter y DataSet
Tal y como podemos observar en la figura para comunicarnos con una fuente de datos siempre necesitaremos establecer una conexin con dicha fuente, independientemente de si esta va a perdurar o no con el tiempo. El objeto Connection es el que nos permite realizar esta tarea. El objeto DataSet por otro lado nos va a permitir recoger la informacin de la fuente de datos y almacenarla en memoria para posteriormente trabajar con estos datos en nuestras aplicaciones. En medio de estos dos objetos nos encontraremos con el objeto DataAdapter el cual es el nexo de unin entre ellos.

Conociendo el objeto DataAdapter


Como explicamos en el anterior captulo, el objeto DataAdatper es el nexo de unin entre un objeto conexin y un DataSet. Este objeto no solamente nos va a proporcionar la ejecucin de sentencias SQL para obtener datos sino que tambin nos va a permitir alterar el contenido de una base de datos y/o de sus tablas. Un ejemplo prctico para entenderlo mejor Tal y como hemos hecho en todo el tutorial, la mejor forma de aprender es realizando ejemplos prcticos. En este caso veremos como conectarnos a una base de datos Sql Mobile y ver como trabajar en un ambiente desconectado. Utilizando las clases de .Net Compact Framework En este ejemplo veremos como trabajar de forma desconectada utilizando las clase de .Net Compact Framework para conectarnos a una base de datos de Sql Mobile, una vez creada la base de datos y agregada al proyecto de dispositivo mvil, tal y como hemos realizado en anteriores captulos lo que haremos ser crear un DataSet y 'poblarlo' con los datos de una tabla de la base de datos. Una vez hecho esto, podremos trabajar con ellos directamente sin necesidad de estar conectados a la base de datos. La primera tarea ser la de incluir las referencias necesarias, estas son System.Data y System.Data.SqlServerCE tal y como podemos ver en la figura siguiente.

- 141 -

Programacin de Dispositivos Mviles

Agregando las referencias necesarios Una vez agregadas las referencias necesarias a nuestro proyecto iremos a la seccin de cdigo y escribiremos las siguientes instrucciones.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.SqlServerCe; using System.IO; namespace SqlDataAdapter { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { string _connString = string.Empty; _connString = @"Data Source=\Program Files\SqlDataAdapter\MyDatabase#1.sdf"; //Creamos el objeto conexion SqlCeConnection conn = new SqlCeConnection(_connString); //Creamos el objeto DataAdatper SqlCeDataAdapter adapter = new SqlCeDataAdapter("SELECT id,nombre,apellidos FROM usuarios", conn); //Creamos el objeto DataSet DataSet ds = new DataSet("ds"); //Poblamos el objeto DataSet usando el adaptador try { adapter.Fill(ds, "usuarios"); //Enlazamos los datos del dataSet a un objeto ListBox listBox1.DataSource = ds.Tables["usuarios"];

- 142 -

Programacin de Dispositivos Mviles

listBox1.DisplayMember = "nombre"; listBox1.ValueMember = "id"; adapter = null; } catch (SqlCeException __ERR) { MessageBox.Show(__ERR.Message.ToString()); } } } } Tal y como se puede observar en el cdigo anterior la tarea es realmente sencilla, es suficiente con crear una nueva conexin y un nuevo objeto DataSet que contendr los datos que recueremos de la base de datos, tal y como dijimos el objeto DataAdatper es el nexo de unin y nos permitira especificar la sentencia SQL y la conexin con la que queremos trabajar. Una vez hecho esto, mediante su mtodo Fill podremos entonces poblar el DataSet. El resultado del ejemplo anterior puede verse en la Figura.

Ejemplo de uso de DataAdapter

Utilizando componentes de .NET Compact Framework


De igual forma que en el ejemplo anterior es posible realizar esta tarea de una forma ms rpida utilizando los componentes de SqlServerCE, lo cual nos permitir realizar la misma tarea pero de forma visual. Para ello nicamente tendramos que incorporar estos componentes a nuestra caja de herramientas. Veremos como realizar esta tarea a continuacin. Una vez seleccionada la 'pestaa' de la caja de herramientas en la que deseamis incorporar los controls, haremos clic con e boton derecho en la misma y seleccionaremos 'Elegir elementos',ver Figura.

Agregando elementos a la caja de herramientas

- 143 -

Programacin de Dispositivos Mviles

Una vez hecho esto seleccionaremos los componentes que deseemos agregar, en nuestro caso los componentes de SqlServerCE

Seleccionando los componentes a agregar

Insertando datos usando DataAdapter


Hasta ahora nicamente hemos visto como usar el objeto DataAdapter para seleccionar un conjunto de datos de la base de datos y mostrarlos en pantalla, no sabemos an nada de como insertar,eliminar o actualizar dichos datos. En este y los prximos captulos veremos como realizar estas tareas. Como sabemos el objecto DataAdapter es el nexo de unin entre una fuente de datos, una base de datos, y un objeto DataSet. Los datos de una tabla o de varias tablas del DataSet pueden ser modificados, eliminados o bien podemos insertar nuevos datos, por lo tanto tambin tenemos mtodos para 'comprometer' estos cambios en el DataSet a la base de datos por medio del adaptador. En este primer captulo veremos como realizar la insercin de datos en un DataSet y como volcar estos datos a la base de datos. Un ejemplo para entenderlo mejor En el siguiente ejemplo veremos como realizar esta tarea, para ello usaremos la base de datos del captulo anterior. Nuestra primera tarea ser la de crear los objetos con los que vamos a trabajar, estos son, el objeto conexin, el objeto adaptador, el objeto DataSet y el comando que nos va a permitir insertar nuevos elementos.

SqlCeConnection conn; SqlCeDataAdapter adapter; SqlCeCommand insertCommand; DataSet ds; Una vez creados vamos a inicializarlos convenientemente mediante un mtodo que hemos llamado InitAdapter.

private void InitAdapter() { string _connString = string.Empty; _connString = @"Data Source=\Program Files\SqlDataAdapter\MyDatabase#1.sdf"; //Creamos el objeto conexion this.conn = new SqlCeConnection(_connString);

- 144 -

Programacin de Dispositivos Mviles

//Creamos el objeto DataAdatper this.adapter = new SqlCeDataAdapter("SELECT id,nombre,apellidos FROM usuarios",this.conn); //Creamos el objeto DataSet this.ds = new DataSet("ds"); //Creamos el objecto comando para insertar nuevos datos this.insertCommand = new SqlCeCommand("INSERT INTO usuarios(nombre,apellidos) VALUES(@nombre,@apellidos)", this.conn); //Creamos los parametros del comando SqlCeParameter paramNombre = new SqlCeParameter("@nombre", SqlDbType.NVarChar,100,"nombre"); SqlCeParameter paramApellidos = new SqlCeParameter("@apellidos", SqlDbType.NVarChar,100,"apellidos"); //Agregamos los parametros al comando this.insertCommand.Parameters.Add(paramNombre); this.insertCommand.Parameters.Add(paramApellidos); //Agregamos el comando de insercion al adaptador this.adapter.InsertCommand = this.insertCommand; } Como se puede observar en el captulo anterior una vez inicializada la conexin y el objeto adaptador hemos construdo nuestro objeto SqlCeCommand que nos permitir manejar las inserciones, una vez iniciado el comando Sql se han agregado al mismo los parmetros necesarios y se ha establecido este comando en el adaptador como el comando de insercin a utilizar en la propiedad InsertCommand. Para comprobar que todo funciona correctamente, aadimos un nuevo registro al DataSet y llamamos al mtodo Update del adaptador el cual comprometer los cambios en la base de datos.

private void menuItemInsertar_Click(object sender, EventArgs e) { //Creamos una nueva fila para la tabla y la agregamos al dataSet DataRow row = this.ds.Tables["usuarios"].NewRow(); row["nombre"] = "nuevo nombre"; row["apellidos"] = "nuevos apellidos"; this.ds.Tables[0].Rows.Add(row); //Hacemos que los cambios se comprometan en la base de datos this.adapter.Update(this.ds); } El cdigo completo del ejemplo puede verse a continuacin

using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.SqlServerCe; using System.IO; namespace SqlDataAdapter { public partial class Form1 : Form

- 145 -

Programacin de Dispositivos Mviles

{ SqlCeConnection conn; SqlCeDataAdapter adapter; SqlCeCommand insertCommand; DataSet ds; public Form1() { InitializeComponent(); InitAdapter(); } private void InitAdapter() { string _connString = string.Empty; _connString = @"Data Source=\Program Files\SqlDataAdapter\MyDatabase#1.sdf"; //Creamos el objeto conexion this.conn = new SqlCeConnection(_connString); //Creamos el objeto DataAdatper this.adapter = new SqlCeDataAdapter("SELECT id,nombre,apellidos FROM usuarios",this.conn); //Creamos el objeto DataSet this.ds = new DataSet("ds"); //Creamos el objecto comando para insertar nuevos datos this.insertCommand = new SqlCeCommand("INSERT INTO usuarios(nombre,apellidos) VALUES(@nombre,@apellidos)", this.conn); //Creamos los parametros del comando SqlCeParameter paramNombre = new SqlCeParameter("@nombre", SqlDbType.NVarChar,100,"nombre"); SqlCeParameter paramApellidos = new SqlCeParameter("@apellidos", SqlDbType.NVarChar,100,"apellidos"); //Agregamos los parametros al comando this.insertCommand.Parameters.Add(paramNombre); this.insertCommand.Parameters.Add(paramApellidos); //Agregamos el comando de insercion al adaptador this.adapter.InsertCommand = this.insertCommand; } private void Form1_Load(object sender, EventArgs e) { try { adapter.Fill(ds, "usuarios"); //Enlazamos los datos del dataSet a un objeto ListBox listBox1.DataSource = ds.Tables["usuarios"]; listBox1.DisplayMember = "nombre"; listBox1.ValueMember = "id"; } catch (SqlCeException __ERR) { MessageBox.Show(__ERR.Message.ToString()); } } private void menuItemInsertar_Click(object sender, EventArgs e) { //Creamos una nueva fila para la tabla y la agregamos al dataSet DataRow row = this.ds.Tables["usuarios"].NewRow(); row["nombre"] = "nuevo nombre"; row["apellidos"] = "nuevos apellidos"; this.ds.Tables["usuarios"].Rows.Add(row);

- 146 -

Programacin de Dispositivos Mviles

//Hacemos que los cambios se comprometan en la base de datos this.adapter.Update(this.ds.Tables["usuarios"]); } } } A continuacin vemos en la primera figura nuestra aplicacin inicialmente y en la segunda Figura una vez insertado el elemeto y comprometido el DataSet en la base de datos.

Ejemplo antes de insertar un elemento por medio del objeto DataAdatper

Ejemplo despus de insertar un elemento por medio del objeto DataAdatper

- 147 -

Programacin de Dispositivos Mviles

Actualizando datos con el objeto DataAdapter


Siguiendo el ejemplo anterior, en el que hemos visto como construir y usar un objeto DataAdapter para insertar datos, veremos ahora como actualizar datos. El proceso es exctamente igual que el anterior, nicamente consiste en crear el comando de actualizacin y asignarlo en la propiedad UpdateCommand del adaptador, este comando ser llamado por el adaptador cuando necesite actualizar alguno de los registros del DataSet. En el siguiente ejemplo veremos como construir el comando de actualizacin, esta tarea la haremos en el mtodo anterior de inicializacin del DataAdapter ( InitAdapter, vase el captulo anterior ).

private void InitAdapter() { string _connString = string.Empty; _connString = @"Data Source=\Program Files\SqlDataAdapter\MyDatabase#1.sdf"; //Creamos el objeto conexion this.conn = new SqlCeConnection(_connString); //Creamos el objeto DataAdatper this.adapter = new SqlCeDataAdapter("SELECT id,nombre,apellidos FROM usuarios",this.conn); //Creamos el objeto DataSet this.ds = new DataSet("ds"); //Creamos el objecto comando para insertar nuevos datos this.insertCommand = new SqlCeCommand("INSERT INTO usuarios(nombre,apellidos) VALUES(@nombre,@apellidos)", this.conn); //Creamos los parametros del comando SqlCeParameter paramNombre = new SqlCeParameter("@nombre", SqlDbType.NVarChar,100,"nombre"); SqlCeParameter paramApellidos = new SqlCeParameter("@apellidos", SqlDbType.NVarChar,100,"apellidos"); //Agregamos los parametros al comando this.insertCommand.Parameters.Add(paramNombre); this.insertCommand.Parameters.Add(paramApellidos); //Agregamos el comando de insercion al adaptador this.adapter.InsertCommand = this.insertCommand; //Creamos el objeto comando para actualizar los registros modificados en el DataSet this.updateCommand = new SqlCeCommand(" UPDATE usuarios SET nombre=@nombre,apellidos=@apellidos WHERE ( id = @id )", this.conn); //Creamos los parametros para el comando de actualizacion SqlCeParameter paramUpdateNombre = new SqlCeParameter("@nombre", SqlDbType.NVarChar, 100, "nombre"); SqlCeParameter paramUpdateApellidos = new SqlCeParameter("@apellidos", SqlDbType.NVarChar, 100, "apellidos"); SqlCeParameter paramUpdateId = new SqlCeParameter("@id", SqlDbType.Int, 4, "id"); paramUpdateId.SourceVersion = DataRowVersion.Original; //Agregamos los parametros al comando this.updateCommand.Parameters.Add(paramUpdateNombre); this.updateCommand.Parameters.Add(paramUpdateApellidos); this.updateCommand.Parameters.Add(paramUpdateId); //Agregamos el comando al adaptador this.adapter.UpdateCommand = this.updateCommand; } Tal y como se puede observar la tarea es exctamente la misma, creacin del objeto comando, asignacin de los parmetros del mismo y establecer este comando en el adaptador para realizar la funcin especfica. Para comprobar que todo funciona correctamente usaremos un mtodo que permita modificar un registro y posteriormente utilizar el adaptador para comprometer estos cambios en la base de datos.

- 148 -

Programacin de Dispositivos Mviles

private void menuItemInsertar_Click(object sender, EventArgs e) { //Modificamos el nombre del primer registro de la tabla de usuarios this.ds.Tables["usuarios"].Rows[0]["nombre"] = "nombre Modificado"; //Hacemos que los cambios se comprometan en la base de datos this.adapter.Update(this.ds,"usuarios"); } En la Figura podemos ver el resultado una vez modificado un elemento.

Ejemplo de actualizacin de datos usando DataAdapter

Eliminando datos usando el objeto DataAdapter


En este punto ya sabemos como usar el objeto DataAdapter para insertar y actualizar los datos de un DataSet en la base de datos, solamente nos queda ver como hacemos para eliminar registros. Como seguramente ya os imaginais el proceso es exactamente el mismo, creacin del comando usado para realizar eliminaciones en la base de datos y asignacin del mismo al adaptador. Seguiremos por lo tanto el ejemplo de los captulos anteriores agregando esta capacidad al adaptador.

private void InitAdapter() { string _connString = string.Empty; _connString = @"Data Source=\Program Files\SqlDataAdapter\MyDatabase#1.sdf"; //Creamos el objeto conexion this.conn = new SqlCeConnection(_connString); //Creamos el objeto DataAdatper this.adapter = new SqlCeDataAdapter("SELECT id,nombre,apellidos FROM usuarios",this.conn); //Creamos el objeto DataSet this.ds = new DataSet("ds"); //Creamos el objecto comando para insertar nuevos datos this.insertCommand = new SqlCeCommand("INSERT INTO usuarios(nombre,apellidos) VALUES(@nombre,@apellidos)", this.conn); //Creamos los parametros del comando

- 149 -

Programacin de Dispositivos Mviles

SqlCeParameter paramNombre = new SqlCeParameter("@nombre", SqlDbType.NVarChar,100,"nombre"); SqlCeParameter paramApellidos = new SqlCeParameter("@apellidos", SqlDbType.NVarChar,100,"apellidos"); //Agregamos los parametros al comando this.insertCommand.Parameters.Add(paramNombre); this.insertCommand.Parameters.Add(paramApellidos); //Agregamos el comando de insercion al adaptador this.adapter.InsertCommand = this.insertCommand; //Creamos el objeto comando para actualizar los registros modificados en el DataSet this.updateCommand = new SqlCeCommand(" UPDATE usuarios SET nombre=@nombre,apellidos=@apellidos WHERE ( id = @id )", this.conn); //Creamos los parametros para el comando de actualizacion SqlCeParameter paramUpdateNombre = new SqlCeParameter("@nombre", SqlDbType.NVarChar, 100, "nombre"); SqlCeParameter paramUpdateApellidos = new SqlCeParameter("@apellidos", SqlDbType.NVarChar, 100, "apellidos"); SqlCeParameter paramUpdateId = new SqlCeParameter("@id", SqlDbType.Int, 4, "id"); paramUpdateId.SourceVersion = DataRowVersion.Original; //Agregamos los parametros al comando this.updateCommand.Parameters.Add(paramUpdateNombre); this.updateCommand.Parameters.Add(paramUpdateApellidos); this.updateCommand.Parameters.Add(paramUpdateId); //Agregamos el comando al adaptador this.adapter.UpdateCommand = this.updateCommand; //Creamos el objeto comando para eliminar los registros eliminados en el DataSet this.deleteCommand = new SqlCeCommand("DELETE FROM usuarios WHERE (id = @id)", this.conn); //Creamos los parmetros de eliminacin SqlCeParameter paramDeleteId = new SqlCeParameter("@id", SqlDbType.Int, 4, "id"); paramDeleteId.SourceVersion = DataRowVersion.Original; //Agregamos los parametros al comando this.deleteCommand.Parameters.Add(paramDeleteId); //Agregamos el comando al adaptador this.adapter.DeleteCommand = this.deleteCommand; } Para probarlo eliminamos la primera fila de la tabla de usuarios del DataSet y llamamos al mtodo Update del adaptador tal y como puede verse en la siguientes lineas de cdigo.

private void menuItemEliminar_Click(object sender, EventArgs e) { //Eliminamos el primer registro de la tabla this.ds.Tables["usuarios"].Rows[0].Delete(); //Hacemos que los cambios se comprometan en la base de datos this.adapter.Update(this.ds, "usuarios"); } En la siguiente figura puede verse el resultado

- 150 -

Programacin de Dispositivos Mviles

Ejemplo de eliminacin de datos usando DataAdapter

- 151 -

Programacin de Dispositivos Mviles

Captura de Datos con DATAREADER con SQLCERESULSET


Se necesita hacer un formulario con dos etiquetas, dos Texbox, un botn y un DataGrid. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Data.Common; using System.Data.SqlServerCe; namespace Captura { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void InsertarRegistro() { //Especificamos el origen de datos string ruta = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string connectionString = string.Empty; connectionString = string.Format(@"DataSource={0}", Path.Combine(ruta,"db.sdf")); //conectamos la base de datos SqlCeConnection oCon = new SqlCeConnection(connectionString); SqlCeCommand command = new SqlCeCommand ("SELECT usuario,password FROM tabla", oCon); if (oCon.State == ConnectionState.Closed) oCon.Open(); //creamos un dataset SqlCeDataAdapter oDA = new SqlCeDataAdapter("SELECT usuario,password FROM tabla", oCon); DataSet oDS = new DataSet("tabla"); //se crea el objeto resulset para movernos entre los registros SqlCeResultSet resulSet = command.ExecuteResultSet(ResultSetOptions.Updatable); try { //se insertan los registros SqlCeUpdatableRecord record = resulSet.CreateRecord(); record[0] = usuario.Text; record[1] = password.Text; ; resulSet.Insert(record); //Rellenamos el dataset oDA.Fill(oDS); } catch (SqlCeException ex) { Console.WriteLine(ex.Message); } finally { //Asignamos al datasource del datagrid nuestro dataset oDA.Dispose(); this.dataGrid1.DataSource = oDS.Tables[0].DefaultView; //cerramos la base de datos oCon.Dispose(); oCon.Close(); } }

- 152 -

Programacin de Dispositivos Mviles

private void btnGuardar_Click(object sender, EventArgs e) { InsertarRegistro(); } }

- 153 -

Programacin de Dispositivos Mviles

Insertar datos en una base de datos con DataAdapter. Se tiene que realizar un formulario con dos etiquetas, dos TextBox y un ListBoxt. Utilizando uno de los botones de men.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Data.Common; using System.Data.SqlServerCe; namespace InsertarDatos { public partial class Form1 : Form { SqlCeConnection conn; SqlCeDataAdapter adapter; SqlCeCommand insertCommand; DataSet ds; public Form1() { InitializeComponent(); IniciarAdapter(); } private void IniciarAdapter() { //Especificamos el origen de datos string ruta = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string conexion = string.Empty; conexion = string.Format(@"DataSource={0}", Path.Combine(ruta, "db.sdf")); //Creamos el objeto conexion this.conn = new SqlCeConnection(conexion); //Creamos el objeto DataAdatper this.adapter = new SqlCeDataAdapter("SELECT id,usuario,password FROM tabla", this.conn); //Creamos el objeto DataSet this.ds = new DataSet("ds"); //Creamos el objecto comando para insertar nuevos datos this.insertCommand = new SqlCeCommand("INSERT INTO tabla(usuario,password) VALUES(@usuario,@password)", this.conn); //Creamos los parametros del comando SqlCeParameter paramUsuario = new SqlCeParameter("@usuario", SqlDbType.NVarChar, 100, "usuario"); SqlCeParameter paramPassword = new SqlCeParameter("@password", SqlDbType.NVarChar, 100, "password"); //Agregamos los parametros al comando this.insertCommand.Parameters.Add(paramUsuario); this.insertCommand.Parameters.Add(paramPassword); //Agregamos el comando de insercion al adaptador this.adapter.InsertCommand = this.insertCommand; } private void Form1_Load(object sender, EventArgs e) { try { adapter.Fill(ds, "tabla"); //Enlazamos los datos del dataSet a un objeto ListBox listBox1.DataSource = ds.Tables["tabla"]; listBox1.DisplayMember = "usuario"; listBox1.ValueMember = "id"; } catch (SqlCeException ex) { MessageBox.Show(ex.Message.ToString()); } } private void menuItem1_Click(object sender, EventArgs e) {

- 154 -

Programacin de Dispositivos Mviles

conn.Open(); //Creamos una nueva fila para la tabla y la agregamos al dataSet DataRow row = this.ds.Tables["tabla"].NewRow(); row["usuario"] = Usuario.Text; row["password"] = Password.Text; this.ds.Tables["tabla"].Rows.Add(row); //Hacemos que los cambios se comprometan en la base de datos this.adapter.Update(this.ds.Tables["tabla"]); conn.Close(); Usuario.Text = ""; Password.Text = ""; Usuario.Focus(); } } }

- 155 -

Programacin de Dispositivos Mviles

Cambiar datos en una base de datos, se utiliza solamente un Label, un TextBoxt y un ListBoxt, adems de el MenuItem.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Data.Common; using System.Data.SqlServerCe; namespace Cambios { public partial class Form1 : Form { SqlCeConnection conn; SqlCeDataAdapter adapter; SqlCeCommand updateCommand; DataSet ds; public Form1() { InitializeComponent(); IniciarAdapter(); } private void IniciarAdapter() { //Especificamos el origen de datos string ruta = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string conexion = string.Empty; conexion = string.Format(@"DataSource={0}", Path.Combine(ruta, "db.sdf")); //Creamos el objeto conexion this.conn = new SqlCeConnection(conexion); //Creamos el objeto DataAdatper this.adapter = new SqlCeDataAdapter("SELECT id,usuario,password FROM tabla", this.conn); //Creamos el objeto DataSet this.ds = new DataSet("ds"); //Creamos el objeto comando para actualizar los registros modificados en el DataSet this.updateCommand = new SqlCeCommand(" UPDATE tabla SET usuario=@usuario,password=@password WHERE ( id = @id )", this.conn); //Creamos los parametros para el comando de actualizacion SqlCeParameter paramUpdateUsuario = new SqlCeParameter("@usuario", SqlDbType.NVarChar, 100, "usuario"); SqlCeParameter paramUpdatePassword = new SqlCeParameter("@password", SqlDbType.NVarChar, 100, "password"); SqlCeParameter paramUpdateId = new SqlCeParameter("@id", SqlDbType.Int, 4, "id"); paramUpdateId.SourceVersion = DataRowVersion.Original; //Agregamos los parametros al comando this.updateCommand.Parameters.Add(paramUpdateUsuario); this.updateCommand.Parameters.Add(paramUpdatePassword); this.updateCommand.Parameters.Add(paramUpdateId); //Agregamos el comando al adaptador this.adapter.UpdateCommand = this.updateCommand; } private void Form1_Load(object sender, EventArgs e) { try {

- 156 -

Programacin de Dispositivos Mviles

adapter.Fill(ds, "tabla"); //Enlazamos los datos del dataSet a un objeto ListBox listBox1.DataSource = ds.Tables["tabla"]; listBox1.DisplayMember = "usuario"; listBox1.ValueMember = "id"; } catch (SqlCeException ex) { MessageBox.Show(ex.Message.ToString()); } } private void menuItem1_Click(object sender, EventArgs e) { conn.Open(); //Modificamos el usuario del primer registro de la tabla int a; a = Convert.ToInt32(Id.Text); this.ds.Tables["tabla"].Rows[a]["usuario"] = Usuario.Text; //Hacemos que los cambios se comprometan en la base de datos this.adapter.Update(this.ds, "tabla"); conn.Close(); Usuario.Text = ""; Id.Text = ""; Id.Focus(); } } }

- 157 -

Programacin de Dispositivos Mviles

Borrar datos en una base de datos, se utiliza solamente un Label, un TextBoxt y un ListBoxt, adems de el MenuItem.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Data.SqlServerCe; namespace Borrar { public partial class Form1 : Form { SqlCeConnection conn; SqlCeDataAdapter adapter; SqlCeCommand deleteCommand; DataSet ds; public Form1() { InitializeComponent(); IniciarAdapter(); } private void IniciarAdapter() { //Especificamos el origen de datos string ruta = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); string conexion = string.Empty; conexion = string.Format(@"DataSource={0}", Path.Combine(ruta, "db.sdf")); //Creamos el objeto conexion this.conn = new SqlCeConnection(conexion); //Creamos el objeto DataAdatper this.adapter = new SqlCeDataAdapter("SELECT id,usuario,password FROM tabla", this.conn); //Creamos el objeto DataSet this.ds = new DataSet("ds"); //Creamos el objeto comando para eliminar los registros eliminados en el DataSet this.deleteCommand = new SqlCeCommand("DELETE FROM tabla WHERE (id = @id)", this.conn); //Creamos los parmetros de eliminacin SqlCeParameter paramDeleteId = new SqlCeParameter("@id", SqlDbType.Int, 4, "id"); paramDeleteId.SourceVersion = DataRowVersion.Original; //Agregamos los parametros al comando this.deleteCommand.Parameters.Add(paramDeleteId); //Agregamos el comando al adaptador this.adapter.DeleteCommand = this.deleteCommand; } private void menuItem1_Click(object sender, EventArgs e) { conn.Open(); //Modificamos el usuario del primer registro de la tabla int a; a = Convert.ToInt32(Orden.Text); this.ds.Tables["tabla"].Rows[a].Delete();

- 158 -

Programacin de Dispositivos Mviles

//Hacemos que los cambios se comprometan en la base de datos this.adapter.Update(this.ds, "tabla"); conn.Close(); Orden.Text = ""; Orden.Focus(); } private void Form1_Load(object sender, EventArgs e) { try { adapter.Fill(ds, "tabla"); //Enlazamos los datos del dataSet a un objeto ListBox listBox1.DataSource = ds.Tables["tabla"]; listBox1.DisplayMember = "usuario"; listBox1.ValueMember = "id"; } catch (SqlCeException ex) { MessageBox.Show(ex.Message.ToString()); } } } }

- 159 -

Programacin de Dispositivos Mviles

Sincronizacin de datos
La sincronizacin de datos entre un dispositivo mvil y una base de datos remota es un proceso complicado que requiere de un estudio exhaustivo para realizar una buena eleccin de las tcnicas a utilizar. En este mdulo trataremos de desglosar diferentes tcnicas y de realizar casos prcticos que nos ayuden en la toma de esas decisiones.

Sincronizacin
Con la llegada de Sql Server 2005 Mobile Edition o superior, la arquitectura del sistema utiliza el agente mvil del cliente SQL para tener acceso a la base de datos local a travs del agente mvil de SQL. Sin embargo, para la sincronizacin con una base de datos remota es necesaria una peticin desde el cliente mvil al servidor SQL con los servicios que proporciona IIS ( Internet Information Services ), el cliente mvil entonces puede utilizar OLE DB para acceder al proveedor, el cual responder con los datos solicitados usando la misma cadena de objetos.La Figura ilustra esta situacin.

Ilustracin del proceso de sincronizacin

RDA - Remote Data Access


RDA permite mantener la sincronizacin entre una base de datos en un dispositivo mvil y una base de datos remota, sin necesitar una conexin constante ( este tipo de conexiones se denominan Loosley Coupled connection ). Una vez que se han recuperado los datos del servidor remoto, estos son almacenados y tratados en el dispositivo mvil mediante el motor de Sql CE. Los datos almacenados as como sus cambios e inserciones pueden ser llevados de nuevo al servidor remoto. Estas dos operaciones se denominan Pull y Push y pasaremos a explicarlas con ms detalle a continuacin.

Operacin PULL
El proceso de Pull recupera los datos de la base de datos remota y los almacena en la base de datos del dispositivo mvil. Esta operacin crea el esquema de la tabla y almacena los datos demandados en ella. Es importante destacar que para que el proceso de Pull se realice correctamente en la base de datos del dispositivo mvil NO debe de existir una tabla con el mismo nombre que la demandada en la operacin. Las operaciones de Pull pueden realizarse de distinta forma dependiendo del propsito de la misma.

TrackingOff No se proporciona seguimiento a los datos replicados, ademas las restricciones de la base de datos remota no son tenidos en cuenta para la creacin del mismo en el dispositivo mvil.

TrackingOn Con esta opcin si se proporciona seguimiento a los datos replicados, para ello la tabla replicada no solo consta de los campos que se traen de la base de datos remota sino que adems se aade una serie de campos para proporcionar este seguimiento. Las restricciones como claves primarias son tenidas en cuenta y replicadas en la base de datos del dispositivo mvil pero los ndices no se tienen en cuenta

TrackingOffWithIndexes Al igual que TrackingOff, no se proporciona seguimiento de los datos replicados aunque en este caso las restricciones de integridad referencial si son aadidas a la tabla de la base de datos del dispositivo mvil.

- 160 -

Programacin de Dispositivos Mviles

TrackingOnWithIndexes Igual que TrackingOn con la diferencia de que en este caso si se aaden los ndices.

Operacin Push
El proceso de Push actualiza los cambios realizados en la base de datos del dispositivo mvil en la base de datos remota. Si durante esta transaccin ocurre algn tipo de fallo, esta es capz de realizar un 'RolledBack' a su estado original. Existen 2 formas de tratar la operacin de Push.

RdaBatchingOn El proceso de Push se realiza en una nica transaccin

RdaBatchingOff Este es el valor por defecto, mediante esta opcin cada fila que se lleva a la base de datos remota se ejecuta en una transaccin.

Observaciones Uno de los problemas que surgen cuando se realizan operaciones de Push en el servidor remoto es el tratamiento de las claves primarias. En el caso de sincronizacin mediante Merge Replication, que veremos en el siguiente captulo, este problema es de fcil solucin mediante IDENTITIES usando la opcin de Sql Sever 2005 o superior NOT FOR REPLICATION. Desgraciadamente con RDA no podemos emplear esta solucin por lo que para garantizar un correcto funcionamiento usando RDA debemos de garantizar que cada cliente sea capaz de crear identificadores nicos y que estos no se puedan imitar en el resto de clientes. Un caso prctico con RDA Veremos a continuacin como implementar RDA con un ejemplo sencillo, empezaremos por crear una nueva base de datos en Sql Server 2005 o superior, esta base de datos la llamaremos RemoteDB y constar de una nica tabla, usuarios, con los campos id, nombre y apellidos tal y como puede verse en la siguiente figura.

Nueva base de datos de SQL Server 2005 o superior (aplicable a SQL Server 2008 superior)

Configuracin de IIS y NTFS


La configuracin del servicio para Internet Information Services (IIS) requiere de los siguientes pasos:

1. 2. 3.
4. 5.

Creamos un directorio virtual en IIS; Especificamos el alias para ese directorio virtual; Especificamos la ruta de acceso al contenido para ese directorio virtual. En este directorio debe existir una copia del Agente de SQL Server CE; por defecto, haremos que este directorio virtual apunte a (para SQL Server 2005 Mobile Edition) C:\Archivos de programa\Microsoft SQL Server 2005 Mobile Edition\Server Concedemos el permiso de ejecucin para este directorio; Configuracin de la autentificacin de IIS: SqlServerCE soporta 3 mtodos de autentificacin: o Acceso Annimo

- 161 -

Programacin de Dispositivos Mviles

o o

Basic Authentication Integrated Windows

Una vez hecho esto es necesario adems agregar permisos de lectura-escritura NTFS al agente sqlcesa30.dll. Una vez hecho esto ya tendremos acceso al agente de servicios mediante la URL domain/virtual-Dir/sqlcesa30.dll.

Implementacin del dispositivo mvil


El acceso mediante RDA al agente de servicios de SQL Server se proporciona mediante el objeto SqlCeRemoteDataAccess. A este objeto es necesario proporcionarle los parmetros de autentificacin al servicio IIS y la URL del servicio, adems de proporcionarle la cadena de conexin a la base de datos Sql Ce del dispositivo mvil. Inicializacin del cliente RDA

private void ConfigureRDA() { ceRDA = new SqlCeRemoteDataAccess(); //Configuracion del acceso remoto ceRDA.InternetLogin = string.Empty; ceRDA.InternetPassword = string.Empty; ceRDA.InternetUrl = "http://192.168.2.5/RemoteDB/sqlcesa30.dll"; string localDbConnectionString = string.Empty; CreateLocalDb(ref localDbConnectionString); ceRDA.LocalConnectionString = localDbConnectionString; } Una vez iniciado el objeto SqlCeRemoteDataAccess con los valores de autentificacin y la ruta de acceso se invoca al mtodo CreateLocalDb el cual crea una nueva base de datos de SqlCe, esto se puede ver en el siguiente cdigo.

private void CreateLocalDb(ref string localPath) { SqlCeEngine engineCe = new SqlCeEngine(); //Path de la base de datos string pathDB = string.Empty; pathDB = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); pathDB = Path.Combine(pathDB, "rda.sdf"); //Creamos la base de datos vaca if (!File.Exists(pathDB)) { localPath = string.Format("Data Source={0}",pathDB); engineCe.LocalConnectionString = localPath; engineCe.CreateDatabase(); } } Una vez hecho esto ya solamente nos queda ver como invocar las operaciones de Pull y/o Push de datos. Para nuestro ejemplo situaremos un control DataGrid en el formulario y veremos como rellenarlo con los datos del servidor remoto. En la figura se puede ver el diseo de nuestra aplicacin.

- 162 -

Programacin de Dispositivos Mviles

Diseo de la aplicacin Los mtodos de Pull y Push necesitan adems de la cadena de conexin de la instancia del Sql Server a la que nos vamos a conectar y los datos de autentificacin tal y como puede verse a continuacin.

private void menuItem1_Click(object sender, EventArgs e) { //Implementacin de Pull if (this.ceRDA != null) { try { string _oleConnectionString = @"Provider=sqloledb;Data Source=PORSOURCECODE\YUKON;Initial Catalog=RemoteDB;User id=sa;password=*****"; ceRDA.Pull("usuarios", "select * from usuarios", _oleConnectionString,RdaTrackOption.TrackingOn); } catch (SqlCeException __ERR) { MessageBox.Show(__ERR.Message.ToString()); } } } private void menuItem2_Click(object sender, EventArgs e) { //Implementacion de Push if (this.ceRDA != null) { try { string _oleConnectionString = @"Provider=sqloledb;Data Source=PORSOURCECODE\YUKON;Initial Catalog=RemoteDB;User id=sa;password=******"; ceRDA.Push("usuarios", _oleConnectionString, RdaBatchOption.BatchingOn); } catch (SqlCeException __ERR) { MessageBox.Show(__ERR.Message.ToString()); } } } A continuacin puede verse en cdigo completo de nuestro ejemplo

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data;

- 163 -

Programacin de Dispositivos Mviles

using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data.SqlServerCe; using System.IO; namespace RDA { public partial class Form1 : Form { SqlCeRemoteDataAccess ceRDA; string localConnectionString = string.Empty; public Form1() { InitializeComponent(); ConfigureRDA(); } private void ConfigureRDA() { ceRDA = new SqlCeRemoteDataAccess(); //Configuracion del acceso remoto ceRDA.InternetLogin = string.Empty; ceRDA.InternetPassword = string.Empty; ceRDA.InternetUrl = "http:"//192.168.2.5/RemoteDB/sqlcesa30.dll"; CreateLocalDb(); ceRDA.LocalConnectionString = this.localConnectionString; } private void CreateLocalDb() { SqlCeEngine engineCe = new SqlCeEngine(); //Path de la base de datos string pathDB = string.Empty; pathDB = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); pathDB = Path.Combine(pathDB, "rda.sdf"); //Creamos la base de datos vaca if (!File.Exists(pathDB)) { this.localConnectionString = string.Format("Data Source={0}",pathDB); engineCe.LocalConnectionString = this.localConnectionString; engineCe.CreateDatabase(); } } private void menuItem1_Click(object sender, EventArgs e) { //Implementacin de Pull if (this.ceRDA != null) { try { string _oleConnectionString = @"Provider=sqloledb;Data Source=PORSOURCECODE\YUKON;Initial Catalog=RemoteDB;User id=sa;password=yukon2005beta"; ceRDA.Pull("usuarios", "select * from usuarios", _oleConnectionString,RdaTrackOption.TrackingOn); } catch (SqlCeException __ERR) { MessageBox.Show(__ERR.Message.ToString()); } } }

- 164 -

Programacin de Dispositivos Mviles

private void menuItem2_Click(object sender, EventArgs e) { //Implementacion de Push if (this.ceRDA != null) { try { string _oleConnectionString = @"Provider=sqloledb;Data Source=PORSOURCECODE\YUKON;Initial Catalog=RemoteDB;User id=sa;password=yukon2005beta"; ceRDA.Push("usuarios", _oleConnectionString, RdaBatchOption.BatchingOn); } catch (SqlCeException __ERR) { MessageBox.Show(__ERR.Message.ToString()); } } } } }

Merge Replication
Merge Replication es una tcnica ideal en dispositivos mviles ya que aporta autonoma e independencia al dispositivo a la vez que facilita el sincronismo de los datos cuando deseen ser volcados al servidor. Dentro de esta tcnica de sincronizacin hemos de distinguir entre Publicadores y Subscriptores. Los publicadores envan los datos y estos son recibidos por los Subscriptores, en el caso que nos ocupa, el publicador es la base de datos remota y el subscriptor es la base de datos del dispositivo mvil. En un entorno real, los datos tanto en local como en la base de datos cambian con el tiempo, empleando este modelo, la sincronizacin de los datos se realiza tanto en el servidor remoto como en el dispositivo mvil recuperando datos nuevos o las modificaciones de los datos existentes. Si bien es cierto que el despliegue y el mantenimiento de Merge Replication requiere de mucho trabajo, esta tcnicas posee ciertas ventajas que se deben tener muy en cuenta:

La replicacin posee caractersticas para resolver los conflictos de sincronizacin Permite la sincronizacin de datos de mltiples tablas en 'un tiempo' Permite llevar un seguimiento de cada publicacin

Es importante comprender y tener en cuenta que la sincronizacin mediante Merge Replication crea una cantidad de carga notable en el servidor. Cuando una base de datos se agrega como Publicador, la Metadata de dicha base de datos se modifica creando distintos 'Disparadores' y 'Procedimientos Almacenados' para facilitar la sincronizacin y la resolucin de conflictos. Adicionalmente a todas las tablas replicadas se les aade una nueva columna de tipo ROWGUIDCOL con el fin de mantener las tablas y de proporcionar a cada fila de un identificador nico. Esta nueva columna en la tabla causa un aumento del trfico de la memoria, por ejemplo en una tabla con nicamente 32 registros, el aumento de aadir el ROWGUIDCOL es de 1Kb = ( 16 bytes en el registro + 16 bytes en el ndice ) * 32. Para reducir el coste de la replicacin, es recomendable reducir la cantidad de datos que se van a sincronizar fijando los filtros de los datos que se van a publicar. Como comentamos, en RDA no est soportado el uso de IDENTITIES; sin embargo en 'Merge' Replication su uso es una buena tcnica de creacin de claves primarias. Las columnas en SQL Server pueden ser marcadas con la restriccin not for replication la cual permite inserciones de valores para un identity fuera del seed actual. El mtodo a seguir consistir en asignar rangos de identities al Publicador y a cada Subscriptor, estableciendo la restriccin not for replication en la tabla de SQL Server. Un caso prctico con Merge Replication En el anterior captulo vimos un caso prctico sobre como implementar RDA ( Remote Data Access ) para ello usamos una base de datos que habamos llamado RemoteDB, en este caso implementaremos el mecanismo de sincronizacin Merge Replication, para ello veremos los pasos uno a uno. 1. Abrimos Microsoft SQL Server 2005 ( superior) y nos conectamos al servidor. Desplegamos la ventana de Explorador de Objetos (Object Explorer). Desplegamos la pestaa Replication y en la subcarpeta hacemos doble clic para crear una nueva publicacin:

2. 3.

- 165 -

Programacin de Dispositivos Mviles

Creando la publicacin 4. 5. 6. 7. 8. 9. 10. 11. 12. Comenzamos el asistente para crear la publicacin Seleccionamos la base de datos que deseamos publicar En el tipo de publicacin seleccionamos 'Merge Publication' Seleccionamos Sql Server Mobile Edition en el tipo de Subscriptor Seleccionamos las tablas o vistas que deseemos publicar Especificamos los filtros, en caso de que se quiera, de las tablas a publicar Especificamos el comportamiento de SnapShop Agent Especificamos la cuenta bajo la cual va a funcionar el agente de SnapShop Especificacin del nombre de la publicacin

Creando la publicacin Una vez que hemos terminado el asistente de publicacin hacemos con el botn derecho del ratn clic en la publicacin y seleccionamos el asistente de Sincronizacin Web

- 166 -

Programacin de Dispositivos Mviles

Creando la publicacin 13. Seleccionamos si deseamos crear un nuevo directorio virtual o usar uno existente, en nuestro caso seleccionamos el que habamos creado para implementar RDA en el captulo anterior.

Creando la publicacin 14. Especificamos la autentificacin de los clientes de la publicacin, nosotros no vamos a requerir nombre de usuario ni contrasea

- 167 -

Programacin de Dispositivos Mviles

Creando la publicacin Con este ltimo asistente hemos terminado la primera parte de nuestro trabajo, ahora tendremos que agregar la subscripcin para esta publicacin para ello nos conectamos desde Sql Server Managment Studio a servidor de Sql Mobile y seleccionamos la base de datos que ser subscriptora de la publicacin que acabos de crear.

Creando la subscripcin (aplicable a SQL Server 2008 superior) En el Object Explorer expandimos Replications y en Subscriptors hacemos clic con el botn derecho para agregar un nuevo Subscriptor,seleccionamos el Servidor y la Publicacin para la cual vamos a ser Subscriptores .

- 168 -

Programacin de Dispositivos Mviles

Creando la subscripcin Una vez terminado el asistente ya estamos en disposicin de crear nuestra aplicacin para dispositivos mviles que implemente Merge Replication.

Creando la subscripcin A continuacin pasamos a ver un ejemplo de cdigo en el que se hace uso de Merge Replication, lo primero que vamos a hacer es configurar los parmetros necesarios para el uso de esta tcnica y posteriormente sincronizar la base de datos del dispositivo mvil con el servidor remoto.

private void menuItem1_Click(object sender, EventArgs e) { repl = new SqlCeReplication(); repl.InternetUrl = @"http:"//192.168.2.5/RemoteDb/sqlcesa30.dll"; repl.InternetLogin = string.Empty; repl.InternetPassword = string.Empty;

- 169 -

Programacin de Dispositivos Mviles

repl.Publisher = @"PORSOURCECODE\YUKON"; repl.PublisherDatabase = @"RemoteDB"; repl.PublisherSecurityMode = SecurityType.DBAuthentication; repl.PublisherLogin = @"sa"; repl.PublisherPassword = @"<...>"; repl.ExchangeType = ExchangeType.BiDirectional; repl.Publication = @"RemoteDbPublication"; repl.Subscriber = @"RemoteDbSubcriptions"; string pathDb = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); pathDb = Path.Combine(pathDb, "merge.sdf"); PathLocalDB = string.Format("Data Source={0}", pathDb); repl.SubscriberConnectionString = PathLocalDB; try { repl.AddSubscription(AddOption.ExistingDatabase); repl.Synchronize(); } catch (SqlCeException e) { MessageBox.Show(e.ToString()); } } Con esto ya tendremos sincronizada en nuestra base de datos de dispositivo mvil la base de datos del servidor remoto, y tal como se puede observar en la siguiente figura efectivamente la base de datos remota ademas de poseer los campos y registros sincronizados posee una serie de columnas nuevas que permitirn la resolucin de conflictos.

Creando la subscripcin El cdigo completo de nuestro sencillo ejemplo puede verse a continuacin.

- 170 -

Programacin de Dispositivos Mviles

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data.SqlServerCe; using System.IO; namespace Merge { public partial class Form1 : Form { SqlCeReplication repl; string PathLocalDB = string.Empty; public Form1() { InitializeComponent(); } private void menuItem1_Click(object sender, EventArgs e) { repl = new SqlCeReplication(); repl.InternetUrl = @"http:"//192.168.2.5/RemoteDb/sqlcesa30.dll"; repl.InternetLogin = string.Empty; repl.InternetPassword = string.Empty; repl.Publisher = @"PORSOURCECODE\YUKON"; repl.PublisherDatabase = @"RemoteDB"; repl.PublisherSecurityMode = SecurityType.DBAuthentication; repl.PublisherLogin = @"sa"; repl.PublisherPassword = @"<...>"; repl.ExchangeType = ExchangeType.BiDirectional; repl.Publication = @"RemoteDbPublication"; repl.Subscriber = @"RemoteDbSubcriptions"; string pathDb = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); pathDb = Path.Combine(pathDb, "merge.sdf"); PathLocalDB = string.Format("Data Source={0}", pathDb); repl.SubscriberConnectionString = PathLocalDB; try { //repl.AddSubscription(AddOption.ExistingDatabase); repl.Synchronize(); } catch (SqlCeException __ERR) { MessageBox.Show(__ERR.Message.ToString()); } } } }

Empaquetado y desplegado
Llegados a este punto del curso ya sabemos como usar Visual Studio 2005 para la creacin de aplicaciones para dispositivos mviles, adems hemos aprendido a trabajar con Sql Ce como motor de bases de datos para estos dispositvos, incluso hemos visto un mdudo de sincronizacin de datos con un servidor Sql Server remoto. An nos queda algo, que por sencillo, no deja de ser muy importante. Ya tengo mi aplicacin, pero cmo hago para instalarla en distintos dispositivos?. En este mdulo veremos los pasos necesarios para crear un instalador de nuestras aplicaciones de tal forma que con un sencillo clic se pueda instalar en un dispositivo mvil.

- 171 -

Programacin de Dispositivos Mviles

Creacin de instaladores
A continuacin veremos paso a paso como construir instaladores para nuestras aplicaciones para dispositivos mviles de una forma sencilla. Supongamos que ya tenemos nuestra aplicacin terminada, la llamaremos MSDNApp y queremos crear un instalador para poder redistribuirla, lo primero que tendremos que realizar ser crear el archivo de tipo .cab (Cabinet) que contendr el ejecutable, referencias y recursos necesarios de la misma.

Creando el .CAB de nuestra aplicacin


Para crear el archivo .CAB de nuestra aplicacin basta con agregar a nuestra solucin un nuevo proyecto de tipo Smart Device CAB Project, tal y como puede verse en la siguiente figura.

Agregando un nuevo proyecto de tipo Cab Project Una vez hecho esto agregamos el proyecto que deseamos empaquetar en el archivo .CAB y si es necesario aquellos archivos que necesitemos llevar, para ello nos situamos en el explorador de soluciones encima del proyecto de SmartDeviceCab, hacemos clic con el botn derecho del ratn y seleccionamos en el men contextual la opcin Add->Project Output o bien Add->File si es necesario.

Agregando elementos al archivo .CAB

- 172 -

Programacin de Dispositivos Mviles

Agregando elementos al archivo .CAB En este momento si generamos la solucin ya tendremos creado nuestro archivo de empaquetado .cab para nuestra aplicacin, estara situado dentro de directorio Debug o Release dependiendo de la configuracin de la solucin. Este archivo .cab podra ser llevado a cualquier dispositivo y ejecutndolo se iniciara el instalador. Sin embargo esto no es lo que queremos, nuestro objetivo es que con un solo clic en el instalador este sea capaz de iniciar el instalador de aplicaciones de ActiveSync para que realice todo el trabajo. En los siguientes puntos veremos como hacer esto.

Creando el instalador de la aplicacin


Para crear el instalador agregaremos un nuevo proyecto de tipo Setup tal y como puede verse en la siguiente figura.

Agregando elementos al archivo .CAB A este proyecto agregamos la salida del proyecto creado anteriormente para generar el archivo .CAB y un archivo Setup.ini que ser usado para la instalacin y que tendr la siguiente estructura

- 173 -

Programacin de Dispositivos Mviles

[CEAppManager] Version = 1.0 Component = MsdnTest [MsdnTest] Description = Descripcin de la aplicacion CabFiles = NombreCab.cab Este archivo .ini ser usando por la herramienta CeAppMngr.exe para instalar el archivo .cab en el dispositivo, Como se realiza esta accin ?. Para hacer que la herramienta CeAppMngr.exe ejecute el archivo .ini e instale el empaquetado .cab de nuestra aplicacin en el dispositivo mvil necesitaremos crear una accin persinalizada de instalacin. Nota: La herramienta CeAppMng.exe es parte de ActiveSync, por lo que este ltimo es un requisito obligatorio

Creacin de la accin de instalacin


Para crear la accin de instalacin crearemos un nuevo proyecto vacio en el que agregaremos un nuevo elemento de tipo Installer Class.

Cre ando la accin de instalacin

- 174 -

Programacin de Dispositivos Mviles

Creando la accin de instalacin Lo que tendremos que hacer es recuperar la informacin de la ruta de la herramienta CeAppMngr.exe para poder llamarla con el fin de que ejecute el archivo .INI creado anteriormente. El cdigo para esta accin personalizada puede verse a continuacin.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Configuration.Install; using Microsoft.Win32; using System.IO; using System.Windows.Forms; using System.Reflection; using System.Diagnostics; namespace CEAppMngrAction { [RunInstaller(true)] public partial class CeAppMngrInstall : Installer { public CeAppMngrInstall() { InitializeComponent(); } private void CeAppMngrInstall_AfterInstall(object sender, InstallEventArgs e) { string _lsPathSetupIni = string.Empty; _lsPathSetupIni = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Setup.ini"); if (File.Exists(_lsPathSetupIni)) RunCeAppManager(_lsPathSetupIni); else MessageBox.Show(" No se encuentra en archivo Setup.ini", "MsdnTest", MessageBoxButtons.OK, MessageBoxIcon.Error); } private void CeAppMngrInstall_AfterUninstall(object sender, InstallEventArgs e)

- 175 -

Programacin de Dispositivos Mviles

{ RunCeAppManager(null); } private void RunCeAppManager(string arg) { //Obtener la ruta de ceappManager string pathCEManager = string.Empty; string argsCeManager = string.Empty; RegistryKey keyCeAppManager = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\CEAPPMGR.EXE"); if (keyCeAppManager != null) { pathCEManager = keyCeAppManager.GetValue("").ToString(); argsCeManager = (arg != null) ? string.Format("\"{0}\"", arg) : string.Empty; Process.Start(string.Format("\"{0}\"", pathCEManager), argsCeManager); } else MessageBox.Show(" No se ha encontrado Active Sync, por favor instale primero este componente", "MsdnTest", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } Una vez creada nuestra accin personalizada simplemente hay que agregarla al proyecto Setup, para ello en el explorador de soluciones en el proyecto hacemos clic con el botn derecho y seleccionamos Ver->Acciones personalizadas.

Creando la accin de instalacin En la vista de acciones personalizadas seleccionamos la entrada Install y en el menu contextual hacemos clic en 'Agregar Accin Personalizada'.

Creando la accin de instalacin En este paso seleccionamos la salida del proyecto de accin personalizada que habamos creado.

- 176 -

Programacin de Dispositivos Mviles

Observaciones Si bien toda la creacin del paquete de instalacin parece una tarea complicada, realmente no lo es y una vez que hagamos el primero todo nos resultar muy sencillo e intuitivo. Los pasos que hemos seguido para la realizacin del paquete de instalacin se pueden resumir en los siguientes puntos.

Creacin del proyecto SmartDeviceCab que generar el .CAB de nuestra aplicacin Creacin del proyecto de Setup Creacin del archivo .INI que contendr una descripcin de nuestra aplicacin y el nombre del paquete .CAB que la contiene Creacin de la accin personalizada para invocar a la herramienta CeAppMngr.exe capaz de instalar automticamente la aplicacin en el dispositivo

Bibliografa:
Sitios Web. http://mosaic.uoc.edu/wp-content/uploads/dispositivos_moviles_y_multimedia.pdf http://156.35.151.9/~smi/5tm/09trabajos-sistemas/1/Memoria.pdf http://carrero.es/sistemas-operativos-para-dispositivos-moviles http://es.wikipedia.org/wiki/Dispositivo_m%C3%B3vil http://leo.ugr.es/J2ME/INTRO/index2.htm http://www.imai-software.com/openlab/data/proyectos/iPhone/iPhoneIntro.pdf http://www.nachocabanes.com/csharp/ http://iteso.mx/~monicad/p_trabajo.html

- 177 -

También podría gustarte