Devoxx 2009 - University days

November 24th, 2009

Como sabeis, cada año se celebra en Amberes el Devoxx (antes conocido como JavaPolis). Como Medianet no se pierde una, este año me ha tocado a mí representarnos en este evento que ,sin duda, es el más importante en Europa relacionado con el mundo java. devoxx.com

Los días se repartían en dos bloques, los University days (lunes y martes) y los Conference days (resto de la semana).

En el primero de ellos, las charlas eran de tres horas de duración y estaban orientadas al aprendizaje, al estilo de clases magistrales impartidas por algún experto.

Algunas de las mejores charlas a las que asistí tuvieron que ver con Java EE 6 y SOA. En la primera de ellas, Antonio Goncalves se marcó una serie de demos para presentarnos las novedades de Java EE 6, os pongo algunas de las características que más me llamaron la atención:

- Servlets 3.0: Presentó las nuevas anotaciones @Servlet que, por ejemplo, eliminan la necesidad de declarar y configurar el servlet en el web.xml. Además, ahora, los servlets tienen soporte para peticiones asincronas.

- EJB 3.1: La principal novedad residía en lo que han llamado EJB Lite, que permite empaquetar un EJB dentro de un WAR. con ciertas limitaciones. También se ha simplificado el tema de las interfaces, ya que si no se usan no es necesario crearlas. Otro punto a favor es que ahora los EJBs de sesión pueden tener métodos asincronos simplemente usando la anotación @Asynchronous sin necesidad de hacer nada más. Por último han creado un nuevo servicio que llaman “Time Service” que usando la nueva anotación @schedule permite programar ,como si de un video se tratara, el EJB para lanzar sus métodos en un momento determinado, al estilo del comando cron de Unix.

- JPA 2.0: Se ha enriquecido JPQL para dar soporte a joins en subqueries con la clausula FROM. También se ha incluido un nuevo nivel de cacheo que se puede usar con la anotación @cacheable. Se han incluido nuevas posibilidades para realizar los bloqueos (Lock, Read and Lock, Lock and Read…)

- JSF 2.0: Ahora JSF 2.0 está integrado en Java EE 6.

- BeanValidation 1.0 : Este nuevo paquete presenta funcionalidad para validar beans usando notaciones del estilo @NotNull, @size, @valid…. Se integra con JPA 2.0 y JSF 2.0

- JAX-RS 1.1: Ahora soporta RESTFul services. Añade notaciones para especificar diferentes tipos MIME (@Produces(”image/jpeg”), @Produces(”text/plain”)…)

Si quereis ver una lista completa y detallada de todas estas novedades podeis hacerlo en http://java.sun.com/javaee/technologies/javaee6.jsp

Ahora mismo, el único servidor que soportará el 100% de la nuevas características de Java EE 6 es Glassfish (implementación de referencia) que estará disponible en versión v3 el 10 de Diciembre. Ya podeís estar atentos. https://glassfish.dev.java.net/

Como he comentado más arriba, otra clase magistral que me gustó especialmente por su claridad y por el enfoque, fue la impartida por Sang Shin evangelista de SUN.

Estuvo presentando, con multitud de ejemplos, los fundamentos de SOA. Desde lo que era un WSDL hasta las tecnologías que permitian orquestar e integrar los distintos servicios BPEL y JBI. Usando para ello Glassfish ESB y NetBeans 6.7.1, este entorno proporciona unos muy buenos editores para hacer el trabajo con estas tecnologías algo más sencillo. Incluso, al final le dió tiempo a montarse un Single Sign On federado usando OpenSSO.

Si quereis seguir esta charla y aprender más sobre un montón de temas relacionados con el mundo java podeis hacer sus estupendos tutoriales en javapassion.com

Google Chrome OS

July 9th, 2009

Google ha anunciado que está desarrollando un Sistema Operativo diseñado especialmente para portatiles netbooks. El Sistema Operativo tendrá el nombre de Google Chrome Operating System.

Lo han definido como un sistema operativo ligero diseñado para que corra en procesadores x86 y ARM utilizando un núcleo Linux.

El enfoque es disponer de un sistema ligero que arranque muy rápidamente y que permita a los usuarios un acceso prácticamente inmediato a sus datos, que vivirán en la nube (Cloud Computing)

La lista de partners de Google para el proyecto Chrome OS es la siguiente.

