viernes, 1 de abril de 2011

Android: Primeros pasos

¿Qué es Android?


Android es una plataforma software de código abierto que incluye un sistema operativo basado en el núcleo de Linux. Su diseño esta orientado a dispositivos móviles, y permite controlar dispositivos por medio de bibliotecas desarrolladas o adaptadas por Google mediante el lenguaje de programación Java.

Entre sus características principales destacan:
  • Framework de aplicaciones que posibilita el uso y reemplazo de aplicaciones.

  • Máquina Virtual Dalvik, muy parecida a la de Java pero optimizada para dispositivos móviles.

  • Navegador web integrado basado en el motor de código abierto WebKit.

  • Gráficos optimizados 2D y 3D.

  • Base de datos SQLite para almacenamiento estructurado disponible para las aplicaciones.

  • Soporte multimedia para los formatos más comunes de audio, video e imágenes.

  • Un importante entorno de desarrollo de aplicaciones que incluye emulador de dispositivos, herramientas de depuración, perfiles de memoria y rendimiento, y un plugin para eclipse.

Dependiendo del dispositivo hardware en cuestión también proporciona soporte para:
  • Telefonía GSM.

  • Bluetooth, EDGE, 3G y WiFi.

  • Cámara, GPS, brújula y acelerómetro.


Desarrollar aplicaciones Android


Introducción


Para comenzar a desarrollar aplicaciones para dispositivos Android es necesario hacer uso del conjunto de herramientas que se nos proporciona en el paquete de desarrollo Android SDK. Podemos acceder a estas herramientas a través de un plugin para Eclipse denominado ADT (Android Development Tools) o desde la línea de comandos. Si no queremos utilizar Eclipse también podemos elegir cualquier otro IDE o simplemente un editor de texto para desarrollar aplicaciones.

Instalar Eclipse


Si aún no tenemos instalado Eclipse, podemos descargar la última versión desde este enlace: http://www.eclipse.org/downloads/. Si sólo vamos a utilizar Eclipse para desarrollar aplicaciones Android se recomienda elegir la opción “Eclipse IDE for Java Developers”.



Si ya tenemos instalado Eclipse debemos asegurarnos de que sea una versión compatible con el plugin de Android, a partir de la versión 3.4 es suficiente.

Descargar el paquete de inicio del SDK


Antes de poder descargar y configurar el plugin ADT, es necesario instalar el “Android SDK Starter package. Este paquete no es un entorno de desarrollo completo, sino que solo incluye el núcleo de herramientas del SDK que podemos usar para descargar el resto de componentes del SDK.

Podemos descargar la última versión del SDK desde la página siguiente: http://developer.android.com/sdk/index.html


Si decidimos descargar el .zip, lo descomprimiremos en una carpeta segura de nuestro equipo. Por defecto, los ficheros del SDK son descomprimidos en un directorio llamado android-sdk-<machine-platform>.

Si descargamos el instalador de Windows y lo ejecutamos, automáticamente comprobará si tenemos instalada la versión adecuada de Java SE Developmet Kit (JDK), instalándola si fuera necesario, y después instalará las herramientas del SDK de Android en la ubicación por defecto.

Es importante recordar el nombre y la localización del directorio donde hemos instalado el SDK en nuestro sistema, ya que nos será necesario a la hora de configurar el plugin ADT y por si queremos ejecutar herramientas del SDK desde la línea de comandos.

Nota: Es necesario tener instalado Java SE Development Kit (JDK) para poder instalar el SDK de Android. Si no lo tenemos, se interrumpirá el proceso de instalación informándonos de ello y nos mostrará la siguiente ventana con un botón que nos enlazará al sitio de Oracle donde poder descargarlo.


Al final de la instalación, se nos pregunta si deseamos iniciar AVD Manager. Desmarcamos la casilla para que no se inicie ya que lo haremos a continuación desde Eclipse.

Instalar el plugin ADT para Eclipse


Una vez instalado el SDK podemos instalar el plugin ADT (Android Development Tools) proporcionado por Android, que esta diseñado para ofrecernos un potente entorno integrado para desarrollar aplicaciones Android.
Para ello abrimos Eclipse y:
  1. Seleccionamos en la barra de herramientas: Help > Install New Software...


  2. Hacemos clic en el botón Add, en la esquina superior derecha.

  3. En la ventana “Add repository” que aparece rellenamos el campo Name con el valor “ADT Plugin” y el campo Location con la siguiente URL: “https://dl-ssl.google.com/android/eclipse/”. Hacemos clic en OK.


Nota: si tenemos algún problema de conexión a la URL para obtener el plugin, podemos intentar usando “http” en lugar de “https” en la URL del campo Location.

  1. En el dialogo “Available Software” marcamos “Developer Tools” y hacemos clic en Next.


  2. En la siguiente ventana veremos la lista de herramientas que van a ser descargadas, hacemos clic en Next.


  3. Leemos y aceptamos los acuerdos de licencia, ya hacemos clic en Finish.




  4. Cuando se haya completado la instalación, reiniciamos Eclipse.

Nota: si aparece alguna advertencia de seguridad durante la instalación, podemos confiar en el equipo de Android y pulsar en Continue.

Configurar el plugin ADT


Una vez que hemos instalado el plugin ADT con éxito y reiniciado Eclipse, podemos proceder a configurar el plugin. Para ello modificaremos las preferencias de ADT en Eclipse para que haga referencia al directorio donde instalamos el SDK de Android.
  1. Seleccionamos en la barra de herramientas de Eclipse: Window > Preferences para abrir el panel de preferencias.


  2. Seleccionamos “Android” en el panel de la izquierda.

  3. Pulsamos el botón Browse junto al campo SDK Location, entonces seleccionamos la carpeta donde instalamos el SDK de Android.


  4. Hacemos clic en Apply y luego en Ok.


Añadir plataformas y otros componentes


El último paso para configurar nuestro SDK es usar Android SDK y AVD Manager (herramientas incluidas en el SDK) para descargar componentes esenciales en nuestro entorno de desarrollo.

Para lanzar Android SDK y AVD Manager desde Eclipse seleccionamos en la barra de herramientas el menú Window > Android SDK and AVD Manager.

Para descargar los componentes necesarios, usamos la interfaz grafica proporcionada por Android SDK y AVD Manager y seleccionamos en el panel lateral izquierdo Available packages y desplegamos Android Repository, en el seleccionamos, al menos, los siguientes elementos a instalar:
  • Android SDK Platform-tools, revision X.

  • Documentación for Android SDK, APIXX, revision X.

  • SDK Platform Android 2.2, API XX, revision X.

  • Samples for SDK, API XX, revision X.

A continuación pulsamos el botón Install Selected.


En la siguiente ventana marcamos la opción Accept All y pulsamos Install para comenzar la instalación.


Nota: Si durante el proceso de instalación se nos pide reiniciar en algún momento, pulsamos Yes.



Primera aplicación


Una vez que hemos que hemos completado la instalación, estamos listos para comenzar a desarrollar aplicaciones.

Hello, World


Como todos sabemos, la primera aplicación que se desarrolla en cualquier lenguaje de programación suele ser mostrar por pantalla el mensaje “Hello, World”, con Android no iba a ser menos. A continuación seguiremos una serie de pasos para crear nuestra primera aplicación Android.

Crear un AVD


Para poder probar cualquier aplicación, primero debemos crear un Dispositivo Android Virtual (AVD), este hará de emulador de un dispositivo Android y definirá las propiedades del dispositivo usado para emular nuestras aplicaciones. Para ello seguiremos los siguientes pasos:
  1. En el menú de herramientas de Eclipse elegimos: Window > Android SDK and AVD Manager.


  2. Seleccionamos Virtual Devices en el panel derecho y hacemos clic en New.


  3. En el dialogo “Create New AVD” que aparece, escribimos un nombre para el dispositivo en el campo Name y seleccionamos en Target la plataforma que vamos a utilizar (versión del SDK).

  4. El resto de campos los podemos ignorar por ahora, y hacemos clic en Create AVD.


