Will Adobe Open Screen Project bring Flash to Game Consoles?

Will the Adobe Open Screen Project bring the Flash player to game consoles? Will I be able to create a Flash game and deploy it via Wiiware?

The open screen project removes some licensing restrictions on delivering the Flash Player and also documents a porting layer for the API, making it easier to get the Flash Player working on your device. I do not see Nintendo or Sony or Microsoft on the list of supporters, but I do think this move would make it easier to implement a version of the Flash Player for game consoles. I wonder if a game developer would take the time to do that, or if it has to be done by the console maker?

The implications for a game developer to be able to develop something once and deploy it across consoles and computers consistently is huge. Maybe my next company will be a gaming company. I'm still digesting what this will mean for the community as Flash and Flex Developers.

Ryan's post on the topic also mentioned also mentioned Adobe AIR for devices, which is a new concept for me. Kevin Lynch's video also mentions AIR for Devices.

Using AIR to launch other applications

Lets say you want to open an MS Word file from your web page. You can just link to it using a normal HREF. Browser settings and the operating system will take care of the rest. If it's a PDF, Reader will open. Word will launch for a .doc file. Excel for an excel sheet. ( Or perhaps your browser independent equivalents ).

How do you give the same functionality to an AIR Application? This exact question came up on the Flex Coders list recently and the general concensus was that it could not be done. That surprised me, because I figured you could do something very similiar to what you would do in a web page and let the operating system handle it. This would (I assume) not violate ay security protocols inside AIR. Am I right?

I played around with it and found one solution to the problem. It's far from perfect, though. I accomplished this using the NavigateToURL functionality. The code is really simple, just a button to open the file:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script><![CDATA[
import flash.net.URLRequest;
      
public function clickButton():void{
var request : URLRequest = new URLRequest('C:\\projects\\test.doc');
navigateToURL(request )   
}
]]></mx:Script>
   
<mx:Button click="clickButton()" />
</mx:WindowedApplication>

Click the button, it creates a URL Request and then uses navigateToURL to launch it. In my tests, this will launch a browser instance outside of AIR; and that browser instance will deal with the file, launching word, or a text editor, or whatever depending upon the file.

I can understand how, in some situations this would not be ideal. Perhaps in AIR next we need a navigateToApplication?

How can I find the user's screen size in AIR?

Yesterday, someone posted to Apollo Coders to ask if they can find out the user's screen resolution in an AIR application. The answer is yes, you can.

You can find this information out using the flash.system.Capabilities class. You need to look at the screenResolutionX and screenResolutionY properties. These are static properties on the Capabilities class, so you do not need to create an instance.

The poster also asked if he could find the height and width of the current window. This on was even easier to answer, because windows (and most UI controls ) have a height and width in the Flex framework.

I can demonstrate both of these answers with a single code sample. This code sample will size the application window to 60% of the screen width:

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
    preinitialize="preInitializeHandler()"/>

<mx:Script><![CDATA[

import flash.system.Capabilities;
import mx.controls.Alert

private function preInitializeHandler():void{
// set the width to 60% of the full screen this.height = Capabilities.screenResolutionY * .6;
this.width = Capabilities.screenResolutionX * .6;
this.visible = true;
}

]]></mx:Script>

</mx:WindowedApplication>

This code is very similar to something I used in a Flex application for a client. It runs code in the preinitialize event. That code sets the height and width of the WindowedApplication to 60% of the screenResolution. Then it makes the window visible. ( I set the window to be invisible in the app.xml file )

As a note, this should work in a Flex app too, but I haven't tried it.

I got a busy week this week. Thursday I'm at a a Microsoft even in Hartford. I understand they are giving out free software. Friday I'm down in NYC to do some podcast interviews at Flex Camp Wall Street.

Accessing command line arguments in AIR!

A question came up over on the Apollo Coders group about how to access command line arguments in an AIR application. I know that there are other explanations + documentation out there on this topic, but I thought I'd regurgitate what I have learned.

In Flex Bulder create an AIR application. I named mine "CommandLine", and the CommandLine.mxml looked like this:

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

