Tag Archives: Flex

All AIR Applications Are Single-Instance

This is not an option: if one tries to launch an AIR application twice, the first instance remains and no other instances start. The first application, however, does get notification and the command-line arguments of the subsequent application executions. It’s a subtle way of communicating with a running AIR application.

If an application has to handle multiple instanciation (like a registered file reader), it has to be able to present multiple instances of some part of its user interface (or be willing to replace the current data at any time). This hearkens back to the days of Multi-Document Interface (MDI) applications. One can encapsulate the main UI as a component, and the application can create one for each “instance” the application needs to present.

Multiple Invocations of an AIR ApplicationThe NativeWindow.invoke Event Fires On Every Application Launch

The application will get an event every time the OS launches an instance of the application. It gets an event on startup, and it gets one each time the OS executes the AIR application file; subsequent executions do not start additional  instances. These events contains the command-line parameters specific to that invocation.

The Invoke event fits into the startup cycle here:

  1. FlexEvent.ADD for the application object
  2. FlexEvent.PREINITIALIZE
  3. Event.ADDED for the descendents of the application object
    (These events happen sporadically intermixed with the following events)
  4. FlexEvent.INITIALIZE
  5. FlexEvent.CREATION_COMPLETE
  6. Event.ADDED_TO_STAGE
  7. FlexEvent.APPLICATION_COMPLETE
  8. InvokeEvent.INVOKE
  9. Event.ACTIVATE

Command-line Parameters in AIR Applications

First, the simple behavior:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx"
    invoke="onInvoke(event)">
    <fx:Script>
        <![CDATA[
            private function onInvoke(event : InvokeEvent) : void
            {
                logText.text += "invoke: event.arguments = " + 
                    event.arguments.toString();

                if (event.currentDirectory != null) {
                    logText.text += "; event.currentDirectory = " + 
                        event.currentDirectory.nativePath;
                }
                else
                    logText.text += "; event.currentDirectory = null";


                if (event.reason != null)
                    logText.text += "; event.reason = " + event.reason;
                else
                    logText.text += "; event.reason =  null";
            }
        ]]>
    </fx:Script>

    <s:TextArea id="logText" left="10" right="10" top="105" bottom="10" />
</s:WindowedApplication>

 

Things My Event Told Me

  • InvokeEvent.arguments is an array (never null) of strings. See your operating system for the rules about special characters and quoting.
  • InvokeEvent.currentDirectory is a File instance set to the directory of the executable. Note that running from the IDE will point to the FlashBuilder.exe directory; running from a shortcut/alias will indicate the location of the shortcut, not the .air file.
  • InvokeEvent.reason is either “standard” or “login” if the  OS starts it automatically (see InvokeEventReason for constants)

Things My Event Never Told Me

  • The event does not indicate if this event is part of the application startup (i.e. the first event) or a subsequent invocation. Use a global counter.
  • The event does not indicate if this event is because the OS registered this application for a file type and the user “opened” a file of that type. The sole argument is the complete (native) path including file name, but shortcuts and the command-line can start the application can have a single argument that is a file path as well.