Más allá de lo que ves: 2013

domingo, 29 de diciembre de 2013

git-flow - Tan Sencillo y Tan Potente

En estos días de vacaciones navideñas en los que tenemos algo más de tiempo para estar en casa con la familia, sentado al lado de la chimenea y con Luz Casal (y los enanos) sonando de fondo, leo sobre Git y voy haciendo algunas pruebas.

Tengo que decir que llevo mucho tiempo trabajando con Subversion y el paso que supuso en su momento trabajar sin control de código fuente a hacerlo con VSC de Microsoft o el siguiente, cambiar de VSC a Subversion diría que se pueden quedar pequeños al lado de las posibilidades que le veo a Git.

Estoy usando diferentes recursos para iniciarme:

El libro Pro Git: http://git-scm.com/book/es
Los tutoriales de Atlassian sobre git: https://www.atlassian.com/git/tutorial
Los tutoriales de Atlassian sobre los flujos de trabajo que podemos utilizar para trabajar con git: https://www.atlassian.com/git/workflows

Comentando con un compañero del curro el tema, me indicó que en un Betabeers que hubo aquí en Badajoz, el ponente (Alfonso Alba García @aalbagarcia) parecía controlar sobre el tema, así pues lo busqué y localicé diferente recursos suyos, parte de la información que encontré fueron 3 vídeos en youtube que recogí en una entrada anterior Taller Git Drupal Camp 2013 de Cáceres Y parece que efectivamente controla sobre el tema.

El caso es que también dispone de un blog Aprende Git donde comenta sus experiencias y publica tutoriales relacionados con git.

Quiero recoger en esta entrada la serie que ha dedicado a Git-flow, mediante esta serie de tutoriales y la explicación de los Workflows de Atlassian me ha parecido impresionante la potencia y el control que git nos puede dar sobre el control del código fuente de nuestros proyectos. He de comentar que si bien está bien saber usar la línea de comandos para conocer lo que se debe hacer y como git-flow realiza numerosas tareas por nosotros, he descargado e instalado también SourceTree y todavía la cosa se simplifica muchísimo más, crear features, finalizarlas, abrir hotfixes, finalizarlos...

Al lío que me enrollo, los artículos relacionados con la serie git-flow en Aprende Git son:
  1. http://aprendegit.com/que-es-git-flow/
  2. http://aprendegit.com/instalacion-de-git-flow/
  3. http://aprendegit.com/git-flow-la-rama-develop-y-uso-de-feature-branches/
  4. http://aprendegit.com/git-flow-release-branches/
  5. http://aprendegit.com/git-flow-hotfix-branches/
  6. http://aprendegit.com/git-flow-resumen-y-conclusiones/
En cuanto al flujo de trabajo, "Git-flow", es referencia obligada Vincent Driessen y el artículo que en enero de 2010 publicó en su blog en el que compartía un flujo de trabajo que a él le estaba funcionando: “A successful Git branching model

Espero que esta información os pueda ser útil, en los artículos de Alfonso queda perfectamente explicado el uso de las ramas master y develop, las reglas que debemos aplicar para trabajar con unas y otras así como cuando y como usar las ramas feature, release y hotfix, os dejo una captura de SourceTree del proyecto que he ido usando para las pruebas en el se pueden observar ramas de feature, de release y de hotfix, gestionadas unas mediante consola con git, otras mediante consola con git-flow y otras con SourceTree.


Un saludo a todos.

viernes, 13 de diciembre de 2013

NO1 S6 - Móvil Chino - Alternativa Interesante

Recientemente he adquirido un smartphone DualSim, concretamente el módelo S6 de NO.1.

Tenía ganas hace tiempo de unir mi teléfono personal y el del trabajo en uno solo de modo que pudiera llevar un único móvil.

Buscando en AliExpress encontraba muchos modelos DualSim pero no sabía por cual decidirme, hay tantos modelos ! Finalmente elegí el NO.1 S6.

Tengo que decir que estoy muy muy muy contento con el.

Para los que no lo conozcan es una copia china del Samsung Galaxy S4, como copia es exacta. Lo he puesto al lado de un Galaxy S4 y salvo que el NO.1 S6 es aproximadamente 1 milímetro más grueso y que no pone SAMSUNG en el frontal ni en la tapa trasera, por lo demás es igual.

He probado todas las funciones y características y funcionan perfectamente:
  • Acceso a PlayStore - Correcto.
  • 3G en España - Correcto.
  • Reconocer ambas tarjetas SIM (ahora mismo Vodafone y Movistar) - Correcto. Puedes decidir desde que tarjeta llamar por defecto o bien que te pregunte cada vez que realizas una llamada por que línea deseas hacerlo. Existen aplicaciones en el Play Store para asignar una melodía a cada SIM, yo he instalado DualSim Ringtone
  • Bluetooth - Correcto.
  • Wifi - Correcto.
  • GPS - Correctísimo probado con Navigation y Runtastic.
  • Radio - Correcto.
Como puntos "en contra" que me gustaría que sepáis ya que al menos una de ellas yo la desconocía.
  • Las 2 tarjetas no son 3G, tan solo nos aceptará 3G en la SIM1 en la SIM2, no.
  • El alcance del Wifi es pobre en casa donde el NO.1 S6 no coge WIFI, el Samsung Galaxy S3 reproduce vídeos de Youtube de forma fluida y sin cortes y se navega por internet sin ningún problema.
A la hora de decidirme para adquirir el terminal me acabó de convencer este artículo de GizChina: NO1 S6 - El control por gestos llega a los clones
En definitiva, salvo estos dos puntos creo que es una opción muy a tener en cuenta por su precio, ahora está entorno a los 130 euros aproximadamente en el vendedor de Aliexpress al que lo compré http://www.aliexpress.com/store/342102 que fueron rápidos y muy serios ( NO1 S6 por 130 euros aproximadamente )

Un par de imágenes en su comparación con el Samsung Galaxy S4.





Saludos.


domingo, 1 de diciembre de 2013

MP4 a MP3 - Convertir vídeos en Mac

En esta ocasión os comento una utilidad para convertir videos mp4 a formato mp3 en Mac. Es libre y muy muy muy sencilla de usar.

