« 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.
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 »








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:
June 8th, 2009 at 8:57 am
Thanks. I fixed it.
Reply to this comment
June 8th, 2009 at 8:54 am
[...] This post was Twitted by ashumittal – Real-url.org [...]
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 [...]
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:
June 10th, 2009 at 4:58 am
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
June 9th, 2009 at 4:08 am
My previous question is for the ProductManager way of doing it… Thanks
Benz
Reply to this comment
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:
August 5th, 2009 at 1:25 pm
Seems fine when I test it. Anyone else have this same issue?
Reply to this comment
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
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:
August 11th, 2009 at 7:05 am
Sorry, I am not following your example description.
Reply to this comment
Rusiru Boralugoda Reply:
August 11th, 2009 at 7:54 am
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
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:
August 12th, 2009 at 1:21 am
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
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:
August 26th, 2009 at 4:48 pm
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
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 [...]
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:
September 30th, 2009 at 2:05 pm
It is part of the framework for AIR applications only.
Reply to this comment
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:
October 5th, 2009 at 8:13 pm
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:
October 6th, 2009 at 2:18 am
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:
October 6th, 2009 at 8:44 am
LocalConnection’s must be unique, so you can’t use more than one with the same name.
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:
October 26th, 2009 at 9:03 pm
ProductManager is an undocumented class.
Reply to this comment
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
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
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
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
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