It's an empty app that does nothing, as expected when it is first created. This application will do the brilliant act of displaying the command line arguments using an alert. So, let's add a script block and import the alert.

<mx:Script>
<![CDATA[
import mx.controls.Alert;
            
]]>
</mx:Script>

Arguments are attached the invokeEvent ckass. So, at the top level (WindowedApplication), let's listen to the invoke event:

<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" invoke="onInvoke(event)">

And we'll need to write an onInvoke function inside our script block:

private function onInvoke(event:InvokeEvent):void{
Alert.show(event.arguments.toString());
}

This function is named onInvoke. It accepts the InvokeEvent as an argument. The InvokeEvent has a property named arguments. Arguments is an array. This method converts it to a string and displays it.

Run the app and you'll see an empty alert box. Let's add some arguments. In Flex Builder, if you select the play drop down and go to "run...". The menu will look something like this:

And it will bring up this configuration screen:

You'll notice the config screen has a place for command line arguments. In this situation I typed test=test, test2=test1 . So far as Flex is concerned, Command line arguments are separated by a space; so I get two command line arguments: "test=test," and "test2=test1".

A few things that you might want to be aware of:

  • The invoke event is fired every time the application is launched, either by double clicking a shortcut or by double clicking the .exe file (or whatever your preferred method of choice is for launching an application). It does not matter if the application is already loaded, the invoke event will be re-run. You may want to write logic to prevent the app from initializing the command line arguments twice.
  • I'm not sure how to add command line arguments to the AIR Application shortcuts as part of the AIR installation process. Does anyone know? In my situation, the AIR app is being launched by another application, so that application handles creating and passing the command line arguments.
  • In it's current form, there is no concept of named arguments. So, the arguments in my above example are "Test=test". I do not have an argument named "test" with a value "test". I bet you could write a parser using regex and a Dictionary to generate your named arguments. Maybe I'll experiment with this at some future time.

The link I saved to the original thread is here although it does not appear to be working at the time of this writing. Maybe I got the link wrong. I currently have 11 things on my list of "writing ideas" and sometimes it takes a while for this stuff to peculate.

Upgrading to Flex Builder 3

I just got the chance to upgrade from Flex Builder 3 Beta 3 to Flex Builder 3 Gold and along the way I also upgraded an application from AIR AIR 1.0 . My upgrade this time was very smooth.

First, as always I strongly recommend reading the release notes all the way through. Do it twice.

The Adobe Partner portal only has the stand alone version, so it took a little searching to find the plug in version. I'm not sure why plug in and stand alone are not on the same page of the public site.

This time I actually used the -clean feature of eclipse to save all my previous work spaces. I'm glad I did; that was a brilliant move. Saved me a ton of time since I have dozens of work spaces.

My AIR application only needed one tweak to the -app.xml config file. I had to change the descriptor from "1.0M6" to "1.0". I figured there would be a change like this along the lines, but I could not find it documented anywhere. I created a new application file and visually compared the Beta 3 XML descriptor with the 1.0 descriptor.

All good stuff!

Reviewing My 360Flex Survey Results

The 360Flex have posted the results of session surveys. Here are mine. Based on a few other speakers I spoke to, I got a lot of responses (20 once you discount the joke review I filled out for my own session).

I thought my session went great, and was in a room with 40-50 people or so. I felt I was able to facilitate a discussion with my attendees (as opposed to just lecturing them), which is what I aim for. I was really worried about having to "repeat the questions", which the ""signers" asked me to do so they could relay to the hearing impaired attendee. But, I think I did pretty good with that.

A few comments that I felt were worthy of mention:

Very nice personality; funny and easy to listen to.

This is a huge boost to my ego. I don't usually think of myself as funny (although I can be sarcastic), but I'm glad you were entertained.

...he was able to facilitate the audience for answering those he did not have knowledge on.

Good conversational communication style

This is the vibe I shoot for when presenting, so I'm glad that at least two person 'got it' and enjoyed it.

