Tutorial: Command Line Parameters in an AIR Application

In this tutorial you will learn how to pass command line arguments to your Adobe AIR applications and how to retrieve those values from within your program. In order to demonstrate this, I'll be sharing a small program I wrote recently to assist in screencasting. The program simply displays a webcam feed in a window that gets its size via command line arguments that are passed in when the program starts. This allows for a simple picture-in-picture effect, and thus, I've named the program PiP. Let's get started.

The original program was created with FlashDevelop, but for simplicity's sake, we'll use the Flash IDE here. Open up Flash and create a new AIR document. It doesn't really matter, but go ahead and set the stage size to 320x240 and set the FPS to 30. This will be our default window size and frame rate. Next open up the actions panel (f9 on Windows) and let's create a couple of constants and some variables.

const DEF_WIDTH:int = 320;
const DEF_HEIGHT:int = 240;

var cWidth:int;
var cHeight:int;
var c:Camera;
var video:Video;
var window:NativeWindow;
var text:TextField;

Notice we've stored our default width and height in the two constants. After that, we create the variables we'll need later on. First are cWidth and cHeight. These represent the content width and height. These will be set with command line arguments in a bit. Next we have our camera and video objects, followed by a window variable which will hold a reference to our program's window. Lastly, we have a simple textfield. We will use this textfield to display a message to the user if we cannot find a camera.

The key to using command line parameters in an AIR application is the InvokeEvent. This event is fired when the application is launched, so we need to make sure we add an event listener for it as shown below.

NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvoke);	
 
function onInvoke(e:InvokeEvent):void 
{
    trace('onInvoke', e.arguments);
}

Notice that the InvokeEvent object has a property named arguments. This is an array of all the passed in command line arguments. Each element is a string. If you run the program now, you should see 'onInvoke' traced to the output window and nothing else. That is because we have not yet passed anything into our program. This is not overly exciting, so let's add some real code to our onInvoke function to handle the command line arguments. For our purposes, the command line arguments we'll be looking for are "w" and "h" for width and height. These will determine the size of the camera feed we see when the application launches.

Go ahead and remove the trace in the onInvoke function and add this code instead:

NativeApplication.nativeApplication.removeEventListener(InvokeEvent.INVOKE, onInvoke);	

window 	= NativeApplication.nativeApplication.activeWindow;
cWidth	= DEF_WIDTH;
cHeight	= DEF_HEIGHT;
	
// get the command line arguments
for each(var s:String in e.arguments)			
{
    if (s.indexOf("w=") >= 0)
    {
        cWidth = parseInt(s.substr(2, s.length));
    }
		
    if (s.indexOf("h=") >= 0)
    {
        cHeight = parseInt(s.substr(2, s.length));
    }
}

The first thing we do is remove our event listener. Then we grab a reference to our application's window. After that, we set the content width and height to the default values. The next line is where things start getting interesting as we find our command line arguments. In this case, we just loop through the array of arguments and look for "w=" and "h=" in the string. If we find either of those, then we need to grab the actual value that was passed in for them. We do this using parseInt on whatever comes after the equals sign.

So imagine someone passed in a width of 640. The argument string would look like this: "w=640". We use the substr function to grab everything after the equals sign and store it in our cWidth variable. In this case, cWidth would now be 640.

We need to be careful here because these values are coming in from the user. It is possible they made a mistake and hit the wrong key when entering the width or the height. We'll do some simple validation checks on the cWidth and cHeight values to guard against mistakes. Add the following code just below the for each loop we created above:

// check to make sure we got valid width and height values
if (isNaN(cWidth) || cWidth == 0 || isNaN(cHeight) || cHeight == 0)
{
    cWidth = DEF_WIDTH;
    cHeight = DEF_HEIGHT;
}

That's better. Now if some bogus value finds its way into our program, we'll catch it and go with the default width and height. Next, its time to use those values to adjust our window and stage size. Check out the code below and add it beneath the validation code we just put in.

