Calendar

June 2009
S M T W T F S
« May   Jul »
 123456
78910111213
14151617181920
21222324252627
282930  

Tag Cloud

Categories

Archives

Recent Posts

Recent Comments


« Adobe Browserlab – How Cool is this! | Main | Online Office Wars Continue Ajax vs Flash »

Open an AIR application from a 2nd AIR application

By Rich Tretola | June 8, 2009
6,075 views

In my 360Flex Indianapolis presentation, I demonstrated how to launch an Adobe AIR application from within a second AIR application. I have extracted the code used and will demonstrate how to do this within this post. There are a few ways to do this.

You can install my LauncherSample application to test the code to follow.

Download LauncherSample

No matter which method you choose, the one thing that is required by both is that the application you are attempting to launch has the allowBrowserInvocation property within the AIR configuration file set to true and the application installed on your system.

1
2
3
<!-- Whether the application can be launched when the user clicks a link in a web browser.
    Optional. Default false. -->
<allowBrowserInvocation>true</allowBrowserInvocation>

You must also know the application’s id and publisher’s id. For example within my LauncherSample, the application id defined in the AIR configuration file is:

1
2
<!-- The application identifier string, unique to this application. Required. -->
<id>LauncherSample</id>

To find the publisher id, you can drill into the installation folder for the application and find the publisherid file within Contents/Resources/META-INF/AIR. If you find this file within the LauncherSample, you will see that my publisherid is 130A080AFCC69239D6F9896EEBED2327BC93ED43.1

Now that we have the 2 required items we can get started. As I previously mentioned, there are a few ways to launch an AIR application from an AIR application.

The first uses an undocumented class adobe.utils.ProductManager. To launch the application using this method you can simply use the code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
                        layout="absolute" width="300" height="100">
    <mx:Script>
        <![CDATA[
            import adobe.utils.ProductManager;
            private var pm:ProductManager;

            private var appID:String = "LauncherSample";
            private var pubID:String = "130A080AFCC69239D6F9896EEBED2327BC93ED43.1";

            private function launchApp():void{
                var mgr:ProductManager = new ProductManager("airappinstaller");
                mgr.launch("-launch " + appID + " " + pubID);
            }
        ]]>
    </mx:Script>
    <mx:Button horizontalCenter="0" verticalCenter="0"
               label="Launch App" click="launchApp()"/>
</mx:WindowedApplication>

This works great, however there is one problem with this method and that is that if the AIR application does not exist on the system, nothing will ever happen and you will not get any feedback alerting you of a problem.

So, we have one other option. We can load in the same swf file that is used by the badge installer and now we will not only be able to launch an AIR application, but we can also test for the existence of the application on the machine.

Upon creationComplete of the application, the code below loads the air.swf file from http://airdownload.adobe.com/air/browserapi/air.swf. Once the air.swf is loaded, the getApplicationVersion method is called against the air.swf and the appId, pubId, and call back method versionDetectCallback are passed in. Within the versionDetectCallback method the version is passed in. If the version is null, we know that the application is not installed on the machine and we offer a download button. If the version is not null, we instead will offer a launch button.

If the user clicks on the install button, we can call the installApplication method on the air.swf passing in the application’s URL and required AIR version.