En 3 sencillos puedes pasar un video a mp3.

1. Seleccionas el video que deseas convertir.
2. Seleccionas el formato al que deseas pasar el vídeo, en este caso mp3.
3. Pulsas en Run para convertir el vídeo.

Se trata de MacX Free MP3 Video Converter.

Sencillo no !


miércoles, 27 de noviembre de 2013

private app limit reached - PhoneGap Build Error

Haciendo pruebas con PhoneGap Build me he encontrado con el error:

private app limit reached

Es debido a que en PhoneGap Build de forma gratuita nos permiten tener una app. Lo que me ha ocurrido es que el proyecto lo cree sobre una carpeta y luego he creado una segundo proyecto que quiero sincronizar con la app anterior para usar PhoneGap Build y me encontraba con la traza del error:

mbp-de-fco:lisbon fjmontesinos$ phonegap build android
[phonegap] detecting iOS SDK environment...
[phonegap] using the remote environment
[phonegap] compressing the app...
[phonegap] uploading the app...
   [error] {"error":"Private app limit reached"}

Solucionarlo es sencillo, no tenemos más que indicar a phonegap el id de nuestra aplicación en PhoneGap Build.

En PhoneGap Build nuestra aplicación tiene un id como se puede ver en la captura. Anotamos el id asignado a la app.



Ahora nos vamos a la carpeta de nuestro proyecto y en el raíz debemos tener la carpeta ".cordova" y dentro el fichero "config.json".


Editamos este fichero y añadimos al final la información del id de nuestra aplicación como se muestra a continuación:

Debemos tener:
"name":"NombreDeNuestraApp"}

Debe quedar, donde 99999 será el id de nuestra app en PhoneGap Build:

"name":"NombreDeNuestraApp","phonegap":{"id":99999}}

Si ahora realizamos un build nos deberá funcionar correctamente.
mbp-de-fco:lisbon fjmontesinos$ phonegap build android
[phonegap] detecting Android SDK environment...
[phonegap] using the remote environment
[phonegap] compressing the app...
[phonegap] uploading the app...
[phonegap] building the app...
[phonegap] Android build complete

sábado, 23 de noviembre de 2013

Cambiar mensaje "Compañero de vida" en S4

Recientemente he adquirido un smartphone No.1 S6, clon del famoso y galardonado Samsung Galaxy S4 con el cual estoy muy muy muy contento, pero esto es tarea para escribir en otra ocasión una entrada sobre mi experiencia con este terminal.

En esta ocasión voy a ser breve. El No.1 S6 viene con Android 4.2.1. y al bloquearse se muestra el mensaje que se puede ver en los Samsung Galaxy S4 "Compañero de vida" o "Life Companion" en inglés. Eliminar o modificar este mensaje es sencillo.

Con el teléfono bloqueado no tienes más que mantener presionada la zona donde aparece el mensaje "Compañero de vida" o "Life Companion" y arrastrar hacia abajo, esto te mostrará un icono de edición donde podrás cambiar el mensaje o eliminar el widget y añadir otro.

Sencillo no !

viernes, 22 de noviembre de 2013

Humor Wasap


Icono Humor Wasap
Os dejo enlace a la app desarrollada por un compañero para que podáis pasar un buen rato viendo imágenes y desconectando un poco del "estrés" diario.

En poco tiempo se ha posicionado entre las 10 primeras de Google Play en aplicaciones de Humor para WhatsApp. La verdad es que la he instalado y esta muy bien, es muy fluida, no ocupan espacio en el teléfono las imágenes o gifs que se muestra, se optimizan el tamaño de las imágenes que se descargan con lo cual no tienes que preocuparte por exceder tu consumo de datos. Destacaría que te avisa cuando hay disponibles nuevas imágenes.

Una opción interesante a tener en cuenta si te gustan este tipo de aplicaciones.

No esperes descárgala ya !!!


Humor Wasap

domingo, 17 de noviembre de 2013

Taller Git Drupal Camp 2013 de Cáceres

Recientemente en la Drupal Camp 2013 - Cáceres ha tenido lugar un taller de #GIT que han publicado en el canal de Youtube Aprende GIT

Es un buen punto de inicio si quieres iniciarte en GIT si no tienes experiencia o si has usado hasta ahora otras herramientas para control de código fuente como #Subversion (como es mi caso) y quieres explorar nuevas opciones y o ver las diferencias entre uno y otro.

Aunque podéis acceder directamente a youtube y ver los vídeos los incluyo aquí para tenerlos como histórico.

También he encontrado muy útil los siguientes recursos un pdf de unas 100 páginas que muestra como funciona Git "internamente"

Cursos gratuitos en Code School:

https://www.codeschool.com/courses/git-real
https://www.codeschool.com/courses/try-git

Bueno y los 3 vídeos del taller. Podéis seguir al ponente en Twitter @aalbagarcia:




sábado, 19 de octubre de 2013

Hacer parpadear el título de página con jQuery

En algunas ocasiones se producen eventos en nuestra aplicación web pero el usuario no está en ese momento visualizando la pestaña o ventana en la que se ejecuta nuestra aplicación. Para esto podemos llamar su atención de diferentes maneras una de ellas es haciendo que el título de la pestaña parpadee con un mensaje.

Con el siguiente ejemplo se consigue este efecto de forma sencilla. Probado en Chrome, Safari y Firefox.

Espero pueda ser útil.

<html>
<head>
 <title>My Application</title>
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
 </script>
 <script type="text/javascript">
  (function () {
   var titleOriginal = document.title;   
   var intervalBlinkTitle = 0;

   // Inicia el parpadeo del título la página
   window.startFlashTitle = function (newTitle) {       
       if(intervalBlinkTitle == 0){
        document.title = 
         (document.title == titleOriginal) ? newTitle : titleOriginal;           

        intervalBlinkTitle = setInterval(function (){
         document.title = 
          (document.title == titleOriginal) ? newTitle : titleOriginal;           
        }, 1000);
    } 
   };

   // Para el parpadeo del título de la página   
   // Restablece el título
   window.stopFlashTitle = function () {       
       clearInterval(intervalBlinkTitle);
       intervalBlinkTitle = 0;
       document.title = titleOriginal;
   };
  }());
 </script>