Crear un nuevo proyecto Android


Una vez que hemos creado un AVD, el siguiente paso es crear un nuevo proyecto de Android en Eclipse:
  1. Desde Eclipse, seleccionamos: File > New > Project.


  2. Si todo fue instalado correctamente debería aparecer una carpeta llamada Android, que contiene la opción Android Project.

  3. Seleccionamos “Android Project” y hacemos clic en Next.


  4. En la ventana “New Android Project” que aparece, especificamos los detalles del proyecto, para nuestro proyecto “Hello, World” usaremos los siguientes valores:
    • Project Name: HelloWorldAndroid

    • Application Name: Hello, World

    • Package Name: com.forman.android.helloworld

    • Create Activity: HelloWorld



  5. Por último hacemos clic en Finish.

miércoles, 30 de marzo de 2011

jChart, Reportes con JasperRepots y iReports



1.- Introducción a Chart

1.1- ¿Por qué usar Charts y Graphs (cuadros y gráficos)?


Los gráficos y los cuadros son el método más eficiente de mostrar la

información de una manera sencilla. El uso de este tipo de representación ayuda a los

usuarios a comprender e interpretar la información más fácilmente y de manera más

eficiente, lo cual podría ser un proceso difícil y tedioso.

Todas las formas de gráficos y tablas incorporan algunos contenidos visuales en

la representación.


1.2- Diferencia entre Charts y Graphs.


Hay una diferencia muy pequeña entre estos dos términos que son usados para

añadir elementos visuales y espaciales que ayudan a la interpretación y comprensión de

la información.

Los charts se suelen usar datos simples de dos variables, como gráficos de barras o gráficos circulares.

También pueden usarse para hacer referencia a cantidades

que se refieren a mapas complejos de alta densidad.

Los graphs normalmente se refieren a temas matemáticos, por lo que en general

contienen los ejes X, Y o Z. En un graph ningún dato es representado sin usar los

ejes y, a veces, también es dividido en cuadrículas para facilitar la clasificación

de los datos.


1.3- Herramientas en Java de código abierto para chart.


Estas son las herramientas de terceros para los que los códigos fuente están

disponibles bajo un acuerdo de licencia de usuario General. Algunos de ellos son los

siguientes:

JFreeChart: Esta es una biblioteca Java libre para la creación de diferentes

tipos de tablas y gráficos, incluyendo:

Gráficos circulares (2D y 3D).

Gráficos de barras (regular y apilados, con un efecto 3D opcional).

La línea y de áreas.

Gráficos de dispersión y gráficos de burbujas.

Series temporales, alto/ bajo/ abierto/ cerrado cuadro y gráficos de vela palo.

Gráficos de Pareto. (Contiene líneas y barras).

Gráficas de Gantt.

Parcelas viento, tablas y gráficos metros símbolo.

Gráficos mapa de la oblea.

JCharts: es de un 100% de utilidad de gráficos basado en Java que hace salir

una gran variedad de gráficos. Este paquete ha sido diseñado desde cero por

voluntarios para la visualización de gráficos a través de servlets, JSP y

aplicaciones Swing.

JGraphT: es una librería Java de gráficos que proporciona teoría de objetos

matemáticos y la teoría de grafos y algoritmos. JGraphT soporta varios tipos de

gráficos, incluyendo:

Grafos dirigidos y no dirigidos.

Grafos ponderados / no ponderados/ etiquetados o cualquiera definido por el

usuario.

Varias opciones de borde múltiple, incluyendo: gráficos simples,

multigrafos, pseudografos.

Gráficos no modificables: permiten módulos que provean acceso de "sólo

lectura" a los gráficos internos.

Gráfo “escuchable”: permiten a los oyentes externos el seguimiento de los

eventos de modificación.

Subgrafos: gráficos que son auto-actualizados.


1.4- Introducción a jChart.

1.4.1- Descargando jChart.


La manera más sencilla de obtener jChart es visitar la página de descarga http://jcharts.sourceforge.net

/downloads.html y bajar

la versión más actual. En esta página no solo podemos encontrar el núcleo de la de

distribución de jChart, sino que también está la guía de usuario y varios proyectos de

terceros que lo integran.


1.4.2- Contenido del archivo.


Una vez descargado el archivo jCharts-x.x.x.zip, solo tenemos que

descomprimirlo en una carpeta, cuyo contenido será algo como parecido a esto:

jCharts-XXX

+--build

+--demo

+--docs

+--lib

+--src

--jCharts-x.x.x.jar

--jChartsServletExamples.var

El archivo jCharts-x.x.x.jar es la librería núcleo de jChart. Solo basta con añadir

este archivo al classpath para poder disfrutar de toda su funcionalidad.

La carpeta build contiene un fichero Jakarta Ant build, llamado build.xml.

La carpeta demo contiene el código para una aplicación demo en Servlet, así

como un ejemplo con Swing.

La carpeta docs contiene la información de la licencia y un archivo readme.html

con notas de los cambios de la versión.

La carpeta javadocs contiene los archivos javadoc para la librería jCharts.

La carpeta lib contiene librerías de soporte que se necesitan para usar algunas

características de jCharts.

La carpeta src contiene los fuentes de jChart. Después de todo, ¡es código

abierto!


1.5- Exportando imágenes.


jChart exporta a los siguientes formatos: PNG, JPEG, y SVG, a través de los

objetos del codificador en el paquete org.krysalis.jcharts.encoders. Cada uno de estos

codificadores tiene un método para codificar sus gráficos: encode(Chart chart,

OutputStream outputStream). Es una versión genérica, por lo que puedes pasarle

cualquier implementación de OutputStream, como FileOutputStream.

El soporte para JPEG y PNG es aportado por el SDK 1.4. En otras palabras,

necesitas el SDK 1.4 (o superior) para usar los codificadores de imagen.

El soporte para SVG es aportado por el proyecto Apache XML: Batik. Visita

http://xml.apache.org/batik/ para más información.


1.6- Imágenes desde un Servlet.


Hay una clase de ayuda, org.krysalis.jcharts.encoders.ServletEncoderHelper,

añadida para exportar charts desde Servlets y JSPs. Hay métodos en esta clase que

exportan a cualquier formato soportado por jChart, con la ventaja añadida de que

automáticamente configura el tipo MIME de los gráficos para tu navegador, por lo que

el navegador sabrá cómo renderizarlo correctamente.

Advertencia: Algunos usuarios intentan una imagen de un gráfico en disco y luego

devolver el flujo hacia el navegador. No es necesario, puedes simplemente dirigir la

imagen al navegador usando la clase mencionada anteriormente.





1.7- Gráficos en aplicaciones Swing.

También puedes usar jCharts en una aplicación Swing. Aquí dejo el ejemplo

SwingDemo del paquete org.krysalis.jcharts.demo.swing. Aquí, simplemente configura

el objeto Graphics de tu componente swing dentro del chart y llama a render();


import org.jCharts.chartData.ChartDataException;
import org.jCharts.chartData.PieChartDataSet;
import org.jCharts.properties.PropertyException;
import org.jCharts.properties.PieChart2DProperties;
import org.jCharts.properties.ChartProperties;
import org.jCharts.properties.LegendProperties;
import org.jCharts.nonAxisChart.PieChart2D;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowEvent;