* Acer
* Adobe
* ASUS
* Freescale
* Hewlett-Packard
* Lenovo
* Qualcomm
* Texas Instruments
* Toshiba

Aunque falten algunas empresas importantes, no quiere decir que no participen ya que irán ampliado la lista en el blog de Google Chrome.

Habrá que ver la evolución del proyecto y la aceptación por parte de los usuarios finales pero sin duda ayudará a la distribución del software libre y dado que será gratuito hará que aumente el uso de las aplicaciones de google.

Las supuestas primeras imágenes han aparecido en ChromeOSleak. Según la descripción hecha en el sitio de la filtración, la instalación de Chrome OS sería expedita y habría tomado solo 10 minutos, incluido un nuevo inicio de un PC portátil Acer Extensa 4620Z. Según la fuente, Chrome OS sería sorprendentemente rápido, aún en su actual etapa beta.

KIT - Ruby/Ruby On Rails

June 22nd, 2009

El pasado martes Pablo Martínez nos comentó a todos los rudimentos de Ruby y su framework Ruby On Rails.
Aunque evidentemente no fue más que arañar la superficie, si fue muy interesante ver como en apenas un cuarto de hora fue capaz de montar una aplicación con las funcionalidades básicas que podría tener un blog, haciendo notoria la velocidad de desarrollo que se puede alcanzar con esta herramienta.
Como conclusiones de la sesión podemos destacar las siguientes:

- Ruby/Ruby On Rails proporciona una gran velocidad y flexibilidad (Convention-Over-Configuration) al proceso de desarrollo
- Ruby/Ruby On Rails proporciona una gran número de componentes/librerías a través de sus Gems
- Ruby/Ruby On Rails tiene ciertos problemas de escalabilidad que se esperan solucionar en próximas versiones, aunque existen formas de paliar esta cuestión.
- Ruby/Ruby On Rails se encuentra en gran crecimiento como lo demuestran:
** La aparición de los primeros IDEs (RubyMine-Jetbrains, Eclipse RDT o Netbeans Ruby)
** Comienza a venir instalado con algunos sistema opetativos como Mac OS X Leopard … apps para IPhone en Ruby-Cocoa?
** El gran número de aplicaciones que están apareciendo basadas totalmente o en parte en esta plataforma, por citar algunos ejemplos:
—- Basecamp - 37 Signals
—- BumperSticker - una FaceBookApp de LinkedIn
—- o Twitter, originalmente completamente, y últimamente solamente el GUI y alguna otra cosa.
** La posibilidad de llevar las aplicaciones al “Cloud”:
—- bien con proveedores “especializados” como Joyent o EngineYard o
—- más generalistas como Amazon WS o GoogleEngine App (en este caso a través de JRuby)

Resumiendo, que aunque tal vez no sea ajustado a todos los casos, sí es algo a no perder de vista.

Cross domain policy files

May 12th, 2009

Ayer en la charla del Kit cuando comentaba la restricción que pone Silverlight a la hora de consultar servicios externos al dominio donde está alojado nuestra aplicación, surgieron muchas dudas acerca de si este era realmente el funcionamiento. Con este artículo pretendo dejar claro el funcionamiento de este mecanismo.

Todo esto viene de Flash, creadores de los ficheros crossdomain.xml, ficheros que especifican si un servicio o recurso es accesible o no por clientes que provienen de otros dominios. Este fichero debe estar en la raíz del dominio donde están alojados los servicios o recursos. La estructura de este fichero se puede consultar aquí: Cross-domain policy file specification

Silverlight hace uso de este tipo de ficheros de la misma forma que Flash, además que incluye también un nuevo tipo de fichero clientaccesspolicy.xml. Silverlight primero tratará de descargar este fichero y si no existe, tratará de descargar crossdomain.xml.

¿Qué ocurre con servicios que no son nuestros?

Es es la primera pregunta que nos puede surgir. Si yo quiero conectarme a los servicios web de Google, Flickr o Twitter, ¿les tengo que decir que me pongan ese fichero? Lo cierto es que todos los grandes servicios tienen ya este fichero configurado para acceso de forma general.

¿Y cuando no existe y no puedo hacer que lo ponga?

Para este caso existen alternativas.

Una de ellas sería hacer uso de la API de integración con el navegador para acceder al objeto JavaScript XMLHttpRequest y consultar a través de él el servicio en cuestión. XMLHttpRequest no hace esta comprobación de ninguno de estos ficheros Xml, aunque podríamos tener problemas con otras características de seguridad que implementen los navegadores para evitar XSS.