</head>
<body>
 <button onclick="startFlashTitle('Hi, Joe !!!');">
  Start
 </button>
 <button onclick="stopFlashTitle();">
  Stop
 </button>
</body>
</html>

miércoles, 16 de octubre de 2013

Vaadin Spring Maven Archetype

Como comentaba en la entrada anterior Comando Tree para Mac ya he finalizado el archetype Maven base que crea un proyecto con Vaadin y Spring integrados de forma sencilla. Las versiones de Spring y Vaadin usadas como dependencias son Vaadin 7 y Spring 3.2.

Tanto el código con el que he creado (proyecto Maven) el archetype como el jar en su versión 0.8 los he puesto en GitHub.

Descargar el archetype: vaadin-spring-webapp-0.8.jar

El código está disponible para descargar y modificar/reutilizar según lo que necesitemos. Tengo pendiente de incluir algún tipo de licencia, pero ya lo veré con más tranquilidad.

Instalar el Archetype vaadin-spring-webapp

Para instalar el archetype en nuestro repositorio local una vez descargado no tenemos más que ejecutar desde la ubicación en la que tenemos descargado el archetype por ejemplo el siguiente comando desde consola:

mvn install:install-file                    \
   -Dfile=vaadin-spring-webapp-0.8.jar      \
   -DgroupId=org.fj2m                       \
   -DartifactId=vaadin-spring-webapp        \
   -Dversion=0.8                            \
   -Dpackaging=jar                          \
   -DgeneratePom=true


Crear un proyecto nuevo Maven con el archetype vaadin-spring-webapp

Una vez instalado el archetype en nuestro repositorio local vamos a crear un nuevo proyecto. Para ello voy a poner capturar de los sencillos pasos que debemos dar desde Eclipse, pero desde línea de comandos o IntelliJ por ejemplo sería similar:

1. Crear un nuevo proyecto en Eclipse.



2. Seleccionar Maven Project



3. Seleccionamos donde queremos ubicar el proyecto, por defecto en el Workspace con el que estemos trabajando.



4. Seleccionar el archetype instalado según indicaciones anteriores. Para ello podemos escribir vaadin-spring-webapp para que solo nos aparezca este.



5. Configurar el proyecto, definir: group Id, artifact Id, version, package y por último mediante una propiedad personalizada el nombre que le queremos dar a nuestra aplicación.



6. Ya tenemos configurado un proyecto Maven con Vaadin y Spring en el que contamos con un punto de entrada a la aplicación mediante la vista MainView.java, en esta se muestra un enlace a ExampleView.java que como su nombre indica es un ejemplo sencillo de vista Vaadin que consta de un formulario que solicita que el usuario introduzca su nombre y mediante una clase de servicio envía una clase de dominio a la capa de acceso a datos (Dao.java) que simplemente asigna el id de la clase de dominio recibida (Dominio.java) y pinta por consola el objeto recibido. Con este ejemplo tenemos lo básico para tener vistas, servicios, objetos de dominio y de persistencia.



7. Punto de entrada a al aplicación con enlace a la vista Vaadin de ejemplo.



8. Vista Vaadin de ejemplo con el formulario y la impresión por consola.


Espero sinceramente que pueda ser útil.

See you later !

domingo, 13 de octubre de 2013

Bricolaje Carpintería - Escritorio y Estantería en SketchUp

En este ocasión la cosa no va de tecnología, aunque al final la haya usado por el camino, para el objetivo final.

Quiero hacerle a mis hijos un escritorio junto con una estantería a cada uno para su habitación.

Después de tomar las medidas en las habitaciones, las medidas del escritorio y la estantería respectivamente serán:

Escritorio : 130 cm x 70 cm x 76,6 cm (ancho x fondo x alto)
Estantería : 120 cm x 33 cm x 38,2 cm

Una vez visto esto y hecho un pequeño plano en papel con lápiz he pasado a montarlo en 3D mediante SketchUp de Google.

El resultado es el que se puede ver en la imagen.

Ahora tan solo queda distribuir las diferentes piezas en tableros y llevar al almacén de maderas para que las corten y canteen.

Para la distribución de las piezas en los tableros utilizaré alguna herramienta como CutMaster a la cual le puedes indicar las dimensiones del(os) tablero(s), las dimensiones de cada una de las piezas, el número de ellas que necesitas, orientación de estas en el corte, bordes que irán canteados... Dispone de una opción para hacer la distribución automática más optima posible sabiendo así de una forma rápida el número de tableros que necesitarás para el trabajo.



sábado, 12 de octubre de 2013

Comando Tree para Mac

Siguiendo con el aprendizaje de Vaadin y con su integración con Spring estoy intentado realizar un "archetype" que permita montar una aplicación web con Vaadin y Spring configurado. Me he encontrado con un par de roquillas que para sortearlas he tenido que "googlear" un poco y que voy a recoger en este post por si a alguien (o a mi mismo en un futuro) le pueden ser de ayuda.

PRIMERA
Utilizar el comando "tree" en Mac sobre una carpeta desde línea de comando. Si bien parece que se puede instalar he encontrado una sentencia que desde línea de comandos nos hace el mismo efecto esta es la siguiente:

find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'



SEGUNDA
Para mostrar los archivos ocultos en el Mac si no se ven tan sencillo como ejecutar:

defaults write com.apple.finder AppleShowAllFiles TRUE
killall Finder

Para volver a ocultarlos:

defaults write com.apple.finder AppleShowAllFiles FALSE
killall Finder


TERCERA
Sobre un proyecto "Dynamic Web Project" de Eclipse si no nos permite pasar el facet web de la versión 3.0 a la 2.5, buscamos en los ficheros de la carpeta .settings del proyecto el que tiene por nombre: org.eclipse.wst.common.project.facet.core.xml

Cambiamos: <installed facet="jst.web" version="3.0"/>

Por: <installed facet="jst.web" version="2.5"/>


Tengo ya el archetype apunto de finalizar. Me quedan algunos retoques, la siguiente entrada será crear un proyecto web Maven, con Vaadin y Spring configurado en menos de un minuto.