He didn't think AIR was broady applicable

This is true, and I'm not ashamed to say it. In fact I did say it in the intro to my presentation. I do not think AIR 1.0 is primed up for wide adoption. The business case for AIR, as I see it, is that it makes it very easy to write "Partially Connected" applications.

More for beginners.

I was very torn whether to tell John and Tom that my preso was a "100" level or "200" level. I went with 200 level. Maybe I shouldn't have. I went with 200 because there is a lot of code that I just glaze over because it was not the focus of the presentation. However, the beginning of my preso deals with things such as "What is AIR and why do we care?" and "Why do we care about code reuse?" That is very intro stuff. However, I made the audience answer those questions to make sure we were on the same page moving forward.

ppt skillz = -1

Oddly someone else said that the slides were useful. The presentation was not about powerpoint, and I think I used it well enough to communicate what I needed to communicate. I'm fine with not being a powerpoint wizard.

He had a hard time answering alot of the questions. It seems like he was relatively new the Flex. I felt like the attendees wanted more answers than he was able to give.
This was sentiment echoed a couple times in the comments, and that surprised me. There was a question or two that I didn't have answers to. I wish I remembered what they were. I don't remember being totally clueless, though. I'd rather say "I don't know" than to BS an answer so I look like I know stuff.

Was a little short

I find it hard to fill up fifty minutes worth of time. 80 minutes scares me. I've spoken to other presenters who have expressed chagrin about the 80 minutes presentations. However, I also know many presenters who could fill up 3 hours without a second though.

And for those that read this far, thank you! Postcards for The Flex Show will be making appearances in the attendee swag bag at two separate Flex Camps:

There is a chance (schedule permitting) that I'll be at Flex Camp Wall Street recording interviews for The Flex Show, although I'm out of the office the day before it for a separate event, so I'm not sure. But Mike Labriola said he used to have my laptop model and may have some extra batteries I could "acquire" from him, so...

I need to figure out April's schedule. Are you going to be at Flex Camp Wall Street? Would you like to listen to me podcast (live) from Flex Camp Wall Street?

Local Access URLs in Adobe AIR

One of the benefits of Adobe AIR, over a browser based application, is that you can have access to the local file system. This question came up on the House of Fusion Flex Coders list; and I thought I'd blog the answer.

I truncated the original question a bit.

I've got an Flex/AIR app which contains a SQLite db and some photos which will be included in the install package.
[cut]
I need to open the db file locally [without using a hard coded absolute path]

How might I go about referencing it this file so that it will work both in development, and installed?

Adobe AIR offers two URL schemes for accessing the local file system. Documentation is here.

  • app:/: App URLs are relative to the application install directory. This is what the poster would need to access the assets he was distributing with his application.
  • app-storage:/: The app-storage URL will get you to the application's storage directory. On a Windows (XP) machine this is under "Documents and Settings/username/applicationdata/"

As an indirect correlation, if you need the absolute paths to the application install directory or the application root directory, you can get them using the File Class.

Somewhere in your ActionScript code, just import the class:

import flash.filesystem.File;

Two static variables exist on the File class, applicationDirectory and applicationStorageDirectory. This code saves them to local variables:

public var appDirectory : String = File.applicationDirectory ;
public var storageDirectory : String = File.applicationStorageDirectory ;

Since these are static properties you do not need to create an instance of the file class to access them. I'm not sure if one method is preferred over the other, as both seem easily transportable between systems and applications.

On Wednesday the 20th, I'll be all over. I'll be speaking to a business group at the Meriden Connecticut Chamber of Commerce in the morning. I'm speaking as part of their Small Business Institute; and will be speaking on the differences between web sites, web applications, and Internet applications.

In the evening, I'm off to the Boston User Group to speak on code reuse between Flex and AIR. This will be my last time giving the presentation before heading off to 360Flex in Atlanta. Are you in Atlanta and want to get together sometime on Saturday -Wednesday let me know.

How was your Upgrade to Flex 3 Beta 3?