Otra alternativa es hacer que nuestro servidor nos haga de Proxy con el servicio o recurso del otro dominio. El problema de esta solución es la posible sobrecarga de nuestro servidor.

+Info

Android VS Microsoft. Primer asalto

February 24th, 2009

Al parecer, y según el siguiente articulo publicado en bloomberg
Google y Microsoft también se verán las caras en el cuadrilatero de los netbooks.

La nueva estrategia de Asus para sus nuevos netbooks es la de dotarlos con el sistema operativo Android, que hasta el momento tan solo era rival de los SS.OO. para moviles de Apple, Microsoft o Nokia.

Bien mirado, la apuesta de Asus por Android resulta completamente lógica. Buscaban un S.O. abierto (opensource), barato (gratis), y ligero (pensado para teléfonos móviles). La guinda del pastel la ponen la compatibilidad con las miles de aplicaciones creadas para Android y con los teléfonos móviles que en un futuro lleven este sistema operativo. ¿A quien no le gustaría tener en su teléfono móvil el mismo sistema operativo que lleva en su portatil?

FindBugs

February 9th, 2009

Desde hace un tiempo venimos usando FindBugs en el proyecto en el que estoy. Para el que no lo conozca, aunque por el nombre es fácil de adivinar, se trata de una herramienta para la detección automática de posibles bugs en nuestro código.

Antes de nada decir que esta aplicación sirve para analizar código Java y que requiere una versión de la JRE (o JDK) igual o superior a la 1.5.0. No obstante, esta “limitación” es solo para correr la herramienta, ya que es capaz de detectar posibles bugs en código compilado para cualquier versión de Java.

Aunque existe una versión stand-alone de la aplicación nosotros utilizamos un plugin para Eclipse que funciona a partir de la versión 3.3. Este plugin integra las funcionalidades de FindBugs en el entorno de desarrollo, creando menús contextuales para las acciones principales y aportando una página de preferencias donde personalizar el comportamiento de la herramienta.

Lo que hace FindBugs es simple: aplicar una serie de patrones para identificar código susceptible de ser un bug. El número de estos patrones es bastante elevado y de diferente severidad. Aquí la lista completa.

Las principales categorías en qué dividen los bugs y algunos ejemplos son:

- Correctness

Código que tiene pinta de ser erroneo debido a una equivocación del programador.

Ejemplos:

* Hacer un cast imposible, que siempre va a lanzar una ClassCastException
* Aparentes bucles infinitos
* Método que define una variable que se llama igual que un atributo de la clase o superclase
* Una variable que se sabe que es null y se utiliza en un instanceof (siempre va a devolver false)

- Bad Practice

Cuando nos hemos saltado alguna de las buenas prácticas recomendadas.

Ejemplos:

* Comparar Strings utilizando == o != en vez de .equals()
* Comprobaciones en clases que definen alguno de los métodos equals() o hashCode()
* Uso de identificadores que son palabras reservadas en versiones superiores de Java
* Método suscetible de dejar abierto un Stream ante una excepción

- Dodgy

Código confuso, anómalo o escrito de forma un tanto ofuscada.

Ejemplos:
* Un método que utiliza el mismo código para dos ramas distintas de un if. Puede ser un copy/paste mal hecho.
* Código con una referencia “hardcodeada” a una ruta absoluta
* Procurar devolver un array de longitud cero antes que null.
* Implementar un interfaz que ya está siendo implementado por una superclase.
* Algún case de una sentencia switch no acaba con break y ejecutará el código del siguiente case.

Aparte de estos ejemplos mas o menos simples hay otros bastantes mas complejos (sobre todo a la hora de detectarlos en ejecución) como pueden ser:

* Un método sobrescribe a otro que se encuentra en una clase Adapter que implementa un listener de java.awt.event o javax.swing.event. Esta situación haría que el método no se llamase al ocurrir el evento.
* Una clase que extiende Servlet y utiliza atributos de clase. Como sólo se crea una instancia de cada Servlet y luego se usa en múltiples hilos de ejecución, es muy probable que esta situación de algún problema. Se recomienda usar únicamente variables locales a los métodos.

En fin, como ya os decía hay una gran cantidad de posibles errores que es capaz de detectar.