public class SwingDemo extends JFrame {

private JPanel panel;
private PieChart2DProperties pieChart2DProperties;
private LegendProperties legendProperties;
private ChartProperties chartProperties;

public SwingDemo() throws ChartDataException, PropertyException {
initComponents();
}

private void initComponents() throws ChartDataException, PropertyException {
this.setSize(500, 500);
this.panel = new JPanel(true);
this.panel.setSize(500, 500);
this.getContentPane().add(this.panel);
this.pieChart2DProperties = new PieChart2DProperties();
this.legendProperties = new LegendProperties();
this.chartProperties = new ChartProperties();
this.setVisible(true);
addWindowListener(new java.awt.event.WindowAdapter() {

public void windowClosing(WindowEvent windowEvent) {
exitForm(windowEvent);
}
});
}

/***************************************************************
*
* @param graphics
**************************************************************/
public void paint(Graphics graphics) {
try {
String[] labels = {"BMW", "Audi", "Lexus"};
String title = "Cars that Own";
Paint[] paints = {Color.blue, Color.gray, Color.red};
double[] data = {50d, 30d, 20d};
PieChartDataSet pieChartDataSet = new PieChartDataSet(title, data,
labels, paints, this.pieChart2DProperties);
Dimension dimension = this.panel.getSize();
PieChart2D pieChart2D = new PieChart2D(pieChartDataSet,
this.legendProperties,
this.chartProperties,
(int) dimension.getWidth(),
(int) dimension.getHeight());
//***** BEGIN SWING SPECIFIC CODE **********************
pieChart2D.setGraphics2D((Graphics2D) this.panel.getGraphics());
pieChart2D.render();
//***** END SWING SPECIFIC CODE *************************
} catch (ChartDataException chartDataException) {
chartDataException.printStackTrace();
} catch (PropertyException propertyException) {
propertyException.printStackTrace();
}
}

private void exitForm(WindowEvent windowEvent) {
System.exit(0);
}

public static void main(String args[]) throws ChartDataException,
PropertyException {
new SwingDemo();
}
}


Este código resulta una imagen como esta:



2.- Creación de Reportes con JasperRepots y iReports: Reportes con Conexión a Base de Datos.


La siguiente prueba se realizará por medio de una aplicación standalone y no como plugin para NetBeans. Está aplicación es muy parecida a la interfaz del NetBeans.

La primera prueba a realizar consistirá en crear reportes haciendo uso de una conexión a la base de datos directamente desde nuestro reporte.

Lo primero que haremos es crear una base de datos con tablas y datos de pruebas para poder tener algo interesante que ver en nuestros reportes. Para ello, usaremos MySQL versión 5.1, usando el conector para Java versión 5.1.13.

La base de datos que usaremos para esta prueba se llamará "pruebaReportes", contiene la tabla "participantes" y constará de los siguientes campos:

  • Id: clave principal, bigint(21).

  • Nombre: varchar(100).

  • Username: varchar(100).

  • Password: varchar(100).

  • Comentarios varchar(100).

Ahora que tenemos nuestros datos crearemos un "datasource" en iReport para poder acceder a nuestros datos y hacer pruebas directamente, sin necesidad de una aplicación Java.

Para crear este datasource hacemos clic en el ícono "Report Datasources" ubicado en la barra de herramientas de iReport.

Con lo que se abrirá la ventana de "Connections / Datasources" que en este momento debe contener solo un "Empty datasource" y la conexión a una base de datos de prueba en HSQLDB. Ahora hacemos clic en el botón "New" para crear nuestro nuevo datasource.

En la nueva ventana que se abre seleccionamos "Database JDBC connection" y presionamos el botón "Next". En la siguiente ventana introducimos el nombre del datasource y los datos para establecer la conexión de la base de datos. Quedando de esta manera:



El botón "Test" nos servirá para comprobar la veracidad de todos los datos. Si es así, pulsamos "Save", para proseguir en la ventana "Connections / Datasources".

Ahora pasaremos a crear nuestro nuevo reporte. Esta será la primer y única ocasión en la que haremos uso del "Report Wizard" para ayudarnos a generar el reporte. Para esto vamos al menú "File -> New...".

Una vez abierta la ventana de "New File" seleccionaremos el formato de nuestro reporte. En este caso seleccionamos la plantilla "Wood", y hacemos clic en el botón "Launch Report Wizard".



Este wizard nos ayudará a crear un reporte 100% funcional en pocos pasos, que podremos ver desde el iReport:

  1. Selección de la localización en la que se guardará nuestro reporte.

  2. Selección del datasource y de la consulta sobre la base de datos.

  3. Selección de los datos que queremos mostrar en el reporte.

  4. Creación de grupos para el reporte.

  5. Selección del layout o acomodo de los datos en el reporte

Una vez elegido la localización y la base de datos que anteriormente creamos, "Conexion MySQL Pruebas". Completamos en “Query” con la consulta deseada pudiendo ser escrita de manera directa. En caso opuesto, y para facilitar nuestra tarea, pulsamos el botón "Design query" con lo que se abrirá una nueva ventana que está dividida en tres secciones.

La primer sección es la de la estructura de la consulta. Aquí básicamente podremos cambiar entre las sentencias que estamos editando (SELECT, WHERE, ORDER BY, etc.).

La segunda sección es la de los elementos de nuestra base de datos como tablas, vistas, y archivos temporales locales. Aquí podremos seleccionar los elementos de los que queremos obtener datos para la consulta.

Para terminar la tercera sección nos muestra los elementos que hemos seleccionado de la segunda sección para que podamos seleccionar los datos a obtener.La consulta que hemos confeccionado nos devolverá todos los datos de la tabla "participantes", con excepción del "ID". Para esto hacemos doble clic sobre el nombre de la tabla "participantes" en la segunda sección de la ventana que tenemos abierta.

Con esto aparecerá en la tercer sección otra ventana con el título "participantes" y un conjunto de checkboxes, cada uno con un campo de nuestra tabla. Completamos todos los campos deseados a mostrar. Pulsamos en el botón "OK", para continuar.



En el 4º paso tendremos que seleccionar cuáles campos de la consulta generada en el paso anterior queremos que se muestren en el reporte. Seleccionamos los deseados y hacemos clic en el botón "Next". Ahora hacemos clic en el botón "Finish" y ya podremos ver la plantilla de nuestro reporte. Si queremos ver como se verá el reporte final, en este caso, podemos ver un preview con los datos reales si cambiamos a la vista de "preview" en la ventana del editor.

Al hacer clic en la pestaña de "preview", nuestro reporte se compilará y se mostrará. En este caso el reporte puede ser pre-visualizado porque las siguientes condiciones se cumplen:

  • Tenemos una base de datos poblada.

  • Tenemos un datasource configurado para esta base de datos.

  • Nuestro reporte hace una consulta directa a esta base de datos a través de datasource anterior.

  • El reporte está preparado para mostrar los datos recuperados anteriormente.

  • Algo importante que ocurre al hacer este preview es que el reporte se compila generando el archivo "reporte1.jasper", el cual es el archivo que usaremos desde la aplicación Java que crearemos en un momento.

Si queremos compilar nuestro reporte de forma manual podemos hacer clic en el botón "Compile Report" de la vista de diseño:

Es posible realizar cambios de estilo para mejorar la visibilidad del reporte y cambios en el diseño por motivos meramente estéticos. Pudiendo dejarlo de esta manera:




Web services para dispositivos con Android y Facebook: Facedroid (Parte I)

El proyecto que hemos realizado ayuda a comprender mejor la interacción de un proyecto Android con las redes sociales. Estudiaremos concretamente la interacción con Facebook.

Para ello, hemos desarrollado una pequeña aplicación capaz de realizar publicaciones en los muros de Facebook los amigos que seleccionemos.

Para empezar vamos a mostrar cómo funciona el proyecto y luego se comentará el desarrollo del mismo.

La aplicación

La primera pantalla sólo consta de un botón para acceder a la validación de nuestro usuario de Facebook.

Una vez pulsado el botón, Facebook nos solicitará nuestras credenciales para poder acceder a la aplicación.

fig 1. Pantalla de Validación

Tras validarnos por primera vez, nuestro terminal Android nos informará que la aplicación necesita permisos para poder acceder a nuestra información personal de Facebook y a la información de los muros de los amigos. Tras conceder los permisos a la aplicación, aparecerá una ventana con todos nuestros amigos.

fig 2. Pantalla de Amigos.

En esta pantalla de amigos, tenemos la opción de buscar amigos introduciendo una parte del nombre del amigo.