If the user clicks on the launch button, we can call the launchApplication method on the air.swf passing in the application’s appId and pubId and the application will be launched.

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
                        creationComplete="loadAIR()"
                        width="300" height="100"
                        layout="absolute">
    <mx:Script>
        <![CDATA[
            private var _air:Object;
            private var _loader:Loader;

            private var appID:String = "LauncherSample";
            private var pubID:String = "130A080AFCC69239D6F9896EEBED2327BC93ED43.1";
            private var appURL:String = "http://blog.everythingflex.com/wp-content/uploads/2009/06/launchersample.air";
            private var runtimeVersion:String = "1.5";

            // load in the air.swf file
            private function loadAIR():void{
                _loader = new Loader();
                var loaderContext:LoaderContext = new LoaderContext();
                loaderContext.applicationDomain = ApplicationDomain.currentDomain;
                _loader.contentLoaderInfo.addEventListener(Event.INIT, onInit);
                _loader.load(new URLRequest("http://airdownload.adobe.com/air/browserapi/air.swf"), loaderContext);

            }
            // handle init of the _loader
            private function onInit(e:Event):void {
                _air = e.target.content;
                // test to see if appplication is installed
                _air.getApplicationVersion(appID, pubID, versionDetectCallback);
            }

            // handle callback from getApplicationVersion
            private function versionDetectCallback(version:String):void {
                // if version found show launch button, if not show install button
                if (version == null) {
                    install.visible = true;
                    launch.visible = false;
                } else {
                    install.visible = false;
                    launch.visible = true;
                }
            }

            // install application from remote server
            private function installApp():void{
                _air.installApplication(appURL, runtimeVersion);
            }

            // launch the application
            private function launchApp():void{
                _air.launchApplication(appID, pubID);
            }
        ]]>
    </mx:Script>
    <mx:Button click="installApp()" label="Install Application"
               horizontalCenter="0" verticalCenter="0" width="150"
               height="22" id="install" visible="false"/>
    <mx:Button click="launchApp()" label="Launch Application"
               horizontalCenter="0" verticalCenter="0" width="150"
               height="22" id="launch" visible="false"/>
</mx:WindowedApplication>

To review, if you know the application you wish to launch is installed, you can use the ProductManager class to launch it, if not, you really don;t have a choice but to load in an external swf. All works well with the second method of launching an AIR application expect for the obvious limitation of the air.swf needing to be downloaded from Adobe. Unfortunately, short of altering the users host file, there is no way around this as if the air.swf is not downloaded from the airdownload.adobe.com domain, it will not work.

Hopefully, AIR 2.0 will be less restrictive and allow for the launching of applications natively.

Topics: Adobe AIR, Flex | 31 Comments »