En cualquier momento podemos decirle a FindBugs que no nos avise de determinados bugs que no consideremos realmente importantes, como puede ser alguna de las buenas prácticas que sea demasiado estricta o que no nos afecte directamente ya que no estamos desarrollando código referente a alguno de esos temas.

En cuanto a cómo usarlo, o mas bien cuándo usarlo, depende de cada uno, pero mi recomendación es intentar hacer una pasada siempre que se vaya a subir código a CVS (o al sistema de control de versiones utilizado). Por ejemplo, en nuestro caso tenemos el código repartido en diferentes plugins de eclipse y, cada vez que tocamos código en uno de ellos o creamos uno nuevo, pasamos un análisis a todo el plugin para identificar posibles puntos conflictivos.

Y si aun no os he convencido del todo, un último pensamiento: ¿cuántas horas habéis perdido intentando solucionar un error para al final daros cuenta de que es que “faltaba un punto y coma aquí”?

Dispositivos empotrados y SunSpot

January 31st, 2009

Aprovecho una mañana de sábado de insomnio para comentaros sobre el proyecto SunSpot. Ayer mientras escuchaba el podcast de enero de Javahispano (descargable aquí) escuché sobre la existencia de este proyecto.

SunSpot es un proyecto experimental de Sun cuyos objetivos quedan descritos en el siguiente párrafo:

Sun está presente en la actualidad en 6 billones (N. del T: billones americanos) de dispositivos en todo el mundo. Más de un billón (N. del T: idem) de dispositivos móviles ejecutan java. En Sun Labs estamos interesados en lo que viene a continuación. Para asegurar que la siguiente generación de dispositivos móviles está basada en tecnología Sun hemos desarrollado Sun Small Programable Object Technology (S.P.O.T). Hemos creado una plataforma experimental para inspirar la creatividad de los desarrolladores a la hora de crear el siguiente juguete, sensor, dispositivo, … quien sabe; empleando para ello tecnología Sun.

Al final un SunSpot es un dispositivo móvil (Procesador 180MHz 32-bit ARM920T con 512K RAM y 4M Flash), wireless (Antena y radio de 2.4 GHz, TI CC2420 compatible con IEEE 802.15.4), alimentado con batería (3.7V Recargable, 750 mAh Ion-Litio), que en su interior tiene una máquina virtual java (JavaMe). Lo que antes solo era posible desarrollar en C++ sobre dispositivos empotrados ahora se puede desarrollar en Java.

El dispositivo SunSpot puede recibir entradas de un conjunto de sensores que lo hacen perfecto como centro de control y coordinación de otros dispositivos. Junto al SunSpot vienen los siguientes:

SunSpot Development Kit
  • 3 acelerómetros (Regulables a 2G o 6G).
  • 1 Sensor de temperatura.

  • 1 Sensor de Luz.

  • 8 Leds tri-color.

  • 6 Sensores de entrada analógicos de corriente alterna-continua

  • 2 Interruptores instantáneos.

  • 5 pins de entrada/salida de propósito general.

  • 4 pins de salida de alta tensión.

El kit completo de desarrollo cuesta 630 euros, y contiene:

  • 2 Dispositivos SunSpot con los sensores antes indicados.
  • 1 Estación base. Que se enchufa al USB del ordenador y sirve como canal de comunicación entre el PC y los Dispositivos SunSpot.

  • Herramientas de desarrollo.

  • Tutoriales

  • Código de ejemplo

  • Accesorios adicionales (ver la foto).

Podeís obtener más información en la web del proyecto.

10 Años de SQL Injection

December 31st, 2008

Descubro via Chema Alonso( MVP Seguridad ): Link que el pasado 25 de Diciembre se cumplieron 10 años del paper donde se expone la técnica que más adelante pasaría a llamarse SQL Injection.
Link al paper original

¿ Que no sabes qué es Sql Injection ?. Resumiendo al máximo: es una técnica para atacar una aplicación que maneja sin cuidado la generación de consultas a BD, inyectando sentencias SQL en lugar de los valores esperados.

Según la Wikipedia: Wikipedia

Por poner un ejemplo claro y clásico:

Código de LogIn en la aplicación pide Usuario y Contraseña, accede a la BD y comprueba si existe una fila en la tabla Usuarios con los datos introducidos, si es así el usuario accede a la aplicación.

Si la generación de la consulta se realiza como sigue: ( Quien no lo ha visto en todos los lenguajes de programación posibles?, salvo en LINQ, claro ;) ).