// set size and scale properties
stage.scaleMode        = StageScaleMode.NO_SCALE;
stage.align            = StageAlign.TOP_LEFT;
window.width           = cWidth;
window.height          = cHeight;
window.alwaysInFront   = true;
stage.stageWidth       = cWidth;
stage.stageHeight      = cHeight;
	
init();

Here we are telling the stage that we don't want it to scale our content and also to align everything to the top left corner. Next, we set the width and height of our application window. I've also set the window to always be in front of other windows because when recording screencasts, I don't want my webcam feed to be obscured by whatever else may be happening on screen. After that, we set the stage width and height to match the window. The last thing we do is call an init function that we haven't written yet. This function will set up our camera and video object and add them to the display. If we can't find a camera to use, we'll use our textfield to display a message to the user.

function init():void
{	
    c    = Camera.getCamera();
	
    if (c)
    {
        c.setMode(cWidth, cHeight, 30);
        c.setQuality(0, 70);
        video = new Video(cWidth + 1, cHeight);
        video.attachCamera(c);				
        addChild(video);
    }			
    else
    {
        var tf:TextFormat;
		
        tf            = new TextFormat("Arial", 28, 0xcc0000, true);
        tf.align      = TextFormatAlign.CENTER;
        text          = new TextField();
        text.multiline = true;
        text.width    = cWidth;
        text.height   = cHeight;
        text.text     = "Camera\nNot Found";
        text.setTextFormat(tf);
        addChild(text);
    }
}

This is the entire init function and while it may look like a lot is going on, it really isn't too bad. First, we try to grab a camera reference. Next we check to make sure we successfully got a camera. If we did, then we set the feed's width and height according to our passed in values. The last number, 30, specifies the FPS we want. After that we set the quality of the camera feed and then we create our video object. Notice that I've added one to the cWidth here. That is because I was seeing a one pixel wide black line between the camera feed's right edge and the window's edge. Adding one eliminates that. Next we just attach our camera to the video object and then add the video to the display.

Above, we covered what happens when we get a valid camera, but what if for some reason we can't get the camera? There are multiple reasons the call to getCamera could fail. The user may not have a webcam connected to their computer or perhaps its already being used by another application. In that case, we create a textfield with a message telling the user that no camera was found. We also created a simple TextFormat object to make the message large and easily readable with big, red letters. The last thing we do is add the textfield to the display.

That's all there is to building this program. If you run it from Flash, it should work just fine and use the default width and height. However, I want to take things a bit further because at this point we're not even using our command line parameters! Let's first take a look at how to publish the AIR application. To do this, you'll need to go to the AIR settings panel by clicking the wrench next to the Target dropdown in the properties panel as shown below.

That should bring up the AIR settings dialog box. In here, you'll want to click on the Signature tab. Now we need to generate a signing certificate, so if you don't have one already, click the Create button. In the box that pops up, you need to fill in all of the fields and make sure you remember your password (refer to the image below). Once you've done all that, hit OK. Now you can enter your password and click the Publish button. This will generate a .air file which you can then open to install the program on your computer.

Now that we've got the program installed, its time to have a look at launching it from the command line and passing in our parameters. By default, mine installed to: C:\Program Files (x86)\PiP. Navigate to the directory and open a command prompt there (on Windows, hold shift and right click, choose Open command window here). Now just type in the following command as shown below.

If everything worked, you should now see the PiP program start and the window size will be 640x480! Woohoo! You can also try starting it without passing in any parameters and it should start at our default size. It will also start at the default size if either parameter is invalid (such as trying w=lol).

That's it, you're all done! In this tutorial you learned how to create an Adobe AIR application which accepts command line arguments. You learned how to parse the data out of the InvokeEvent object's arguments array and how to practically apply it in a real, working program. I hope you found this useful. You can download the sample project file below (Flash CS6) or check out PiP on github.

Download Source File (Flash CS6)

See PiP in action.

Bookmark and Share

Leave a Reply

Subscribe to RSS feed FGS5 Badge