Una vez seleccionados los amigos a los que deseamos publicar en su muro pulsamos el botón seleccionar para pasar a la ventana de publicación.

fig 3. Pantalla de Publicación

Tras escribir el mensaje deseado pulsamos el botón Publicar. Una vez que la aplicación detecta que se ha publicado correctamente, nos muestra un mensaje de confirmación.

Para continuar publicando mensajes debemos pulsar el botón Publicar más mensajes para volver a la pantalla de amigos para volver a empezar.



Instalación de
la api de facebook

Para empezar es necesario el archivo "fbconnect-android.zip" que se puede descargar del siguiente enlace:

http://code.google.com.iproxy.saverpigeeks.com/p/fbconnect-android/downloads/list

En la dirección anterior también se pueden encontrar capturas de pantalla de la configuración que hay que hay que realizar en el IDE para añadir la librería de android.

Hay que descomprimir el archivo y copiar la carpeta "api" en el workspace del IDE e importar el proyecto: Import… > Existing Projects into Workspace y seleccionamos el proyecto con nombre “api”.

Aparecerá en nuestro explorador de paquetes con fallos de compilación, esto sucede por dos motivos:

El primero es que le falta la librería de android, para ello hace falta instalar el SDK de android (descargar de aquí http://developer.android.com/sdk/index.html y ver instrucciones en la entrada del blog sobre ello).

Una vez instalado el SDK tendremos que añadir la librería en el proyecto (Build Path > Configure Build Path > Libraries > Add external jar.

fig 4. Configuración del path para añadir android a la api.

El archivo jar que necesitamos se encontrará dentro de la carpeta elegida para la instalación del SDK en la ruta "…\android-sdk-windows\platforms\android-X\android.jar" (deberemos elegir la versión "X" de android que nos convenga para nuestro proyecto).

El otro fallo de compilación es que el proyecto no tiene main. Esto no un problema que nos afecte.

El siguiente paso es exportar el proyecto como "Jar File" y nombrarlo "fbconnect.jar".

fig 5. Menú para exportar el proyecto.

Una vez creado el archivo jar, debemos añadir la librería "fbconnect.jar" en nuestro proyecto (Facedroid), tal como hicimos anteriormente.

Registro en facebook de la aplicación

Tenemos que registrarnos en facebook como developer en el siguiente enlace: http://www.facebook.com/developers/

Tendremos que darle permiso para la aplicación en nuestra cuenta y después nos saldrá una página como la siguiente.

fig 6. Página de desarrollador en facebook.

Para crear una nueva aplicación nos pedirá verificar nuestra cuenta mediante nuestro teléfono móvil o nuestra tarjeta de crédito con el siguiente mensaje:

fig 7. Verificación de cuenta.

Si se elige la opción del teléfono móvil llegará un mensaje sms al número que le hemos indicado con el código de activación. Lo introducimos y tendremos acceso para poder añadir nuestra aplicación. Incorporar la aplicación a tu cuenta de desarrollador es un paso muy importante ya que nos proporciona el número de identificación de la aplicación, que será necesario para incluirlo en el código de nuestro programa.

Utilización de las librerias Java Mail y envío de SMS

1.- Introducción

En esta serie de artículos vamos a empezar a usar JavaMail. Aunque en la página de SUN ponga que es para J2EE, la verdad es que esta librería nos permite enviar y recibir correos desde cualquier aplicación java.

Veremos en primer lugar qué tenemos qué descargar, puesto que JavaMail no viene por defecto con Java y necesita, además, otra librería adicional, JAF (o JavaBeans Activation Framework).

Luego, de la forma más directa posible y un mínimo de explicaciones para entender lo que estamos haciendo, haremos tres ejemplos con JavaMail:

  • Leer un correo

  • Enviar un correo

  • Enviar un correo con datos adjuntos.

Para nuestros ejemplos usaré la cuenta de gmail, así que la configuración que veas es para dicha cuenta. Si tienes otro servidor de correo, tendrás que mirar cómo es la configuración con tu servidor y cambiar los parámetros adecuados en la configuración de JavaMail.



2.- ¿Qué necesitamos descargarnos para usar JavaMail?

Para usar JavaMail necesitamos descargarnos la librería de JavaMail de la página de SUN. Puedes bajártela aquí:

http://www.oracle.com/technetwork/java/index-138643.html

Acepta las condiciones, bájate el zip, desempaquétalo y añade los jar que vienen a tu proyecto.

JavaMail utiliza otra librería, JAF, que también debes descargarte:

http://www.oracle.com/technetwork/java/javase/tech/index-jsp-138795.html

El activation.jar que viene ahí también debes añadirlo a tu proyecto, igual que los anteriores.

Ya tienes todo lo que necesitas para usar JavaMail.



3.- Ejemplos con JavaMail

Vamos a ver tres ejemplos sencillos con JavaMail, de más sencillo a más complejo:



4.- Envío de un correo de texto

Para el ejemplo, usaremos una cuenta de gmail como servidor de correo.

La configuración de esta cuenta (de cualquier cuenta de gmail) para el envío de correos es

  • Requiere usuario y password. El usuario es la cuenta de correo, pondremos por ejemplo, ejemplo@gmail.com

  • Protocolo smtp

  • TLS si está disponible

  • Puerto 587, que no es el de defecto de smtp.

Clases y configuración de JavaMail para el envío de mensajes

Para este ejemplo sencillo, hay tres clases de JavaMail implicadas:

  • Session: De alguna forma representa la conexión con el servidor gmail de correo. Hay que obtenerla pasándole los parámetros de configuración para el servidor de correo -gmail en nuestro caso-.

  • Transport: Clase para el envío de mensajes. Se obtiene llamando al método getTransport() de la clase Session.

  • MimeMessage: El mensaje.

Creación y configuración de la clase Session de JavaMail

La clase Session representa nuestra conexión con el servidor de correo -gmail en nuestro caso-. Se obtiene con el método Session.getDefaultInstance() pasándole un parámetro:

  • Un Properties con las propiedades de la conexión.

Properties es una clase de java estándar java.util.Properties. Esta clase admite que guardemos en ella parejas "clave-valor", es decir, guardamos datos -de tipo String- dándoles un nombre a cada uno para luego poder recuperarlos. Esto se hace por medio del método setProperty(), de esta manera

Properties p = new Properties();
p.setProperty("un nombre", "un valor");
p.setProperty("PI", "3.1416");

Las Properties que necesita Session son específicas, es decir, tienen que tener unos nombres concretos y unos posibles valores concretos. En la API una lista de algunas de ellas y también en la API tienes una lista más completa.

Veremos aquí sólo las estrictamente necesarias para conectarnos con gmail y poder enviar mensajes. El código sería este

Properties props = new Properties();

// Nombre del host de correo, es smtp.gmail.com
props.setProperty("mail.smtp.host", "smtp.gmail.com");

// TLS si está disponible
props.setProperty("mail.smtp.starttls.enable", "true");

// Puerto de gmail para envio de correos
props.setProperty("mail.smtp.port","587");

// Nombre del usuario
props.setProperty("mail.smtp.user", "ejemplo@gmail.com");

// Si requiere o no usuario y password para conectarse.
props.setProperty("mail.smtp.auth", "true");

Con esto estamos en disposición de obtener nuestra instancia de Session.

Session session = Session.getDefaultInstance(props);
session.setDebug(true);

Hemos puesto setDebug(true) para obtener más información por pantalla de lo que está sucediendo. Una vez que el programa nos funcione, podemos quitar esa línea sin problemas.

Ya tenemos nuestro objeto Session.

Construir el mensaje para enviar con JavaMail

Vamos ahora a construir un mensaje simple de texto. Para ellos instanciamos la clase MimeMessage y le ponemos varios datos.

En el constructor debemos pasarle el objeto Session que obtuvimos anteriormente

MimeMessage message = new MimeMessage(session);

Ponemos luego el FROM y el TO del mensaje, es decir, quién lo envía y a quién va dirigido. Para meter estos datos usaremos los métodos setFrom() y addRecipient() de MimeMesage. Los parámetros que admiten estos métodos son instancias de javax.mail.internet.InternetAddress. En el constructor de esta clase InternetAddress símplemente ponemos la dirección de correo -ver código más abajo-.

Para los destinatarios usaremos el método addRecipient() de MimeMessage. Esta método admite dos parámetros, una constante para indicar el tipo de destinatario y otro que es el InternetAdress mencionado. El tipo de destinatario puede ser

  • Message.RecipientType.TO Destinatario principal del mensaje

  • Message.RecipientType.CC Destinatario al que se envía copia del mensaje

  • Message.RecipientType.BCC Destinatario al que se envía copia, pero sin que los demás destinatarios puedan verlo.

En nuestro caso, sólo pondremos el TO y la dirección de correo.

// Quien envia el correo
message.setFrom(new InternetAddress("ejemplo@gmail.com"));

// A quien va dirigido
message.addRecipient(Message.RecipientType.TO, new InternetAddress("destinatario@dominio.com"));

Ahora sólo queda llenar el asunto -subject que dirían los ingleses- del mensaje y el texto. Como tenemos métodos para ello, setSubject() y setText(), no hay ningún problema.

message.setSubject("Hola");
message.setText("Mensajito con Java Mail" +
"de los buenos." +
"poque si");

Ya tenemos construido el mensaje.

Un pequeño detalle nada más. Este mensaje es de texto y el formato que se está usando es texto "plano", es decir, texto normalito, tal cual, sin más. Hay muchas formas de enviar texto. Se puede enviar, por ejemplo, en formato html, con lo que podríamos poner negritas, cursivas, etc.

Para enviar texto con otros formatos, debemos usar el mismo método setText(), pero con más parámetros. En concreto, podemos usar la versión de setText() que admite tres parámetros

  • El texto, en formato html -o el que decidamos-

  • El juego de caracteres a utilizar. Por ejemplo, puede ser "ISO-8859-1", que corresponde a nuestro juego de caracteres.

  • El formato a utilizar. Para un html sería "html". No se puede poner cualquier cosa, hay que utilizar subtipos estandar de los tipos MIME (Multipurpose Internet Mail Extension). Al utilizar setText(), la primera parte de este tipo se presupone "text". El subtipo "hmtl" es el que ponemos aquí.

El siguiente código crearía el mismo mensaje, pero con texto html y algún adorno de negrita y cursiva

message.setText(
"Mensajito con Java Mail
" + "de los buenos." + "poque si",
"ISO-8859-1",
"html");

Enviamos el mensaje

Para enviar el mensaje usamos la clase Transport, que se obtiene de Session. El método getTransport() requiere un parámetro String con el nombre del protocolo a usar. Como el de gmail es smtp, pues ponemos smtp.

Transport t = session.getTransport("smtp");

Ahora debemos establecer la conexión, dando el nombre de usuario y password.

t.connect("ejemplo@gmail.com","la password");

y ahora simplemente enviamos el mensaje

t.sendMessage(message,message.getAllRecipients());

El método de enviar mensaje es sendMessage() y NO sólo send(). El método send() es estático y no tiene en cuenta la conexión, ni el usuario ni la password. Es una forma rápida de envio de mensaje para un servidor smtp que no requiera autentificación. Como no es el caso, debemos usar sendMessage().

El método sendMessage(), además del mensaje, necesita la lista de receptores del mensaje, es decir, el array de direcciones a los que va el mensaje. La forma rápida de obtener este array es llamar al método getAllRecipients() de la clase MimeMessage, justo como lo hemos hecho en el código.

Con esto se envía el mensaje. Ahora solo queda cerrar la conexión

t.close();

Ejemplo completo:

package tucuenta.ejemplos.mail;

import java.util.Properties;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class EnviarMail
{
/**
* main de prueba
* @param args Se ignoran.
*/
public static void main(String[] args)
{
try
{
// Propiedades de la conexión
Properties props = new Properties();
props.setProperty("mail.smtp.host", "smtp.gmail.com");
props.setProperty("mail.smtp.starttls.enable", "true");
props.setProperty("mail.smtp.port", "587");
props.setProperty("mail.smtp.user", "tucuenta@gmail.com");
props.setProperty("mail.smtp.auth", "true");

// Preparamos la sesion
Session session = Session.getDefaultInstance(props);

// Construimos el mensaje
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("yo@yo.com"));
message.addRecipient(
Message.RecipientType.TO,
new InternetAddress("tucuenta@gmail.com"));
message.setSubject("Hola");
message.setText(
"Mensajito con Java Mail" + "de los buenos.");

// Lo enviamos.
Transport t = session.getTransport("smtp");
t.connect("tucuenta@gmail.com", "la clave");
t.sendMessage(message, message.getAllRecipients());

// Cierre.
t.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}





5.- Recepcion de un correo con JavaMail

Leer un correo tonto de texto con JavaMail es bastante sencillo, pero si nuestro programa hace eso a piñón fijo, no podremos leer cualquier correo que nos llegue.

La estructura real de un correo, con adjuntos y posibilidad de visualizarlo en texto plano o html es algo compleja, pero debemos tratarla para poder leer cualquier correo.

En este tutorial haremos un ejemplo de lectura de correo con JavaMail, teniendo en cuenta todo esto, pero sin complicarnos demasiado la vida. Lo justo para ver cómo leer correos con JavaMail y empezar a entender la estructura de estos correos complejos.

El comprender estos correos complejos nos ayudará, más adelante, a construir y enviar con JavaMail correos que van más allá de un simple texto.

Servidor de gmail

En el ejemplo, usaré una cuenta de gmail para conectarme con ella y obtener los correos del buzón inbox (carpeta de entrada). Si usas otro servidor de correo, deberás cambiar los parámetros de configuración de acuerdo a tu servidor.

La configuración de gmail para leer los correos es la siguiente

  • Tener POP habilitado. Entra en tu cuenta de gmail y arriba a la derecha pincha "configuración". En la nueva pantalla pincha "Reenvio y correo POP". Asegúrate de que pone "POP habilitado" o marca la opción "Habilitar POP para todos los mensajes que se reciban a partir de ahora". Si no lo haces, no podrás acceder desde JavaMail a tus mensajes.

  • Servidor de correo al que conectarse pop.gmail.com

  • Puerto de conexión 995

  • Conexión SSL

  • Deshabilitar TLS

  • Usuario -la dirección de correo, usaré ejemplo@gmail.com- y password válidos de gmail.

Clases implicadas en la lectura de un correo

Para leer los correos necesitamos básicamente las siguientes clases de JavaMail:

  • Session, que representa de alguna forma la conexión con gmail.

  • Store y Folder, que representan el almacén del servidor con los ocrreos y la carpeta dentro de ese almacén donde el servidor guarda los correos que queremos leer.

  • Message, los mensajes que leeremos.

Establecer la Session

Para obtener la sesión con gmail necesitamos tener una instancia de la clase Session con la configuración adecuada. Esta instancia se obtiene llamando al método Session.getDefaultInstance(). El parámetro para este método es una clase java.util.Properties de java estándar.

Como mencionamos anteriormente, Properties es una clase java que nos permite guardar datos de tipo texto asignándoles un nombre. Sería algo parecido a esto

Properties p = new Properties();
p.setProperty("un nombre", "un valor");
p.setProperty("PI", "3.1416");

Para obtener una instancia correctamente configurada de Session, en la clase Properties que le pasemos deben estar fijadas determinadas parejas nombre-valor. Tienes una lista de todas las posibles propiedades que JavaMail tiene en cuenta en la API. Vamos a ver las concretas para la conexión con pop.gmail.com

Properties prop = new Properties();

// Deshabilitamos TLS
prop.setProperty("mail.pop3.starttls.enable", "false");

// Hay que usar SSL
prop.setProperty("mail.pop3.socketFactory.class","javax.net.ssl.SSLSocketFactory" );
prop.setProperty("mail.pop3.socketFactory.fallback", "false");

// Puerto 995 para conectarse.
prop.setProperty("mail.pop3.port","995");
prop.setProperty("mail.pop3.socketFactory.port", "995");

Con mail.pop3.starttls.enable a false deshabilitamos TLS.

Para usar SSL debemos decirle a JMail como obtener un socket SSL, para ellos fijamos mail.pop3.socketFactory.class al nombre de clase que nos proporciona java estándar para obtener sockets SSL, es decir, javax.net.ssl.SSLSocketFactory.

Lo de mail.pop3.socketFactory.fallback es opcional. Si no lo fijamos, si falla el socket SSL JavaMail intentará con un socket normal. Puesto que es inútil -gmail sólo admite SSL-, ponemos esta propiedad a false para indicarle a JavaMail que no lo intente con sockets normales.

Falta indicar el puerto 995 tanto para JavaMail como para la clase que crea sockets SSL, por ello fijamos con este valor dos propiedades distintas: mail.pop3.port y mail.pop3.socketFactory.port

Con todo esto inicializado, ya podemos obtener nuestra instancia de Session

Session sesion = Session.getInstance(prop);
sesion.setDebug(true);

Lo de setDebug(true) es sólo para obtener más información en la pantalla de lo que se está haciendo. Cuando nuestro programa funcione correctamente, podemos quitar esta línea.

Obtener el Store y el Folder de Inbox

Una vez que tenemos nuestro Session, tenemos que obtener la carpeta de correo entrante de nuestro servidor de correo. Para ello ponemos las siguientes líneas de código

Store store = sesion.getStore("pop3");
store.connect("pop.gmail.com","ejemplo@gmail.com","la password ");
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);

A partir de Session obtenemos el almacen de correos Store con getStore(), indicando el protocolo "pop3" con nuestro servidor de correo.

Con el Store establecemos la conexión con el servidor de correo, indicando nombre de host -pop.gmail.com-, usuario (la dirección de correo) y password. Para ello usamos el método connect().

Finalmente, al Store le pedimos la carpeta Inbox con getFolder("INBOX"). Este Folder hay que abrirlo, en principio para sólo lectura.

Obtener los mensajes

Antes de nada, que quede claro que según hayas puesto en gmail, puede que sólo obtengas los mensajes nuevos. Si vas siguiendo el ejemplo con código, envíate un mensaje a esa cuenta antes de ejecutar el programa, para asegurarte que tienes un mensaje nuevo sin leer. En mis pruebas no he podido bajarme correos que me he enviado desde mi mismo PC y con mi cliente de correo (Thunderbird), así que he tenido que entrar con el navagador en gmail y enviarme desde ahí correos a mí mismo.

Para obtener los mensajes, símplemente hay que llamar a getMessages() de la clase Folder. Esto nos devolverá un array de Message, con los mensajes nuevos.

Message [] mensajes = folder.getMessages();

Como primera medida sencilla y para ver algo, sacaremos por pantalla los campos From y Subject -asunto- del mensaje. El contenido del mensaje es más complejo y lo vemos en el siguiente apartado.

Los campos From y Subject se obtienen con los métodos getFrom() y getSubject().

El getFrom() nos devuelve un array de Address, así que debemos ir leyendolos de uno en uno. El código para escribir esta información de cada mensaje puede ser como el siguiente

for (int i=0;i

Ver el contenido del mensaje

Bueno, aquí comienza el lio. Un mensje puede ser muy tonto -un simple texto- o muy complicado -un texto en formato plano y html para que elijas cual quieres ver y con ficheros adjuntos variados.

Lo primero es ver de qué tipo es. La clase Message -en realidad la interface Part que esta clase implementa- tiene el método isMimeType() para poder identificar de qué tipo es el mensaje. La primera comprobación que podemos hacer es ver si es de tipo text o multipart. El primer caso nos indica que es un texto sencillo, el segundo que es un mensaje compuesto. Podríamos comprobar también si una image o cualquier otro tipo MIME que se nos ocurra, pero lo normal es que recibamos un text o un mutipart. El código sería así

for (int i=0;i// mensaje de texto simple
if (mensajes[i].isMimeType("multipart/*"))
// mensaje compuesto
}

Como ves, hemos usado comodines -el asterisco- para que nos valga cualquier tipo de texto -text/plain, text/html, etc- y cualquier tipo de multipart -multipart/alternative, multipart/parallel, etc-

Sacar el contenido de texto

Si el MIME type es text/*, podemos sacar su contenido. Obviamente deberíamos ver exactamente que tipo de texto -text/plain, text/html, text/rtf, etc- para presentarlo en condiciones, pero es mucho para este tutorial. Vamos a suponer que es text/plain y podemos sacarlo y visualizarlo tal cual.

El código es muy tonto

System.out.println(mensajes[i].getContent());

Si el mensaje es de tipo text, el método getContent() nos devolverá directamente el String con el texto del mensaje. Si es text/plain, se podrá escribir directamente en pantalla o donde queramos.

Para otros tipos, como text/html o text/rtf, necesitas algo más elaborado, como un JEditorPane, para mostrar el contenido correctamente.

Obtener las partes de un multiparte.

Si el MIME type del mensaje es multipart, debemos ir extrayendo cada una de las partes que componen el mensaje compuesto. Con cada una de ellas debemos hacer un tratamiento similar, es decir, ver si es algún tipo simple -text, image, etc- o si a su vez vuelve a estar compuesto -multipart- y repetir el proceso hasta obtener las partes simples.

Si el mensaje es de tipo multipart, el método getContent() nos devolverá una clase MultiPart. Esta clase tiene métodos para saber cuántos cachos componen el mensaje y obtener cada uno de ellos. El código par esto podría ser así

if (mensajes[i].isMimeType("multipart/*"))
{
// Obtenemos el contenido, que es de tipo MultiPart.
Multipart multi;
multi = (Multipart)mensajes[i].getContent();

// Extraemos cada una de las partes.
for (int j=0;j
// Volvemos a analizar cada parte de la MultiParte
if (unaParte.isMimeType (....))
...
}
}

Es decir, con getContent() del mensaje obtenemos un MultiPart.

Con getCount() de este MultiPart obtenemos de cuántas partes esta compuesto el mensaje -por ejemplo, podría ser un mensaje de texto con dos imágenes adjuntas, es decir, tres partes-.

Obtenemos cada parte con getBodyPart(). Cada una de estas partes hay que volver a analizarla.

Esto, claramente, nos invita a un método recursivo para analizar cada parte, de forma que si la parte es simple, se muestra el contenido y si es compuesta, se extraen las subpartes y se vuelve a llamar al mismo método. En el código de ejemplo del final está hecho así.

Obtener una imagen adjunta.

La idea ya debería estar clara. Vamos a ver como tratar algo que no sea text ni multipart. Como ejemplo, una imagen adjunta.

Para comprobar si una parte es una imagen, nuevamente usamos el método isMimeType().

if (unaParte.isMimeType("image/*"))
{
...
}

Si no es un text ni un multipart, lo más probable es que getContent() nos devuelva un InputStream del que podemos leer los bytes que componen esa parte. En nuestro caso, los bytes de la imagen. En cualquier caso, tenemos el método getInputStream() que seguro que nos lo devuelve como un InputStream.

A partir de este InputStream es fácil leer los bytes y guardarlos, por ejemplo, en un fichero de imagen con un FileOutputStream. Tal cual leemos bytes del InputStream, los vamos escribiendo en el FileOutputStream. El método getFileName(), para el caso de imagen, posiblemente nos devuelva el nombre del fichero que tenía la imagen cuando nos la enviaron, con lo que ya tenemos que nombre darle al fichero. Aquí tienes un trozo de código para guardar la imagen en un fichero (ojo, lo mete en el raíz de la unidad D:\, cámbialo si no te gusta).

if (unaParte.isMimeType("image/*"))
{
FileOutputStream fichero = new FileOutputStream("d:/"+unaParte.getFileName());
InputStream imagen =
bodyPart.getInputStream();
byte [] bytes = new byte[1000];
int leidos=0;
while ((leidos=imagen.read(bytes))>0)
{
fichero.write(bytes,0,leidos);
}
}

De todas formas, a mí me gusta más ver la foto, así que aquí va el código para mostrarla en un JFrame.

if (unaParte.isMimeType("image/*"))
{
JFrame v = new JFrame();
ImageIcon icono = new ImageIcon(ImageIO.read(
unaParte.getInputStream()));
JLabel l = new JLabel(icono);
v.getContentPane().add(l);
v.pack();
v.setVisible(true);
}

Como puedes ver, se comprueba si es de tipo image/*. En caso afirmativo, la clase ImageIO de java nos ayuda a construir una Image a partir de un InputStream y esta podemos meterla en un ImageIcon, que se puede meter a su vez dentro de un JLabel que podemos pintar en una ventana JFrame ... ¡¡uff!!

En RecibirMail.java tienes un programa completo capaz de leer los correos de gmail. Escribe en pantalla las partes de texto y salva en fichero en d:\ las imagenes, además de visualizarlas en un JFrame.

Ejemplo:


package tucuenta.ejemplos.mail;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;


public class RecibirMail
{
/**
* main de la clase.
* @param args Se ignoran
*/
public static void main(String[] args)
{
// Se obtiene la Session
Properties prop = new Properties();
prop.setProperty("mail.pop3.starttls.enable", "false");
prop.setProperty(
"mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
prop.setProperty("mail.pop3.socketFactory.fallback", "false");
prop.setProperty("mail.pop3.port", "995");
prop.setProperty("mail.pop3.socketFactory.port", "995");
Session sesion = Session.getInstance(prop);
// sesion.setDebug(true);

try
{
// Se obtiene el Store y el Folder, para poder leer el
// correo.
Store store = sesion.getStore("pop3");
store.connect(
"pop.gmail.com", "tucuenta@gmail.com", "la password");
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);

// Se obtienen los mensajes.
Message[] mensajes = folder.getMessages();

// Se escribe from y subject de cada mensaje
for (int i = 0; i < mensajes.length; i++)
{
System.out.println(
"From:" + mensajes[i].getFrom()[0].toString());
System.out.println("Subject:" + mensajes[i].getSubject());

// Se visualiza, si se sabe como, el contenido de cada mensaje
analizaParteDeMensaje(mensajes[i]);
}

folder.close(false);
store.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}

/**
* Metodo recursivo.
* Si la parte que se pasa es compuesta, se extrae cada una de las subpartes y
* el metodo se llama a si mismo con cada una de ellas.
* Si la parte es un text, se escribe en pantalla.
* Si la parte es una image, se guarda en un fichero y se visualiza en un JFrame.
* En cualquier otro caso, simplemente se escribe el tipo recibido, pero se
* ignora el mensaje.
*
* @param unaParte Parte del mensaje a analizar.
*/
private static void analizaParteDeMensaje(Part unaParte)
{
try
{
// Si es multipart, se analiza cada una de sus partes recursivamente.
if (unaParte.isMimeType("multipart/*"))
{
Multipart multi;
multi = (Multipart) unaParte.getContent();

for (int j = 0; j < multi.getCount(); j++)
{
analizaParteDeMensaje(multi.getBodyPart(j));
}
}
else
{
// Si es texto, se escribe el texto.
if (unaParte.isMimeType("text/*"))
{
System.out.println("Texto " + unaParte.getContentType());
System.out.println(unaParte.getContent());
System.out.println("---------------------------------");
}
else
{
// Si es imagen, se guarda en fichero y se visualiza en JFrame
if (unaParte.isMimeType("image/*"))
{
System.out.println(
"Imagen " + unaParte.getContentType());
System.out.println("Fichero=" + unaParte.getFileName());
System.out.println("---------------------------------");

salvaImagenEnFichero(unaParte);
visualizaImagenEnJFrame(unaParte);
}
else
{
// Si no es ninguna de las anteriores, se escribe en pantalla
// el tipo.
System.out.println(
"Recibido " + unaParte.getContentType());
System.out.println("---------------------------------");
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}

/**
* Presupone que unaParte es una foto adjunta a un correo.
* Recoge la imagen y la visualiza en un JFrame
*
* @param unaParte Parte de un correo correspondiente a una imagen.
*
* @throws IOException
* @throws MessagingException
*/
private static void visualizaImagenEnJFrame(Part unaParte)
throws IOException, MessagingException
{
JFrame v = new JFrame();
ImageIcon icono = new ImageIcon(
ImageIO.read(unaParte.getInputStream()));
JLabel l = new JLabel(icono);
v.getContentPane().add(l);
v.pack();
v.setVisible(true);
}

/**
* Supone que unaParte corresponde a una imagen de un fichero y que
* getFileName() esta relleno.
* Salva la imagen en d:\getFileName().
*
* @param unaParte Parte de un correo correspondiente a una imagen.
*
* @throws FileNotFoundException
* @throws MessagingException
* @throws IOException
*/
private static void salvaImagenEnFichero(Part unaParte)
throws FileNotFoundException, MessagingException, IOException
{
FileOutputStream fichero = new FileOutputStream(
"d:/" + unaParte.getFileName());
InputStream imagen = unaParte.getInputStream();
byte[] bytes = new byte[1000];
int leidos = 0;

while ((leidos = imagen.read(bytes)) > 0)
{
fichero.write(bytes, 0, leidos);
}
}
}

5.- Envío de un correo con datos adjuntos con JavaMail.

Habíamos visto que un correo compuesto tiene más o menos una estructura de árbol. Cada nodo del árbol tiene como datos una clase MultiPart. Las hojas del árbol son las que contienen la información del correo, es decir, el texto, la imagen, etc.

Vamos a ello.

Clases implicadas

Las clases que necesitamos para enviar un correo con adjuntos con JavaMail son

  • Session y Transport para la conexión con gmail y envio del mensaje.

  • MimeMessage, MimeMultiPart y MimeBodyPart Para construir el mensaje.

Obtención de Session

Como mencionamos en el envio de un correo sencillo, necesitamos obtener una instancia de Session y para ello necesitamos previamente rellenar una variable Properties.

Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.setProperty("mail.smtp.starttls.enable", "true");
props.setProperty("mail.smtp.port","587");
props.setProperty("mail.smtp.user", "
tucuenta@gmail.com");
props.setProperty("mail.smtp.auth", "true");

Session session = Session.getDefaultInstance(props, null);
session.setDebug(true);

Los detalles de estos valores que hemos rellenado puedes verlos en el enlace anterior.

Con esto ya tenemos instanciada la clase Session. Vamos ahora a construir el mensaje

Construir un correo de texto con un adjunto

Lo primero vamos a construir las dos partes del mensaje. El texto y la imagen. Para ello, instanciamos dos clases MimeBodyPart y las rellenamos con los datos.

Empezamos con la de texto, que es más sencilla

BodyPart texto = new MimeBodyPart();
texto.setText("Texto del mensaje");

Ya está. Al usar el método setText() sin parámetros, ya se está configurando todo para que sea un texto plano -text/plain en MIME type-.

El adjunto con la imagen también es sencillo. Supongamos que tenemos la imagen en un fichero D:\futbol.gif -por supuesto, de una extensión conocida por java-

También debemos crear un MimeBodyPart, pero esta vez llamamos al método setContent(). A este método hay que pasarle un DataHandler, que es una clase capaz de manejar los datos que vayan en esta parte. Para instanciar ese DataHandler debemos darle una fuente de datos. La fuente, puesto que tenemos la imagen en fichero, puede ser una clase FileDataSource, capaz de leer un fichero con datos y saber de qué tipo es (imagen, audio, etc). En resumen, el código sería este

BodyPart adjunto = new MimeBodyPart();
adjunto.setDataHandler(new DataHandler(new FileDataSource("d:/futbol.gif")));
adjunto.setFileName("futbol.gif");

La llamada a setFileName() es opcional. Haciéndola le daremos al receptor del correo posibilidad de saber el nombre del fichero de imagen. Si no lo ponemos, no pasa nada.

Juntar el texto y la imagen adjunta

Ahora debemos juntar estas dos partes en una única parte compuesta.

Para ello, instanciamos una clase MimeMultiPart y le añadimos ambos cachos. La clase MimeMultiPart no es más que una parte más de un correo, pero que está a su vez compuesta de otras partes -el texto y la imagen en nuestro caso-. Podemos ir añadiendo aquí todas las imagenes y otros ficheros que queramos.

MimeMultipart multiParte = new MimeMultipart();

multiParte.addBodyPart(texto);
multiParte.addBodyPart(adjunto);

Ya está. Ahora sólo nos falta el mensaje en sí, algo a lo que podamos dar un destinatario de correo, un asunto -subject-, etc.

Construir el mensaje de correo

El mensaje a construir es simplemente una instancia de MimeMessage. Al instanciarlo debemos pasarle el objeto Session que obtuvimos anteriormente. También debemos rellenar los campos de destinatario y demás. Y finalmente también debemos rellenar el contenido, metiendo nuestro MimeMultipart anterior.

Los detalles de los campos subject, to y from puedes verlos en el envío de un mensaje sencillo con JavaMail.

El código quedaría así

MimeMessage message = new MimeMessage(session);

// Se rellena el From
message.setFrom(new InternetAddress("yo@yo.com"));

// Se rellenan los destinatarios
message.addRecipient(Message.RecipientType.TO, new InternetAddress("tucuenta@gmail.com"));

// Se rellena el subject
message.setSubject("Hola");

// Se mete el texto y la foto adjunta.
message.setContent(multiParte);

Ya tenemos compuesto el total del correo. Ahora sólo queda enviarlo

Enviar el correo

Ya lo vimos en el ejemplo sencillo de envio de correo con JavaMail. Sólo tenemos que hacer lo siguiente.

Transport t = session.getTransport("smtp");
t.connect("
tucuenta@gmail.com","la password");
t.sendMessage(message,message.getAllRecipients());
t.close();

Simplemente obtenemos una instancia de Transport, que es la clase encargada del envio del correo.

Realizamos la conexión dando usuario -correo de gmail de la cuenta que estemos usando- y la clave.

Enviamos el mensaje con sendMessage(). Ojo, no uses el método send() a secas, porque ese no tiene en cuenta los parámetros de conexión.

Ejemplo completo:

package tucuenta.ejemplos.mail;

import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class EnviarMailComplejo
{
public static void main(String[] args)
{
try
{
// se obtiene el objeto Session. La configuración es para
// una cuenta de gmail.
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.setProperty("mail.smtp.starttls.enable", "true");
props.setProperty("mail.smtp.port", "587");
props.setProperty("mail.smtp.user", "tucuenta@gmail.com");
props.setProperty("mail.smtp.auth", "true");

Session session = Session.getDefaultInstance(props, null);
// session.setDebug(true);

// Se compone la parte del texto
BodyPart texto = new MimeBodyPart();
texto.setText("Texto del mensaje");

// Se compone el adjunto con la imagen
BodyPart adjunto = new MimeBodyPart();
adjunto.setDataHandler(
new DataHandler(new FileDataSource("d:/futbol.gif")));
adjunto.setFileName("futbol.gif");

// Una MultiParte para agrupar texto e imagen.
MimeMultipart multiParte = new MimeMultipart();
multiParte.addBodyPart(texto);
multiParte.addBodyPart(adjunto);

// Se compone el correo, dando to, from, subject y el
// contenido.
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("yo@yo.com"));
message.addRecipient(
Message.RecipientType.TO,
new InternetAddress("tucuentag@gmail.com"));
message.setSubject("Hola");
message.setContent(multiParte);

// Se envia el correo.
Transport t = session.getTransport("smtp");
t.connect("tucuenta@gmail.com", "la clave");
t.sendMessage(message, message.getAllRecipients());
t.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}



Enviar SMS desde una aplicación JAVA


En esta entrada os mostraremos cómo enviar sms desde una aplicación Java. Seguro que esta funcionalidad os la ha pedido algún cliente que quería integrar directamente en vuestra aplicación la posibilidad de enviar un sms en alguna situación como comunicarse con sus propios clientes, enviar una alerta en determinadas ocasiones, etc…

Lo primero es encontrar un proveedor que permita el envío de sms mediante una conexión a su servidor. Puede que existan aún aquellas páginas donde era gratuito enviar un sms. Sin embargo la fiabilidad de entrega de estos proveedores, unido a que sólo permiten enviar a través de una página web y no desde un programa java y que suelen estár asociados al envío de publicidad no hacen de esta solución una solución aceptable.

Un proveedor de sms sirve de intermediario entre nuestra aplicación Java y los operadores de telefonía móvil. La misión del programa Java será por tanto conectarse de algún modo al proveedor elegido (HTTP, SMTP…) y pasarle los datos del sms en algún formato (con los propios parámetros de HTTP, con un xml…).

Después de buscar entre varios proveedores, nos hemos quedado con la pasarela de envío de sms de Altiria. El envío de sms se realiza con este proveedor mediante una petición POST a su servidor con los datos del sms que se quiere enviar como parámetros de la propia petición, siendo los más importantes el contenido del sms y los destinatarios. Se puede encontrar el documento de especificaciones de la conexión también en su web (Documento de especificaciones).

Queremos resaltar que el para que el ejemplo que ponemos a continuación funcione y envíe un sms, es necesario ponerse en contacto con Altiria y contratar un bono de envío de sms que permita la conexión a su pasarela de envío. El ejemplo sirve para ilustrar lo fácil que sería el envío del sms una vez contratado el bono.

Ya tenemos el proveedor y el mecanismo de envío (HTTP). Ya sólo queda implementar esta conexión HTTP en nuestro programa Java. Para ello necesitamos un cliente HTTP para realizar la conexión. Hemos elegido la librería HTTP de Jakarta, (HttpClient) que debe estar presente en el classpath de nuestra aplicación. El siguiente código realiza la conexión enviando los parámetros del sms.

Ejemplo:

//Se inicia el objeto HTTP

HttpClient client = new HttpClient();

client.setStrictMode(true);

//Se fija el tiempo máximo de espera de la respuesta del servidor

client.setTimeout(60000);

//Se fija el tiempo máximo de espera para conectar con el servidor

client.setConnectionTimeout(5000);

PostMethod post = null;

//Se fija la URL sobre la que enviar la petición POST

//Como ejemplo se supone www.pasarela_push_altiria.com/post/sms

post = new PostMethod("http://www.pasarela_push_altiria.com/post/sms");

//Se fija la codificación de caracteres en la cabecera de la petición

post.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");

//Se crea la lista de parámetros a enviar en la petición POST

NameValuePair[] parametersList = new NameValuePair[3];

parametersList[0] = new NameValuePair("dest", "34600111222");

parametersList[1] = new NameValuePair("dest", "34600111333");

parametersList[2] = new NameValuePair("msg", "Mensaje de prueba");

//Se rellena el cuerpo de la petición POST con los parámetros

post.setRequestBody(parametersList);

int httpstatus = 0;

String response = null;

try {

//Se envía la petición

httpstatus = client.executeMethod(post);

//Se consigue la respuesta

response = post.getResponseBodyAsString();

}

catch (Exception e) {

//Habrá que prever la captura de excepciones

return;

}

finally {

//En cualquier caso se cierra la conexión

post.releaseConnection();

}

//Habrá que prever posibles errores en la respuesta del servidor

if (httpStatus!=200){

return;

}

else {

//Se procesa la respuesta capturada en la cadena ‘‘response’’



Este código se traduce en el envío de un sms con el texto “Mensaje de Prueba” a los móviles 34600111222 y 34600111333.