string sql = "SELECT Count(*) FROM Usuarios WHERE NombreUsuario = '" + textBoxNombreUsuario.Text + "' AND Contrasenya = '"+ textBoxContraseñaUsuario.Text + "'";

Bien, si el usuario de la aplicación, espabilado él, introduce por ejemplo, como nombre de usuario: MiUsuario’ OR 1=1 — la consulta resultante sería:

string sql = "SELECT Count(*) FROM Usuarios WHERE NombreUsuario = 'MiUsuario' OR 1=1 -- AND Contrasenya = 'cualquier cosa que ponga'";

Donde “–” en SQL comenta el resto de la línea… por lo que la consulta va a evaluar solamente las filas cuyo usuario sea ‘MiUsuario’ OR 1 sea igual a 1…. que suele serlo :)

Éste es el ejemplo más simple, recordad que SQL permite realizar operaciones en batches, separando cada consulta por ‘;’, con lo que en casos tan extremos como el anterior se pueden llegar a inyectar acciones DML tan “simples” como pueden ser DROP TABLE o DROP DATABASE: MiUsuario’ OR 1=1; DROP TABLE Usuarios —

Evidentemente para que pudieran realizarse operaciones de DML en la Base de Datos el usuario que ejecuta las consultas tendría que tener esos permisos… y no debería tenerlos, debería lo menos crearse un usuario con los menos permisos posibles para ejecutar las consultas de la aplicación y otro administrador para gestionarla … pero igualmente no se deberían crear las consultas dinámicas que estamos viendo, así que mejor verlo junto :)

A partir de aquí surgen distintas variaciones de la técnica, basándose en la información que se puede obtener de la página, como por ejemplo:

-Time-Based SqlInjection: Inyectar queries en las que si se cumple la condición que esperas se ejecuta un delay con el que poder distinguir basándonos en el tiempo de respuesta si la condición se ha cumplido o no. El ejemplo básico sería deducir una password a base de ir encontrando cada caracter, sabiendo si es válido porque cuando lo es la ejecución de la página es más lenta debido a la query inyectada. En TechNet hay un artículo, también de Chema, al respecto: link

Además de las neuronas de quien pone a prueba la aplicación, existen Tools que realizan sofisticados ataques basados en diccionarios, comparando resultados de la página, aplicando Time-Based SQL Injection… un ejemplo de herramienta puede ser :sqlpowerinjector

Bueno, me estoy extendiendo demasiado y se me acaba el año :)

Espero que con este mínimo resumen haya despertado la curiosidad de algunos y elevado el nivel de atención a la seguridad. Recordad que en general estas técnicas son totalmente independientes del lenguaje de programación y de la Base de Datos, cada uno puede tener algún agujero o característica especial, pero las técnicas generales aplican a todos.

El año que viene opinamos sobre qué hacer para evitar estas vulnerabilidades, pero las recetas mágicas no existen y siempre será necesario ser consciente de las técnicas de ataque para intentar evitarlas en lo posible.

Ajax Facilito en Java - DWR

December 24th, 2008

Volviendo otra vez al proyecto actual en el que estamos asignados Dani Gonzalez y yo, nos hemos encontrado con que las versiones de Portlet y de JSF utilizadas no permiten el uso de componentes con comportamiento AJAX. En versiones posteriores estos problemas tienen solución e incluso existen librerías de componentes JSF muy potentes en este sentido (ICE Faces, RichFaces, Oracle ADF) pero como todos os imagináis a los dueños de una aplicación no suele gustarles que les digas que vas a invertir un tiempecito migrando a una nueva versión de algo que no conocen y que además para utilizarla es necesario cambiar la versión del servidor de aplicaciones en producción… así que hemos tenido que “invertar” alguna cosa, para dar ese comportamiento dinámico que nos requería el usuario final. Concretamente la primera petición de nuestros usuarios vino para recuperar la irradiación (cantidad de sol recibido por un punto de la superficie terrestre) a partir de las coordeandas seleccionadas por el usuario en un mapa (en este caso generado con Google Maps) sin necesidad de realizar un submit y recargar toda la página…