A few weeks ago I finally got to upgrade from Flex Builder 3 (Beta 2) to Flex Builder 3 (Beta 3). I had an AIR application in the works, so along the way I also got a chance to upgrade the AIR runtime and SDK. As with all upgrades, I strongly recommend reading the release notes. Read them twice.

My software upgrade was not very smooth, unfortunately. The first step was to uninstall Beta 2. I opened up the windows control panel and uninstalled it. However, that did not appear to do anything. Any attempt to install Beta 3 would tell me that Beta 2 was still installed. ( I don't remember the exact message ). Eventually I opened up my eclipse directory and manually deleted everything that had com.adobe.* in the directory name. After that process, the Beta 3 install would succesfully complete.

Once I got it installed, the code upgrade process was relatively smooth. I had to change a few APIs on my AIR Application:

  • File.applicationResourceDirectory -> File.applicationDirectory: This was documented and had no issues.
  • HTMLControl --> HTMLLoader: this was documented and had no issues
  • HTMLPDFCapability.STATUS_OK turns into PDFCapability.STATUS_OK I couldn't find this change documented anywhere, but performed some searching of the documents and figured out what was going on.
There are plenty of other API changes, but these were the only ones that affected me. Be sure to read the release notes for a full list.

One issue I had, that wouldn't cause a compiler error was that the URL schemes have changed regarding local file access. The "app-resource" scheme was replaced with "App". In my code, the URLs to local files were always stored as strings; even a wrong URL path is still a valid string, so it makes sense the compiler wouldn't flag them. I wonder if Flex could benefit from a "compatibility analyzer" like used to be in the ColdFusion Administrator? I just used search and replace to address all those changes.

My good friend Jason asked me a question about upgrading and licensing:

I decided to install Flex 3 Beta 3. Much to my chagrin, FB3-B3 considers my Serial number to be invalid? Have you encountered this?

I experienced the same issue, although I couldn't find any documentation about it. I assume that Flex Builder 3 has moved to a new version licensing scheme and the Flex Builder 2 serial numbers will no longer work. A computer world article states that the AIR release will be next month (February), so I'm expecting an official release soon. Can you think of any events in February where Adobe could make a big announcement?

What problems did you have when upgrading your application?

How do you put an AIR App in the System Tray?

I'm being watched. I don't know exactly what that means, though. I have to admit, it's a bit weird. That feed is in my list of blogs to read, but otherwise I'm not sure what that post means. Anyone know who Iconara.net is or why they want to watch me?

Anyway, I'll be speaking this year on Code Reuse with Flex and AIR. The intent of the topic is to talk about how to write code that you can then reuse in both a Flex and AIR application. ( Dan contacted me asking for clarification ). I'll be giving this presentation next week in Connecticut at CFUGitives ( The Southwest CT Adobe User Group) and at the Hartford Adobe User Group. Next month I'll be giving it at the Boston User Group and the 360Flex conference in Atlanta. That's a busy schedule, I think.

Anyway, I'm working on my presentation, and wanted to use a moment to try put my AIR app into the system tray. AFter some search, it appears that Saskovic already did the work for me. I took his code and discovered it wouldn't compile on Beta 3. I did a quick read through of the AIR release notes and was able to convert his code to work on the latest release.

Here it is:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApplication()">
<mx:Script>
   <![CDATA[
   /**
   * This example describes how to dock an AIR application to the system tray
   * and then undock it again.
   * The minimize and close actions of the WindowedApplication are caught, so
   * that we can introduce our own actions.
   *
   * A simple systray menu is presented, to show the usage of that.
   *
   * @Author: S.Radovanovic
   * @Url: http://www.saskovic.com/blog/?p=5
   * @Date: 24-11-2007
   * @Author: Jeffry Houser
   * @Date: 09-01-2007
   * Updated for AIR Beta 3
   */

   import mx.controls.Alert;
   import mx.events.CloseEvent;

   private var dockImage:BitmapData;
   
   /**
   * Initialize the application to the default values.
   * This method is called upon creationComplete from the Windowed Application
   *
   * @Author: S.Radovanovic
   */
   public function initApplication():void {
   
      //Use the loader object to load an image, which will be used for the systray       //After the image has been loaded into the object, we can prepare the application       //for docking to the system tray
      var loader:Loader = new Loader();
      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, prepareForSystray);
      loader.load(new URLRequest("http://www.saskovic.com/images/systray_icon_16.png"));
      
      //Catch the closing event so that the user can decide if it wants to dock or really       //close the application
      this.addEventListener(Event.CLOSING, closingApplication);
   }

   /**
   * Check if the user wants to close the application or dock it
   *
   * @Author: S.Radovanovic
   */
   private function closingApplication(evt:Event):void {
      //Don't close, so prevent the event from happening
      evt.preventDefault();
      
      //Check what the user really want's to do       //Alert.buttonWidth = 110;
      Alert.yesLabel = "Close";
      Alert.noLabel = "Minimize";
      Alert.show("Close or minimize?", "Close?", 3, this, alertCloseHandler);
   }

   // Event handler function for displaying the selected Alert button.
   private function alertCloseHandler(event:CloseEvent):void {
      if (event.detail==Alert.YES) {
         closeApp(event);
      } else {
         dock();
      }
   }


   /**
   * Check to see if the application may be docked and set basic properties
   *
   * @Author: S.Radovanovic
   */

   public function prepareForSystray(event:Event):void {
   
      //Retrieve the image being used as the systray icon
      dockImage = event.target.content.bitmapData;
      
      //For windows systems we can set the systray props       //(there's also an implementation for mac's, it's similar and you can find it on the net... ;) )
      if (NativeApplication.supportsSystemTrayIcon){
         setSystemTrayProperties();
         
         //Set some systray menu options, so that the user can right-click and access functionality          //without needing to open the application          
SystemTrayIcon(NativeApplication.nativeApplication .icon).menu = createSystrayRootMenu();
      }
   }

   /**
   * Create a menu that can be accessed from the systray
   *
   * @Author: S.Radovanovic
   */
   private function createSystrayRootMenu():NativeMenu{
      //Add the menuitems with the corresponding actions
      var menu:NativeMenu = new NativeMenu();
      var openNativeMenuItem:NativeMenuItem = new NativeMenuItem("Open");
      var exitNativeMenuItem:NativeMenuItem = new NativeMenuItem("Exit");

      //What should happen when the user clicks on something...       

openNativeMenuItem.addEventListener(Event.SELECT, undock);

      exitNativeMenuItem.addEventListener(Event.SELECT, closeApp);

      //Add the menuitems to the menu
      menu.addItem(openNativeMenuItem);
      menu.addItem(new NativeMenuItem("",true));
//separator
      menu.addItem(exitNativeMenuItem);
      
      return menu;
   }

   /**
   * To be able to dock and undock we need to set some eventlisteners
   *
   * @Author: S.Radovanovic
   */
   private function setSystemTrayProperties():void{
      //Text to show when hovering of the docked application icon       
SystemTrayIcon(NativeApplication.nativeApplication .icon).tooltip = "Systray test application";
      
      //We want to be able to open the application after it has been docked       
SystemTrayIcon(NativeApplication.nativeApplication .icon).addEventListener(MouseEvent.CLICK, undock);
      
      //Listen to the display state changing of the window, so that we can catch the minimize       
stage.nativeWindow.addEventListener(NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING, nwMinimized); //Catch the minimize event
   }

   /**
   * Do the appropriate actions after the windows display state has changed.
   * E.g. dock when the user clicks on minize
   *
   * @Author: S.Radovanovic
   */
   private function nwMinimized(displayStateEvent:NativeWindowDisplayStateEvent):void {
   
      //Do we have an minimize action?       //The afterDisplayState hasn't happened yet, but only describes the state the window will go to,       //so we can prevent it!
      if(displayStateEvent.afterDisplayState == NativeWindowDisplayState.MINIMIZED) {
         //Prevent the windowedapplication minimize action from happening and implement our own minimize          //The reason the windowedapplication minimize action is caught, is that if active we're not able to          //undock the application back neatly. The application doesn't become visible directly, but only after clicking          //on the taskbars application link. (Not sure yet what happens exactly with standard minimize)
         displayStateEvent.preventDefault();
         
         //Dock (our own minimize)
         dock();
      }
   }

   /**
   * Do our own 'minimize' by docking the application to the systray (showing the application icon in the systray)
   *
   * @Author: S.Radovanovic
   */
   public function dock():void {
      //Hide the applcation
      stage.nativeWindow.visible = false;
      
      //Setting the bitmaps array will show the application icon in the systray
      NativeApplication.nativeApplication .icon.bitmaps = [dockImage];
   }

   /**
   * Show the application again and remove the application icon from the systray
   *
   * @Author: S.Radovanovic
   */
   public function undock(evt:Event):void {
      //After setting the window to visible, make sure that the application is ordered to the front,       //else we'll still need to click on the application on the taskbar to make it visible
      stage.nativeWindow.visible = true;
      stage.nativeWindow.orderToFront();
      
      //Clearing the bitmaps array also clears the applcation icon from the systray
      NativeApplication.nativeApplication .icon.bitmaps = [];
   }


   /**
   * Close the application
   *
   * @Author: S.Radovanovic
   */
   private function closeApp(evt:Event):void {
      stage.nativeWindow.close();
   }
]]>
</mx:Script>
   