See you later !

martes, 1 de octubre de 2013

Añadir archetype Maven: "vaadin-archetype-application" a Eclipse

Estoy viendo el uso de Vaadin desde Eclipse y al intentar crear un proyecto Maven con el archetype correspondiente "vaadin-archetype-application", me he encontrado con que no me aparecía este en la consola de Eclipse para seleccionarlo.

Para que aparezca no hay más que hacer clic en el botón "Add Archetype" e informar en el formulario de alta los siguiente:

  • Archetype Group Id: com.vaadin
  • Archetype Artifact Id: vaadin-archetype-application
  • Archetype Version: LATEST
  • Repository URL: lo dejamos vacío.




Pulsamos en ok y Eclipse se encarga de buscar en los repositorios de Maven que tiene configurados el "archetype" solicitado y descargarlo, para nosotros.

Ahora ya está disponible para poder seleccionarlo.


UPDATED (01/10/2013)
Una vez hecho todo eso y al correr el proyecto con el plugin de Jetty (goals= jetty:run) me aparecía el siguiente error:

Vaadin GWT compilation fails: nocache.js file not found

Para solventar lo que he hecho es quitar de la configuración del Servlet el parámetro widgetset, en mi caso la configuración para Servlet 3.0 venía realizada mediante la anotación @VaadinServletConfiguration, si por el contrario la configuración la tienes mediante web.xml para Servlet 2.5 -> lo que debes buscar es el parámetro widgetset en el web.xml y eliminarlo para que te corra bien el proyecto sin problemas.


Si por el contrario lo quieres ejecutar sobre un servidor por ejemplo Tomcat que tengas integrado ya en Eclipse -> no tienes más que hacer clic con el botón derecho y seleccionar "Run as" / "Run on a Server". Seleccionamos el tomcat en cuestión y voila !! tenemos un proyecto con Vaadin, Maven y Tomcat corriendo sobre Tomcat 5

viernes, 30 de agosto de 2013

Instalar Memcached en Mac

Guía sencilla para instalar Memcached.

El entorno de instalación ha sido en un Mountain Lion (10.8.4)

1. Instalar primero MacPorts descargar dmg para Mountain Lion

2. añadir al path /opt/local/bin y /opt/local/sbin export PATH=/opt/local/bin:/opt/local/sbin:$PATH

3. Actualizar macports $ sudo port -v selfupdate

4. Instalar memcached $ sudo port install memcached

5. Reiniciar. A mi no ha funcionado hasta que no he reiniciado, probablemente lo podría haber evitado pero no sabía el modo.

6. Lanzar como demonio $ memcached -d

7. Conectar mediante telnet:

$ telnet localhot 11211

8. Añadir un valor:

$ add key 0 0 17
javier montesinos
STORED

9. Obtener un valor por su key
$ get key
VALUE 0 0 17
javier montesinos
END

10. Parar el servicio memcached:

$ ps ux | grep memcached
$ pkill -f memcached

Ayuda: Comandos telnet para memcached

Revolucionando Javascript: Require JS, Backbone, Mustache...

Con la aparición de jQuery la programación en Javascript dio un salto cualitativo importante y a raíz de su puesta en escena comenzaron a surgir nuevas herramientas / frameworks que o bien la utilizan como base o la complementan.

El objetivo de esta entrada no es más que enumerarlas y de forma progresiva ir publicando una entrada específica para cada una de ellas en la que se muestre de una forma práctica su uso, que teoría ya hay mucha y muy bien escrita a nada que "Googleemos" un pelín.

  1. RequireJS como anuncian en su página nos permite cargar scripts (modular script loader) lo cual sin duda hará que nuestras aplicaciones sean mucho más ágiles.
  2. Underscore JS Nos ofrece unas 80 funciones primitivas que no se implementan de forma nativa o al menos no en todos los navegadores. Estas funciones nos ofrecen funcionalidad dividida en 5 grupos:  Collections, Arrays, Objects,  Functions y Utilities. Muy interesante y a tener en cuenta.
  3. Backbone Esta librería nos permitirá desarrollar aplicaciones javascript siguiendo el patrón MVC. Para aquellos que estemos familiarizados con este patrón agradeceremos su uso para estructurar nuestras aplicaciones con Modelos, Controladores y Vistas todo ello conectado si así lo deseamos a servicios REST.
  4. Mustache Como explican en su web es un sistema de plantillas “logic-less”. “Logic-less” significa que no dispone de sentencias de tipo if, else for... Las plantillas se definen únicamente con etiquetas. Mustache está implementado para diferentes lenguajes: Ruby, JavaScript, Python, PHP, Perl, Objective-C, Java, .NET, Android... Mustache.js es la implementación para Javascript.
Algunos recursos que parecen interesantes de Christophe Coenraets:

miércoles, 24 de julio de 2013

Sincronización desactivada en Android

Desde hace aproximadamente un mes en mi Galaxy S3 las cuentas de correo corporativo, Gmail, Google Calendar... no se sincronizan de forma automática. Cuando accedo a Ajustes / Cuentas y accedo a alguna de estas me aparece el texto "Sincronización desactivada"

Para solventarlo he instalado un widget que me permite activar la sincronización automática. He optado por Power Widget Lite de modo que he añadido el Widget con la opción de Sincronización Automatica (la segunda por la izquierda de las subrayadas de amarillo en la imagen inferior) a una de las pantallas de inicio.

He activado la opción de Sincronización Automática y Eureka! se ha solucionado el problema, ya me sincronizan las cuentas de forma automática.


Entiendo que en alguna actualización de android esta opción se ha perdido.

Por cierto, mi versión de android, la 4.1.2

sábado, 20 de julio de 2013

Xcode version installed is too old. Minimum: >=4.5.x - Phonegap

Pues nada que después de añadir la plataforma android a un proyecto phonegap he ido a añadir la plataforma ios y me reportaba el error "Xcode version installed is too old. Minimum: >=4.5.x"

Para ello he seguido lo que se comenta en este hilo y todo solventado the-installed-version-of-xcode-3-1-4-is-too-old-error-in-port-after-installi

