Using AIR 1.5.1 InovkeReason for friendlier applications

I recently discovered a new feature of AIR 1.5.1 that makes AIR applications more consumer friendly in certain situations. When you have your application set to start on user login using “NativeApplication.nativeApplication.startAtLogin = true”, you may want the application to start as a background process rather than show the entire application at login. In AIR 1.5.1 there is a new property of the InvokeEvent called “reason” that will report if the application was started at login or was started when the users invokes the application by launching the application.

By capturing this event and testing for InovokeReason.LOGIN, you can keep your application invisible and only show the windows docked in the system tray. If a users starts the application it will be InvokeReason.STANDARD and you can then show the application as normal. I find it annoying to have a ton of windows popping up on my screen when I restart my computer.

I usually set up an InvokeEvent when a users clicks on the system tray icon to activate the application and bring it to the forefront. I initially set WindowsApplicatoin visible=”false” so the application is invisible on start. If the the InvokeEventReason is “LOGIN”, I keep the application invisible, in other cases I activate the application and bring it to the forefront.

It should be noted that the InvokeEvent fires on application start up as well as from running the the application from the IDE (so you can’t test it fully unless you install the application and login again). Also, because of timing of events at start up, the application is invisible even when you set it to active, so it will blink if the InvokeEventReason is STANDARD. To avoid this behavior, I use the “windowComplete” event of the WindowedApplication to add the InvokeEvent listeners. So the code might look something like the following:


<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"  windowComplete="onAppInit()"  visible="false"  >

<mx:Script>
<![CDATA[

private function onAppInit():void
{
if (NativeApplication.supportsSystemTrayIcon) { // windows
setSystemTrayProperties();
} else if(NativeApplication.supportsDockIcon) { // mac
setDockProperties();
}
}

// add click event to the system tray
private function setSystemTrayProperties():void
{
var sysTray:SystemTrayIcon = NativeApplication.nativeApplication.icon as SystemTrayIcon;
sysTray.addEventListener(MouseEvent.CLICK, onIconClick, false, 0, true);

NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onIconClick, false, 0, true);
}

// add click event to the system tray
private function setDockProperties():void
{
NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onIconClick, false, 0, true);
}

private function onIconClick(event:InvokeEvent):void
{
trace("INVOKE REASON: " + event.reason);
if(event.reason != InvokeEventReason.LOGIN) {
if (NativeApplication.supportsSystemTrayIcon) {
stage.nativeWindow.visible = true;  // win
} else {
stage.nativeWindow.activate();  // mac
}
stage.nativeWindow.orderToFront();
{
}
]]>
</mx:Script>

– Mister

6 Comments

  1. Hi,

    Thanks for your interesting article.

    I’m trying to incorporate the same thing in my code but my application always has an InvokeEvent.reason of “standard”, including on login in Windows XP.

    Have you ever had any such issues?

    Thanks,

    Martyn

    1. Are you aware that there is a feature of Flex applications that you can actually right-click to view source? You should be familiar with this option as its used in many code examples.

Comments are closed.