</mx:WindowedApplication>

I'm not sure if the Blog formatting may have added extra line breaks or not in the comments, so beware of that.

Over the next 3-6 months, I want to blog about the process I use in creating an application, from conception to completion. My plan is to build an "RSS Watcher". Something that can sit in my sustem tray, watch an RSS Feed, and show a pop-up window whenever an RSS Feed changes. I have a preliminary version of this that I hacked together as an example in the presentation. IT uses Saskovic's code along with code from the Adobe example app Wordup.

Upgrade AIR from Beta 1 to Beta 2

As most of you reading this probably know, Adobe AIR Beta 2 was released on the first day of the Adobe MAX conference. With the public release of Beta 2, I was able to migrate an application and deliver it to the client.

Here are a few things I discovered during the migration:

  • Read the release notes twice. Read them once before you start the migration, and then keep them handy as you try to migrate. A bunch of my issues were addressed there, I just forgot about that they were listed. I forgot to Migrate the Application Descriptor.
  • Flex Builder 3 includes the AIR SDK. You do not need to download and do a separate install. I would expect this to be documented somewhere, but I couldn't find it and it was a source of confusion for me.
  • Keep Imports Organized went from off to on. This caused problems as I was trying to debug some code, and Flex Builder automatically started removing imported classes that were listed in the import list. As I uncommented code to isolate a bug, I got errors because the class imports were missing. You can turn this off by windows--> Properties --> Flex --> Editors --> ActionScript Code --> Keep imports organized.
  • Supposedly you can run the SDK of AIR Beta 1 and AIR Beta 2 side by side, but I couldn't find any documentation on this. I backed up my Eclipse directory, then installed the Flex Builder Beta 2 plugin into "Flex Builder 3 Plug-in B2" instead of "Flex Builder 3 Plug-in". So, beta 2 went into the "B2" Directory and beta one was untouched. I upgraded my 'original' eclipse install folder. I just need to make shortcuts to each eclipse install. The backup for beta 1 usage, and the current directory for the Beta 2 usage. I would have thought the multiple SDK feature of Flex Builder would have handled his, but it didn't for me.
  • When using the file APIs, the 'get file path from URL' method changed from "resolve" to "resolvePath". This is the element I remembered from the first time I read the release notes.
  • And finally, I noticed that the invoke event of an AIR app was now firing before CreationComplete event instead of after. In Beta 1, I set values in creationComplete and accessed them in the invoke. In beta 2, those values were still in their default state. I had to move around some initialization code. So far as I know, this is not documented anywhere.

More Entries

All Content Copyright 2005, 2006, 2007 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.8.