Primeramente he ejectuado:

$ xcode-select -print-path

con la siguiente salida:

/Volumes/Xcode/Xcode.app/Contents/Developer

Posteriormente he ejecutado:

$ sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer/

Y ahora al ejecutar $ xcode-select -print-path la salida es:

/Applications/Xcode.app/Contents/Developer

Para añadir la plataforma ios al proyecto cordova no he tenido más que ejecutar:

$ cd hello
$ cordova platform add ios
$ cd platforms
$ ls

Y aparece la carpeta asociada a la plataforma ios para el proyecto

Platform add android not phonegap command

Si intentas trastear con phonegap sobre mac y sigues las indicaciones de la web de phonegap donde te indican que para instalarlo previamente instales Nodejs y posteriormente ejecutes: 

$ sudo npm install -g phonegap

No la utilices, utiliza la siguiente:

$ sudo npm install -g cordova

Con la primera cuando tengas que añadir alguna plataforma al primer proyecto de ejemplo mediante:

$ phonegap platform add android

Te aparecerá el mensaje que da título a esta entrada. Si instalas Phonegap usando la segunda opción cuando añadas una plataforma deberás usar el siguiente comando desde el directorio de un proyecto creado y esta vez si que te añadirá la plataforma.:

$ mkdir mis_phonegaps
$ cd mis_phonegaps
$ cordova create hello com.example.hello "Hola Mundo"
$ cd hello

Para añadir la plataforma los ejemplos indican usar:

$ cordova platform add android

El caso es que tampoco funciona, para ello borra el proyecto y lo vuelves a crear con los comandos:

$ cordova create hello com.montesinos.hello hello

De esta firma si que me ha funcionado tanto el crear proyectos como el añadir la plataforma android.

Para añadir la plataforma ios hay otro problema con la versión de Xcode, me dice que debe ser superior a la 4.5.x y tengo instalada la 4.5.2. pero eso ya es harina de otra entrada.

martes, 18 de junio de 2013

Listar tablas base de datos SQL Server

Es sencillo basta con ejecutar la siguiente sentencia:

USE NombreDeLaBD
GO 
SELECT *
FROM sys.Tables
GO

jueves, 30 de mayo de 2013

XML-RPC WordPress 3.5

En la entrada Activar Servicio XML-RPC en WordPress comentaba como activar los servicios XML-RPC para poder publicar mediante el uso de este servicio entradas directamente desde el móvil con la aplicación de WordPress por ejemplo para android.

Hay gente que me ha consultado la forma de activarlo en la versión 3.5.x, parece ser que en la versión 3.5.x de WordPress esta opción viene activada por defecto.

Os dejo un enlace en WordPress donde informan de esto XML-RPC Support

Extracto del recurso:

Enabling XML-RPC
XML-RPC functionality is turned on by default since WordPress 3.5.

In previous versions of WordPress, XML-RPC was user enabled

Espero que pueda servir de ayuda.

martes, 30 de abril de 2013

ASTROFOTOGRAFÍA






Aquí os dejo mis primeros pinitos en el mundo de la astrofotografía.....y qué frío he pasado!!

miércoles, 3 de abril de 2013

JODReports - Tutorial práctico.

Tras ver la gran aceptación que a tenido el tema de los reportes utilizando plantillas ODT y la librería JODReports y viendo la escasa documentación y ejemplos que se pueden encontrar en la red me dispongo a mostraros algunos ejemplos de utilización de esta herramienta así como algunas recomendaciones y posibles problemas que he tenido a lo largo de algunos proyectos con estos informes y la mejor forma que he encontrado de solucionarlo.
Este tutorial se divide en 2: en la primera mostraré la parte en java (básicamente coger la plantilla, enchufarle los datos y obtener el fichero final) y en la segunda, a mi entender, la mejor forma de construir una plantilla.
En el post anterior JODReports - Mini How to se describe la utilización básica de esta librería. Aquí repasaremos dichos ejemplos y ampliaremos con recomendaciones que por razones de desconocimiento no se mencionaron en el anterior.

1. JODReports: Sustitución de variables.

Para sustituir las variables en nuestra plantilla lo primero que debemos hacer es abrir nuestra plantilla, para ello utilizamos la siguiente línea:
DocumentTemplateFactory documentTemplateFactory = new DocumentTemplateFactory();

DocumentTemplate template = documentTemplateFactory.getTemplate(new File(ruta_fisica_plantilla/nombreFichero.odt));

Las variables a sustituir previamiente las hemos debido de cargar a un objeto Map
Map data = new HashMap();
data.put("nombre_variable", "valor_variable");
// añadir todas las variables a cambiar