31 Responses to “Open an AIR application from a 2nd AIR application”

  1. TJ Downes Says:
    June 8th, 2009 at 8:23 am

    Hey Rich, great post!

    One minor correction, I think the last word should be “natively”, as one would hope that people are not launching apps naively :)

    Reply to this comment

    Rich Tretola Reply:

    Thanks. I fixed it.

    Reply to this comment

  2. Twitted by ashumittal Says:
    June 8th, 2009 at 8:54 am

    [...] This post was Twitted by ashumittal – Real-url.org [...]

  3. Launch an AIR app from within another AIR app « Devgirl’s Weblog Says:
    June 8th, 2009 at 9:16 am

    [...] myself wondering how this would be done exactly, and noticed that Rich Tretola just did a great blog post this morning on two ways to do it, including source code. He presented the solutions at 360 | Flex [...]

  4. Benz Says:
    June 9th, 2009 at 3:52 am

    Do you know if there is a way to pass parameters to the application being launched? So you can catch them maybe in the Invoke Event?
    Thanks
    Benz

    Reply to this comment

    Rich Tretola Reply:

    I have not tried this but you should be able to pass arguments. Check out David’s post on this topic for some additional info:
    http://www.davidtucker.net/2008/01/10/air-tip-5-passing-arguments-to-an-application-on-install/

    Reply to this comment

  5. Benz Says:
    June 9th, 2009 at 4:08 am

    My previous question is for the ProductManager way of doing it… Thanks
    Benz

    Reply to this comment

  6. JonZ Says:
    August 5th, 2009 at 5:43 am

    Hey,

    does this still work in the AIR 1.5.2 release?
    Can’t get it to work, installing the application simply doesn’t start.
    The launching of an app that’s already installed (with ProductManager) does work.
    Thanks!

    Reply to this comment

    Rich Tretola Reply:

    Seems fine when I test it. Anyone else have this same issue?

    Reply to this comment

  7. JonZ Says:
    August 6th, 2009 at 4:48 am

    Ah think I found it :)

    Using the launch or install methods from that air.swf file need user interaction, if I put those on a button click, they work :)
    What I did before was checking the version, than call the installApp() or launchApp() methods.

    Reply to this comment

  8. Rusiru Boralugoda Says:
    August 11th, 2009 at 3:12 am

    Thanks for a great post Rich. But I have a one concern. This works fine if I want to launch a one AIR application by another.

    But what if I want to run a one mxml component as another application from the main mxml application while the main mxml is running.

    Say, I have an admin panel and a projector screen. I want to project some of the details in the projector screen while admin panel is running. So here there are two applications as the admin panel and the projector.

    I can’t use your method here because the projector it self has different states that change.

    Reply to this comment

    Rich Tretola Reply:

    Sorry, I am not following your example description.

    Reply to this comment

    Rusiru Boralugoda Reply:

    Well, say there is a flex project that runs as a desktop application (AIR app.) called admin console. I’ve add an mxml component to it (projector.mxml)

    In this projecotr.mxml i want to carry out separate functionalities (has basically 4 states that display different data that continuously changes, that handles by repeatedly polling to a db)

    First I’ve created the projector as 4 different AIR apps(depending on what to display). Now what I wanted to do is to include them in to the admin app so that admin console can invoke the needed projector screen as a separate AIR app while admin console is running separately.

    The requirement is to project the data displayed in the projector app in a real projector screen to a large crowd while the person controlling the admin console to continue on his work.

    Thanks…

    Reply to this comment

  9. JonZ Says:
    August 11th, 2009 at 8:25 am

    @Rusiru Boralugoda:

    Maybe you can use this util little util klass I made for a simular problem:
    http://code.google.com/p/airscreenmanageras3/

    You don’t have to make another application to do that.
    Just make a new NativeWindow, add you mxml to the NativeWindow’s stage and use the Util class to open you new window on another screen.

    Reply to this comment

    Rusiru Boralugoda Reply:

    Thanks a lot Jonz and Rich… :)

    Well, It was actually much simpler than I thought. All I had to do is changing the root tag of the projector.mxml from `Canvas` to `Window` and open it as a new window at the admin console … :)

    var projView:Projector = new Projector ();
    projView.open();

    Thanks again guys…

    Reply to this comment

  10. arten Says:
    August 26th, 2009 at 7:40 am

    Hi,

    I’ve tried your method above to make an app launcher but it doesn’t work. I have set the allowbrowserinvocation to true and this is my code (i use destroy twitter as an example here)

    var myLauncher:ProductManager = new ProductManager(”launcher”);

    var appID:String = “app.destroytwitter”;
    var pubID:String =”23CA2F9B070E2FB8C4472F982F88B1A471F11AE2.1″;

    myLauncher.launch(”-launch ” + appID + ” ” + pubID);

    Reply to this comment

    JonZ Reply:

    Arten,

    The allowbrowserinvocation property has to be set on the application you want to start, not the other way around.
    And I don’t thing DestroyTwitter has it turned on :)

    Reply to this comment

  11. Twitter Trackbacks for Open an AIR application from a 2nd AIR application | EverythingFlex: Flex & AIR [everythingflex.com] on Topsy.com Says:
    August 30th, 2009 at 7:49 am

    [...] Open an AIR application from a 2nd AIR application | EverythingFlex: Flex & AIR blog.everythingflex.com/2009/06/08/open-an-air-application-from-a-2nd-air-application – view page – cached 360Flex acrobat actionscript air android apple as3 books conference contest cookbook FileReference flash flash builder flash catalyst Flash Player flashplayer flashplayer10 Flex flex4 flexbuilder flickr fotobooth Frameworks google gumbo ImageDropR indexing InsideRIA iphone java localconnection max merapi microsoft mobile pixel bender riatrax SilverLight sqlite swf Thermo update framework updatemanager URLTestr — From the page [...]

  12. bitsofinfo Says:
    September 30th, 2009 at 1:12 pm

    Can anyone tell me what SWC contains the ProductMangager class?? I cannot import adobe.utils.ProductManager

    Reply to this comment

    Rich Tretola Reply:

    It is part of the framework for AIR applications only.

    Reply to this comment

  13. Nikola Minovski Says:
    October 5th, 2009 at 3:28 am

    Hello,

    I’m working on an air application (launcher) for launching other already installed air applications on my PC.
    Lets say my launcher is consisting of one launch button. When you launch an air application (click on the launch button), the launcher will go to the system tray (dock) and in the center of the dektop is active the new launched air application (with target appID and pubID).
    If I close the launched application, I want the launcher to be visible again (undock).
    Is it possible to detect if an external air application (instead of launcher) is active or inactive? How to do that?

    Thanks in advance,
    Nikola

    Reply to this comment

    Rich Tretola Reply:

    I waited to respond to this comment. AIR 2 will allow you to open applications without all of the workarounds I mentioned in this article.

    Reply to this comment

    Nikola Minovski Reply:

    Hi Rich! I believe also in v2.0. However I’ve tried to establish a connection using localconnection. If you have only one external application, everything works great, but I’ve faced another problem.

    I can’t manage the case if you launch more than one external air application. Because in this case I’m using timer event, maybe the problem is here, but I really don’t know!

    How to solve this? If you are interested in finding a solution, I’ll send you my connection code for the launcher and for first and second external air application.

    Please let me know!

    Another problem regarding the launcher which I want to solve also (I really don’t know if it is possible) is:

    If the launcher is consisting of several buttons (each for launching the corresponding external air application (more than one)), I want within the launcher to check if these external air applications are installed on the PC. If the application is installed, the corresponding launch button in the launcher will be enabled, otherwise will be disabled. This case also work good with only one button in the launcher (only one external application).

    I’ve tried with two (more) buttons and in Flex output received the following error:

    [SWF] LauncherSample.swf – 1,544,229 bytes after decompression
    [SWF] /air/browserapi/air.swf – 4,530 bytes after decompression
    Error: Operation already in progress.
    at AIR/getApplicationVersion()
    at LauncherSample/onInit()[C:\Documents and Settings\Nikola Minovski\My Documents\Flex Builder 3\LauncherSample\src\LauncherSample.mxml:28]

    How to fix this problem? Is it possible?

    Thanks in advance,
    Nikola

    Reply to this comment

    Rich Tretola Reply:

    LocalConnection’s must be unique, so you can’t use more than one with the same name.

  14. Harry Says:
    October 26th, 2009 at 4:57 pm

    Great article, thanks!

    I’m trying to debug some problems I am having with ProductManager; do you know if there is anywhere I can see the source code for it, or at least a list of public methods?

    Reply to this comment

    Rich Tretola Reply:

    ProductManager is an undocumented class.

    Reply to this comment

  15. Jonathan Says:
    January 12th, 2010 at 8:32 pm

    Hey Rich,

    Have you ever managed to pass extra arguments using the ProductManager class… ?

    e.x. mgr.launch(”-launch ” + appID + ” ” + pubID + ” ” + “arg0″ + ” ” + “arg1″);

    And successfully parse these arguments in your BrowserInvoke handler in the app that gets launched?

    I am trying, but cant get any extra arguments through… the app launch fails if i pass anything but the appId and pubId in the way i’ve shown above

    Reply to this comment

  16. Ed Hardy Says:
    January 20th, 2010 at 9:41 pm

    Exquisite design, superior material, exquisite craft. Ed Hardy Close to her heart, the most perfect expression of your love.

    Reply to this comment

  17. madhu panisetty Says:
    January 22nd, 2010 at 9:47 am

    Thank you, working fine. But what to do if user clicks cancel. Can we detect it.

    Reply to this comment

  18. madhu panisetty Says:
    January 22nd, 2010 at 9:48 am

    @Jonathan

    you have to use — to pass arguments

    e.x. mgr.launch(”-launch ” + appID + ” ” + pubID + ” — ” + “arg0″ + ” ” + “arg1″);

    Reply to this comment

  19. madhu panisetty Says:
    January 22nd, 2010 at 9:51 am

    @Jonathan

    you have to use – - (2 hypens side by side) to pass arguments

    @Rich Tretola
    For some reason when I type – - without space in comments it is being converted to single hypen.

    Reply to this comment

Comments