Estuvimos viendo distintas alternativas como dojo (aunque se caracteriza más por su librería de componentes gráficos javascript también tiene funcionalidad para realizar llamadas ajax), prototype, el uso del objeto XMLHttpRequest, y otros aunque finalmente nos decidimos por DWR dada la facilidad con la que se puede utilizar en un entorno Java. En realidad, después de un poco de tiempo trabajando con DWR coincido bastante con la forma en que ellos se definen en su site: “DWR es una librería java que permite al código java ejecutado en un servidor de aplicaciones y al código Javascript ejecutado en un navegador interactuar entre ambos de la manera más simple posible” y su eslogan es: “DWR is Easy Ajax for Java”

Bueno, a grandes rasgos nos encontramos con dos piezas que son necesarias para que esto funcione:

  • Un servlet java ejecutándose en el servidor que procesa las peticiones Ajax recibidas y devuelve la respuesta al navegador
  • Una librería javascript en el navegador utilizada para enviar peticiones al servidor y recibe las respuestas desde éste para actualizar la página que se muestra

Vale y como funciona realmente?

  • DWR genera dinámicamente el código javascript para que cada una de las clases java de servidor expuestas como servicios AJAX puedan ser accedidas desde javascript. Es decir el javascript generado por DWR crea un objeto javascript que puede ser referenciado desde cualquier parte de nuestro código js en el navegador.
  • El objeto creado se encarga de abstraernos de la comunicación con el servidor. Cuando se invoca a alguno de los métodos javascript ofrecidos se desencadena una llamada al servidor en la que DWR se encarga del envío y recepción (marshalling / unmarshalling) de los parámetros de forma transparente.

Y aquí tenemos un diagrama sencillo de como funciona.
Como funciona DWR

Si queréis ver un ejemplo muy sencillo de lo que hay que hacer para poner esto a funcionar podéis ir a un tutorial en la página oficial de DWR

A partir de la versión 2 (la actual es la 3) ofrece una funcionalidad que ellos llaman “reverse ajax” que permite realizar acciones “push” al estilo comet… También ofrecen dentro de la librería javascript un conjunto de funciones de utilidad para manejar los objetos HTML / JS en cliente / navegador. Y parece que también están trabajando en integrarse con algunos frameworks de componentes de interfaz de usuario como Dojo o Yahoo YUI .

En mi opinión hay otros frameworks / especificaciones que ofrecen una solución completa cubriendo el ciclo de peticiones en servidor (como por ejemplo JSF), pero para algo rápido, sencillo y fácil merece la pena… y si finalmente se integran con alguno de los frameworks de componentes gráficos que hemos dicho antes no habría que perderles la pista…

Motorola cambia Symbian por Android

December 22nd, 2008

Óscar Rodríguez, director de dispositivos móviles de la compañía en España, anunció el pasado miércoles 17 de diciembre, que el fabricante de móviles estadounidense ha decidido cambiar su estrategia y abandonar Symbian en todos sus aparatos multimedia por el nuevo sistema operativo de código abierto diseñado por Google.

Motorola viene sufriendo en los últimos meses, al igual que sus competidores, una caída de ventas por el desplome del consumo y ha decidido aprovechar esta crisis para cambiar sus teléfonos con el objetivo de competir mejor en un mercado cada vez más exigente, lo que le obligará a paralizar prácticamente toda su producción en 2009 para adaptar sus aparatos, con la inevitable caída de la cuota de mercado. Rodríguez afirmó en el anuncio que “La compañía está saneada y podemos aguantar tres trimestres con menores ventas a cambio de hacer una apuesta de futuro”.

Mientras se realiza la transición a Android los consumidores sólo podrán elegir entre uno o dos teléfonos Motorola por gama. A partir de ahora, los teléfonos de Motorola utilizarán tres sistemas: Android para los dispositivos multimedia, Windows Mobile para el mercado de aparatos profesionales y el sistema propio del fabricante para los teléfonos de gama más básica.

Motorola (que forma parte de la Open Handset Alliance) ya había anunciado en octubre su intención de adoptar Android como sistema operativo para algún modelo, para lo cual había anunciado una inversión de 50 millones de dólares. Ese anuncio se hizo justo después del lanzamiento en EEUU de su primer terminal con pantalla táctil (Krave ZN4), algo casi imprescindible para sacar partido a Android.

Por su parte Nokia, propietaria del 100% de Symbian, el líder de sistemas operativos para teléfonos móviles, anunció justo después del nacimiento de Android que en dos años el sistema operativo sería abierto, lo que unificará sus versiones y se abrirá a más fabricantes. La batalla está servida.