Una vez tenemos la plantilla y las variables simplemente pasamos estas últimas a la plantilla y le indicamos el fichero de salida.
template.createDocument(data, new FileOutputStream(ruta_fisica_fichero_guardar//nombreFichero-final.odt));

Si queremos incluir imágenes en nuestra plantilla odt deberemos definir un ImageSource que también añadiremos a nuestro Map con las variables para que sea sustituida.
El objeto ImageSource se puede definir de las siguientes maneras:
ImageSource imagen = new RenderedImageSource(ImageIO.read(new File(ruta_fisica_imagen)));
ImageSource imagen = new FileImageSource(ruta_fisica_imagen);
ImageSource imagen = new ClasspathImageSource(ruta_fisica_imagen);

2. JODReports: Construcción de la plantilla.

Bueno llegados a este punto ya tenemos la parte de java desarrollada ahora vamos a construir la plantilla odt.
Recomendación MUY IMPORTANTE: Hay que intentar lo más posible hacer la plantilla enteramente desde el OpenOffice, si habéis leído el post anterior habréis observado que para introducir las sentencias de bucles o condicionales se recurre a abrir el fichero odt con winrar y editar el archivo content.xml esto es un error pues TODO el código que hayamos tecleado fuera de la estructura del documento si tenemos que editar la plantilla desde el OpenOffice para hacer alguna modificación en el contenido estático, al guardar todo será eliminado ya que el documento es reconstruido cada vez que guardamos.
Ahora empezamos a construir la plantilla. Lo primero será preparar todo el contenido estático del documento (contenido y formato). Es importante que el documento esté bien construido (por ejemplo: nada de 5 saltos de linea para conseguir la separación apropiada entre 2 párrafos nos vamos a propiedades del párrafo y le decimos que tenga una separación concreta con el siguiente o si necesitamos una página nueva hacemos un salto de página nada de salto de lineas hasta que salte de página).

Variables


Una vez que tenemos el contenido estático empezamos a introducir el contenido dinámico, lo primero y más sencillo las variables. Para insertar una variable simplemente ${nombre_variable}. Esta variable a de estar en nuestro Map principal. Esta variable puede ser un objeto simple (int, char, Integer, String, etc.) o un objeto complejo o un Map en tales casos para acceder a una propiedad (en el objeto) se hará ${nombre_variable.propiedad} o un value del objeto con ${nombre_variable.clave}.
Si necesitamos, por ejemplo, un contador dentro del documento o una variable podemos hacerlo de la siguiente manera:
[#assign contador = 1]
Acabamos de crear una variable "contador" con valor = 1. Para mostrarla simplemente ${contador}. Si necesitamos incrementarla, por ejemplo, lo podemos hacer de la siguiente manera :
[#assign contador = contado + 1]

Sentencia condicional


La sentencia condicional que tenemos disponible para mostrar u ocultar un bloque del documento es la siguiente.
[#if mi_variable = valor]
bloque de contenido...
[#else]
otro bloque...
[/#if]
¿Simple verdad? Ahora voy a explicar y a mostrar con un sencillo ejemplo un caso práctico de como utilizar esto correctamente, los posibles errores que podemos tener y como evitarlos o solucionarlos.
He aquí una captura de una plantilla con 3 párrafos (5 si contamos los 2 formados por la apertura y cierre del segundo if) y dos sentencias condicionales:
JODReports : ejemplo condicional if
En el ejemplo mostrado en la imagen, la primera condición de no cumplirse al generar el odt resultante hará que aunque el fichero se cree de forma correcta al tratar de abrirlo con OpenOffice nos de un error en la estructura. ¿la razón? la explico a continuación. El código interno de la plantilla tras guardarla para estos párrafos sería el siguiente:

<text:p text:style-name="P1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu varius diam. Curabitur quis tellus turpis. Nunc non nibh massa. Vestibulum et [#if variableUno = 1] <text:span text:style-name="T1"> lorem sed arcu hendrerit[/#if]</text:span> suscipit in ut mauris. Maecenas est ipsum, feugiat at rhoncus eget, scelerisque quis felis. Vestibulum elementum pellentesque pharetra. Donec commodo volutpat nunc vel cursus.
</text:p>
<text:p text:style-name="P1">
[#if variableDos = 1]
</text:p>
<text:p text:style-name="P1">
Nullam lorem elit, tempor fermentum sodales nec, ultricies a leo. Fusce vestibulum nisl eget libero pulvinar in accumsan libero pulvinar. Sed placerat tortor in arcu laoreet id convallis turpis rhoncus. Suspendisse sit amet mollis ante.
</text:p>
<text:p text:style-name="P1">
[/#if]
</text:p>
<text:p text:style-name="P1">
Aliquam vel lorem ligula. Donec convallis, ligula id dictum imperdiet, leo diam congue quam, in eleifend est neque eu tellus.
</text:p>

El código anterior es el que veríamos si abriéramos el odt de la plantilla con winrar y editáramos el content.xml. En el se pueden apreciar perfectamente los 5 párrafos que componen este documento (<text:p></text:p>). Como es un ejemplo muy simple el estilo para los 5 párrafos es el mismo (text:style-name="P1"). Para aplicar un estilo dentro del párrafo en linea se utiliza <text:span></text:span>.
Una vez aclarado esto podemos observar que para dar el formato de negrita en el documento se ha utilizado esta etiqueta span. ¿cuál es el problema con la primera sentencia? Si se cumple no hay problema, ahora si la condición no se cumple al generar el odt resultante se eliminará todo aquello dentro del [#if][/if] por lo que el código del párrafo generado será el siguiente:

<text:p text:style-name="P1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu varius diam. Curabitur quis tellus turpis. Nunc non nibh massa. Vestibulum et </text:span> suscipit in ut mauris. Maecenas est ipsum, feugiat at rhoncus eget, scelerisque quis felis. Vestibulum elementum pellentesque pharetra. Donec commodo volutpat nunc vel cursus.
</text:p>
Como se pude observar queda por ahí perdida una etiqueta de cierre del span que daba la formato al a la porción de texto dentro del párrafo. Esto va a producir un error al abrir el documento con OpenOffice pues la estructura de este no es correcta. Para evitar estos errores simplemente debemos de estar atentos al construir nuestra plantilla. Si el cierre del if [/#if] no hubiera estado en negrita significaría que esta fuera de ese span de formato y por lo tanto se eliminaría por completo todo el span y no se habría roto la estructura del documento. Y la plantilla sería correcta.
En la segunda sentencia no habría problemas de no cumplirse pues el código resultante sería correcto. Marco con un fondo más oscuro lo susceptible a desaparecer en el código si no se cumpliera la segunda condición.
La etiqueta de párrafo del sentencia [#if] en caso de no cumplirse la condición no se queda abierta ya que se cierra con la etiqueta de cierre del párrafo del cierre de la sentencia [/#if].

<text:p text:style-name="P1">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu varius diam. Curabitur quis tellus turpis. Nunc non nibh massa. Vestibulum et [#if variableUno = 1] <text:span text:style-name="T1"> lorem sed arcu hendrerit[/#if]</text:span> suscipit in ut mauris. Maecenas est ipsum, feugiat at rhoncus eget, scelerisque quis felis. Vestibulum elementum pellentesque pharetra. Donec commodo volutpat nunc vel cursus.
</text:p>
<text:p text:style-name="P1">
[#if variableDos = 1]
</text:p>
<text:p text:style-name="P1">
Nullam lorem elit, tempor fermentum sodales nec, ultricies a leo. Fusce vestibulum nisl eget libero pulvinar in accumsan libero pulvinar. Sed placerat tortor in arcu laoreet id convallis turpis rhoncus. Suspendisse sit amet mollis ante.
</text:p>
<text:p text:style-name="P1">
[/#if]
</text:p>
<text:p text:style-name="P1">
Aliquam vel lorem ligula. Donec convallis, ligula id dictum imperdiet, leo diam congue quam, in eleifend est neque eu tellus.
</text:p>
Resumiendo aunque no tengamos que editar el content.xml si que tenemos que construir la plantilla teniendo presente el código que se va a generar por debajo.

Iteración de listas


Para la iteración de objetos tipo List tenemos en JODReports la sentencia [#list nuestra_lista as item][/#list] y se utiliza de la siguiente manera:

Para iterar un List de Strings
[#list mi_lista_string as cadena]
${cadena}
[/#list]

Para iterar un list de objetos con sus propiedades
[#list mi_lista_object as item]
${item.propiedad}
[/#list]
A continuación vamos a ver unos ejemplos de iteración de listas, la lista estará formada por un listado de objetos Producto como el que se muestra a continuación.
public class Producto {
    private int id;
    private String nombre;
    private int cantidad;
    private float precioUnidad;

   // Constructores
   // ...
        
   // Getters and Setters
   // ...

}
Ahora vamos a ver 4 ejemplos básicos de iteración de listas, el porque de construir así la plantilla y el código que produce. Empezaremos viendo la captura de la plantilla con los 4 ejemplos.
JODReports : ejemplos de list
Ejemplo 1
En el primer ejemplo vamos a iterar un list en línea con el texto (dentro de un párrafo). En este caso la única consideración a tener en cuenta es la misma que vimos en el primer ejemplo de la sentencia condicional, es decir, tenemos que intentar prevenir que el list pueda romper algún estilo. Veamos el código interno producido y la parte que se va a repetir con cada iteración (con fondo más oscuro).

<text:p text:style-name="Standard">Ejemplo 1:</text:p>
<text:p text:style-name="Standard"> A continuación se mencionan el nombre de todos los productos:[#list productos as item] ${item.nombre}, [/#list]. Las propiedades de cada producto se detallan en cada tabla de producto.
</text:p>
Ejemplo 2
En este segundo ejemplo vamos a mostrar todas las propiedades del elemento Producto en una tabla individual por cada elemento o iteración. En principio tampoco contempla ningún tipo de complicación ya que la iteración se va a realizar sobre una estructura (una tabla, podría ser un párrafo, etc) completa por lo que no tendremos problemas de que se rompa la estructura aunque no contenga elementos la lista ya que en ese caso la etiqueta que se abre antes de la definición del [#list] se cerraría con la etiqueta de cierre de la etiqueta que contiene el cierre del list [/#list] (al no tener elementos que iterar todo lo contenido entre [#list] y [/#list] se eliminará). Veamos el código interno producido y la parte que se va a repetir con cada iteración (con fondo más oscuro).

<text:p text:style-name="Standard">Ejemplo 2:</text:p>
<text:p text:style-name="Standard">
  [#list productos as item]
</text:p>
<table:table table:name="Tabla1" table:style-name="Tabla1">
  <table:table-column   table:style-name="Tabla1.A"/>
  <table:table-column   table:style-name="Tabla1.B"/>
  <table:table-row>
    <table:table-cell table:style-name="Tabla1.A1" office:value-type="string">
      <text:p text:style-name="P1">
        Id
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla1.B1" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
         ${item.id}
      </text:p>
    </table:table-cell>
  </table:table-row>
  <table:table-row>
    <table:table-cell table:style-name="Tabla1.A2" office:value-type="string">
      <text:p text:style-name="P1">
        Nombre
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla1.B2" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.nombre}
      </text:p>
    </table:table-cell>
  </table:table-row>
  <table:table-row>
    <table:table-cell table:style-name="Tabla1.A2" office:value-type="string">
      <text:p text:style-name="P1">
        Cantidad
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla1.B2" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.cantidad}
      </text:p>
    </table:table-cell>
  </table:table-row>
  <table:table-row>
    <table:table-cell table:style-name="Tabla1.A2" office:value-type="string">
      <text:p text:style-name="P1">
        Precio
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla1.B2" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.precioUnidad}/ Unidad
      </text:p>
    </table:table-cell>
  </table:table-row>
</table:table>
<text:p text:style-name="Standard">
  
[/#list]
</text:p>
Ejemplo 3
En este tercer ejemplo vamos a iterar los elementos Producto del list dentro de una tabla sin cabecera de tal forma que cada elemento este en una fila y cada propiedad en una columna. La definición del list se hace en la primera columna de la tabla que tendrá los bordes superior, izquierda e inferior sin pintar u ocultos para que una vez generado el informe no se aprecie esta columna. En la segunda columna y en adelante vamos colocando las propiedades del objeto como se muestra. El cierre del list se hace en la primera columna de la segunda fila, ocultaremos también los bordes oportunos para hacer desaparecer esta fila al generar el informe. Esta forma especial de construir el list dentro de la tabla hará que las iteraciones hagan crecer la tabla sin romper su estructura tengamos 0, 1 o n elementos en el list. Veamos el código interno producido y la parte que se va a repetir con cada iteración (con fondo más oscuro).

<text:p text:style-name="Standard">
  Ejemplo 3:
</text:p>
<table:table table:name="Tabla2" table:style-name="Tabla2">
  <table:table-column table:style-name="Tabla2.A"/>
  <table:table-column table:style-name="Tabla2.B"/>
  <table:table-column table:style-name="Tabla2.C"/>
  <table:table-column table:style-name="Tabla2.D"/>
  <table:table-column table:style-name="Tabla2.E"/>
  <table:table-row>
    <table:table-cell table:style-name="Tabla2.A1" office:value-type="string">
      <text:p text:style-name="P2">
        [#list productos as item]
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla2.B1" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
         ${item.id}
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla2.B1" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.nombre}
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla2.B1" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.cantidad}
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla2.E1" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.precioUnidad} / Unidad
      </text:p>
    </table:table-cell>
  </table:table-row>
  <table:table-row>
    <table:table-cell table:style-name="Tabla2.A1" office:value-type="string">
      <text:p text:style-name="P2">
        
[/#list]
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla2.A1" office:value-type="string">
      <text:p text:style-name="P2"/>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla2.A1" office:value-type="string">
      <text:p text:style-name="P2"/>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla2.A1" office:value-type="string">
      <text:p text:style-name="P2"/>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla2.A1" office:value-type="string">
      <text:p text:style-name="P2"/>
    </table:table-cell>
  </table:table-row>
</table:table>
Ejemplo 4
El cuarto y último ejemplo de iterar listas es muy parecido al anterior se iteran las elementos rellenando una tabla solo que en este ejemplo la tabla lleva una cabecera en la primera fila. Al igual que en el ejemplo anterior el list se abrirá y cerrará en una columna a la cual ocultaremos los bordes oportunos para que al generar el informe no se visualice solo que en este caso la columna no será la primera sino la última. En la última columna de la cabecera abrimos el list, en la siguiente fila iteramos las propiedades del objeto y en la última columna de esta fila cerramos el list. Esta forma especial de construir el list dentro de la tabla hará que las iteraciones hagan crecer la tabla sin romper su estructura tengamos 0, 1 o n elementos en el list. Veamos el código interno producido y la parte que se va a repetir con cada iteración (con fondo más oscuro).

<text:p text:style-name="Standard">
  Ejemplo 4:
</text:p>
<table:table table:name="Tabla3" table:style-name="Tabla3">
  <table:table-column table:style-name="Tabla3.A"/>
  <table:table-column table:style-name="Tabla3.B"/>
  <table:table-column table:style-name="Tabla3.C"/>
  <table:table-column table:style-name="Tabla3.D"/>
  <table:table-column table:style-name="Tabla3.E"/>
  <table:table-row>
    <table:table-cell table:style-name="Tabla3.A1" office:value-type="string">
      <text:p text:style-name="P4">
        ID:
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla3.A1" office:value-type="string">
      <text:p text:style-name="P4">
        NOMBRE:
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla3.A1" office:value-type="string">
      <text:p text:style-name="P4">
        CANTIDAD:
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla3.D1" office:value-type="string">
      <text:p text:style-name="P4">
        PRECIO / UNIDAD:
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla3.E1" office:value-type="string">
      <text:p text:style-name="P2">
        [#list productos as item]
      </text:p>
    </table:table-cell>
  </table:table-row>
  <table:table-row>
    <table:table-cell table:style-name="Tabla3.A2" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.id}:
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla3.A2" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.nombre}:
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla3.A2" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.cantidad}:
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla3.D2" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        ${item.precioUnidad} / Unidad:
      </text:p>
    </table:table-cell>
    <table:table-cell table:style-name="Tabla3.E1" office:value-type="string">
      <text:p text:style-name="Table_20_Contents">
        
[/#list]:
      </text:p>
    </table:table-cell>
  </table:table-row>
</table:table>

Imágenes


Para incluir imágenes de forma dinámica en nuestra plantilla simplemente tenemos que insertar uma imagen abrir sus propiedades y en la pestaña "Opciones" indicamos para "Nombre" jooscript.image(nombre_variable) tal y como se muestra en la imagen.
JODReports : inclusión de imágenes
Y hasta aquí este post de JODReports y la construcción de plantillas desde OpenOffice. Espero que sirva si os estáis peleando con los informes. No olvidéis si os ha gustado y os ha servido de ayuda dejar un comentario y compartir. Cualquier duda no dudéis en preguntarla trataré de responder a la mayor brevedad posible.
Salu2

sábado, 23 de febrero de 2013

Blogger SEO - Personalizar tag Title

De forma general en las plantillas que se utilizan en Blogger puede aparecer una etiqueta como la siguiente para mostrar el título de las entradas de nuestro blog:
<title><data:blog.pageTitle/></title>
Este tipo de configuración mostrará como título para nuestras páginas a nivel de etiqueta TITLE algo como Título del blog: titulo de la entrada, así esta entrada tendría el título: Más allá de lo que ves: Blogger SEO - Personalizar tag Title Personalmente prefiero (y por lo que he podido leer mejora el SEO de nuestro sitio) que aparezca a la izquierda el título de la entrada con las palabras relevantes y al final de esta la fuente de la publicación. Para esto podemos modificar nuestra plantilla sustituyendo el contenido de title anterior por:
<title><data:blog.pageName/> - <data:blog.title/></title>
Sin embargo este código hará que nuestra home tenga como título algo como | Más allá de lo que ves, así para dejarlo completamente optimizado para home y para entradas usaremos el siguiente código en nuestra plantilla:
<b:if cond='data:blog.pageType == &quot;item&quot;'>
  <title><data:blog.pageName/> - <data:blog.title/></title>
<b:else />
  <title><data:blog.pageTitle/></title> 
</b:if>
Esto nos ofrecerá un título como el de esta entrada, ya que he modificado la plantilla según este cambio.

martes, 12 de febrero de 2013

Apps Android en Windows o Mac | BlueStacks

¿Quieres ejecutar tus aplicaciones Android en tu pc o en tu mac?  Ahora es sencillo no tienes más que descargarte la aplicación BlueStacks (http://www.bluestacks.com/) instalarla y ejecutar tus aplicaciones Android en tu ordenador.

Por defecto vienen preinstaladas una serie de aplicaciones pero puedes añadir las que quieras siempre que sean compatibles.

Por ejemplo, yo he probado a instalar WhatsApp y es muy sencillo.

1. Descarga e instala la aplicación BlueStacks.

2. Descarga el SDK de Android y lo descomprimes en una carpeta por ejemplo c:/android_sdk/ (http://developer.android.com/sdk/index.html)

3. Accede a la web de WhatsApp (http://www.whatsapp.com/) y descarga la aplicación "apk"

4. Lanza BlueStacks (esto iniciará una máquina virtual android con las aplicaciones que incorpora BlueStacks)

5. Desde una ventana de comandos accede a la carpeta "tools" ubicada en el SDK de Android y ejecutamos lo siguiente:

cd c:/android_sdk/tools/
adb connect localhost:10001
adb install c:/descargas/whatsapp.apk