14.08.08

Minimizar una aplicacion AIR al area de notificacion (systemtray) de windows

Posted in air at 13:54

Una de las funcionalidades que nos ofrece Adobe a la hora de desarrollar una aplicación AIR, que nos puede resultar muy útil, es la de poder añadir un icono al área de notificación de windows (o system tray) y añadirle un menú contextual. Esto se consigue añadiendo el siguiente código cuando inicializamos la aplicación:

Primero habrá que cargar la imagen que queremos que sea nuestro icono en el área de notificación. Para ello utilizaremos la clase Loader. Además monitorizaremos el evento que queremos que sea el que haga aparecer el icono en el área (En el ejemplo se captura el evento de minimizar la ventana). Para ello escribiremos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Bindable] 
private var iconoMinimizado:BitmapData; 
 
private function creationComplete():void{ 
    //Cargamos el icono de la bandeja de notificacion y monitorizamos el evento de minimizar 
    var loader:Loader = new Loader(); 
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, inicializarSystray); 
    loader.load(new URLRequest("assets/icon.png")); 
    this.addEventListener(NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE, stateChanging); 
} 
 
private function stateChanging(event:NativeWindowDisplayStateEvent):void{ 
    event.preventDefault(); 
    if(event.afterDisplayState == NativeWindowDisplayState.MINIMIZED){ 
        //Ocultamos la aplicacion y mostramos el icono del systray 
        stage.nativeWindow.visible = false 
        NativeApplication.nativeApplication.icon.bitmaps = [iconoMinimizado]; 
    } 
}

En la función que hemos indicado que queremos que sea la que se ejecute cuando se cargue la imagen (inicializarSystray), inicializaremos el menú del icono, el evento click sobre él (en nuestro caso será para restaurar la aplicación) y el tooltip que se mostrará.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
private function inicializarSystray(event:Event):void { 
    iconoMinimizado = event.target.content.bitmapData; 
    if(NativeApplication.supportsSystemTrayIcon){ 
        SystemTrayIcon(NativeApplication.nativeApplication.icon).tooltip = "Ejemplo de Systray"; 
        SystemTrayIcon(NativeApplication.nativeApplication.icon).addEventListener(MouseEvent.CLICK, restaurarAplicacion); 
 
        //Creamos su menu y lo añadimos 
        var menu:NativeMenu = new NativeMenu(); 
        var restaurarNativeMenuItem:NativeMenuItem = new NativeMenuItem("Restaurar"); 
        var maximizarNativeMenuItem:NativeMenuItem = new NativeMenuItem("Maximizar"); 
        var salirNativeMenuItem:NativeMenuItem = new NativeMenuItem("Salir"); 
 
        //Manejador de cada uno de los items del menu 
        restaurarNativeMenuItem.addEventListener(Event.SELECT, restaurarAplicacion); 
        maximizarNativeMenuItem.addEventListener(Event.SELECT, maximizarAplicacion); 
        salirNativeMenuItem.addEventListener(Event.SELECT, cerrarAplicacion); 
 
        //Añadimos los menuitems al menu, y el menu al icono 
        menu.addItem(restaurarNativeMenuItem); 
        menu.addItem(maximizarNativeMenuItem); 
        menu.addItem(new NativeMenuItem("",true)); //Esto es un separador 
        menu.addItem(salirNativeMenuItem); 
        SystemTrayIcon(NativeApplication.nativeApplication.icon).menu = menu; 
    } 
} 
 
private function restaurarAplicacion(event:Event):void { 
    //Ponemos la aplicacion visible y la maximizamos 
    stage.nativeWindow.visible = true; 
    stage.nativeWindow.restore(); 
 
    //Eliminamos el icono del systray 
    NativeApplication.nativeApplication.icon.bitmaps = []; 
} 
 
private function maximizarAplicacion(evt:Event):void { 
    //Ponemos la aplicacion visible y la maximizamos 
    stage.nativeWindow.visible = true; 
    stage.nativeWindow.maximize(); 
 
    //Eliminamos el icono del systray 
    NativeApplication.nativeApplication.icon.bitmaps = []; 
} 
 
private function cerrarAplicacion(event:Event):void{ 
    this.close(); 
}

Con este código, cada vez que minimicemos la aplicación, en lugar de estar en la parte inferior, nos aparecerá un icono en el área de notificación y dándole un click normal, restauraremos la aplicación, y dándole un click con el botón derecho, nos aparecerá un menú de restaurar, maximizar o cerrar.

Para más comodidad os podéis descargar el proyecto AIR con el código fuente para verlo con más calma :). Espero que sirva de ayuda. Saludos!!

04.08.08

Llamar a objetos remotos en cluster desde una aplicación flex

Posted in flex at 9:29

Durante esta última semana en el trabajo, a petición de los de sistemas, nos hemos visto en la necesidad de poner todas las aplicaciones para que se puedan ejecutar en cluster. Como nuestros servidores son Java, con poner la etiqueta <distributable /> en el fichero web.xml, era suficiente. Una vez desplegadas las nuevas aplicaciones con dicha etiqueta, nos ponemos a probarlas y vemos que la parte web normal (struts2, etc.) funciona correctamente, pero a la hora de ejecutar una aplicación flex y llamar a un objeto remoto, este no se ejecuta bien, devolviéndonos una excepción enorme.

Tras dos días de plena investigación, encontré mucha documentación sobre BlazeDS acerca de unos tags <cluster>, unos ficheros jgroups-tcp.xml y jgroups-udp.xml, etc., etc. Tras probar todo esto, de todas las formas posibles, el error seguía manteniéndose y no había forma de hacer una llamada remota. Finalmente haciendo pruebas ya a la desesperada, probamos a marcar las clases Java que son llamadas como objeto remoto como Serializables.

Para nuestra sorpresa y alegría, con esto ya se podían hacer llamadas remotas con la aplicación en el servidor ejecutándose en cluster, así que si alguna vez os veis en la necesidad de marcar una aplicación como <distributable />, para que las llamadas funcionen sólo tenéis que marcar los RO como Serializables y todo funcionará con total normalidad.

¡Saludos! (PD: Creo que es el post más chorras que he escrito, pero os estoy ahorrando horas y horas de pruebas :D)