AIR Beta 3 Migration Tips
AIR Beta 3 is an exciting release that takes us one step closer to AIR 1.0. Unlike the myriad of changes introduced in the move from AIR Beta 1 to AIR Beta 2, the changes in AIR Beta 3 are far more subtle. While this stability indicates the growing maturity of the product, AIR Beta 3 is an update and will require some changes to your applications. You can read the release notes of course, but in the progress of updating my forty-plus AIR applications, here are the common changes that I encountered.
Application Descriptor File
The good news here is that most of the changes take place up front and are very easy to update. The XML attributes “version” and “id” used to be on the root “application” node, but have now gone solo and are nodes on their own. There also used to be a node called “title” that came before the “initialWindow” block. That node is now called “filename” which is used for the application filename and is required. Most of the other nodes are the same, or will work as is from AIR Beta 2.
<?xml version="1.0" encoding="utf-8" ?>
<application xmlns="http://ns.adobe.com/air/application/1.0.M6">
<id>com.example.ExampleApplication</id>
<name>Example Co. Example Application 1.0</name>
<version>1.0</version>
<filename>Example Application</filename>
<description>This is a sample AIR application.</description>
<copyright>(c) 2007 Example Co., Inc.</copyright>
<initialWindow>
<content>ExampleApplication.swf</content>
<title>Example Application</title>
<systemChrome>standard</systemChrome>
<transparent>false</transparent>
<visible>true</visible>
</initialWindow>
</application>
Application Resource Directory
For security reasons, there were a number of changes introduced to the “application resource directory” in AIR Beta 2. One of those that you may have missed, especially during development with ADL, is that you cannot write to the resource directory. That directory is designed to contain only the core files that shipped with the application. This is really important if you’re shipping a database file or the likes with your application, as you’ll need to move it elsewhere for the “first run” of the application.
As far as the API goes, what was the File.applicationResourceDirectory property is now the File.applicationDirectory property. Also note that if you’re developing AIR applications with HTML, all this security goodness means that you likely use an IFRAME for most of your content. The sandbox bridge used to require that the “documentRoot” property had a value of “app-resource:/”. The value for AIR Beta 3 is simply “app:/” removing the redundancy of the “resource” term.
<iframe
id="viewport"
src="ui.html"
sandboxRoot="http://SomeRemoteDomain.com/"
documentRoot="app:/" />
HTML Control Moved to MX Package
Since most of my examples tend to cross liberally over the lines of JavaScript and Flash, I often found myself referring to the “window.htmlControl” property. The HTML proper has been moved over to the Flex SDK, which means it is now a part of the “MX” package and not included with the runtime itself. The good news is that there is a “window.htmlLoader” property that largely takes its place. Functionality such as the “stage” property, can now be found on the “window.htmlLoader” property from JavaScript.
function doSave()
{
var png = null;
var capture = null;
var stream = new air.FileStream();
var temp = air.File.applicationStorageDirectory.resolvePath( 'capture.png' );
capture = new air.BitmapData( window.htmlLoader.stage.stageWidth,
window.htmlLoader.stage.stageHeight );
capture.draw( window.htmlLoader );
// Encode image
png = runtime.com.adobe.images.PNGEncoder.encode( capture );
stream.open( temp, air.FileMode.WRITE );
stream.writeBytes( png, 0, 0 );
stream.close();
}
Creating a Native Window from HTML
When creating new native windows from JavaScript, I found it more effective to reach deeply into the Flash side of the house. The good news is that it is now much easier using the HTMLLoader.createRootWindow() method. You see that little “HTMLLoader” class part there? Well you know that there’s the new “window.htmlLoader” property, right? So I must be referring to that right? Nope! This one stumped me for a while, but the createRootWindow() is a static method and therefore does not require an instance of HTMLLoader to operate.
function doWindow()
{
var init = new air.NativeWindowInitOptions();
var bounds = null;
var win = null;
var login = air.File.applicationDirectory.resolvePath( 'login.html' );
bounds = new air.Rectangle( ( air.Capabilities.screenResolutionX - 325 ) / 2,
( air.Capabilities.screenResolutionY - 145 ) / 2, 325, 145 );
init.minimizable = false;
init.maximizable = false;
init.resizable = false;
win = air.HTMLLoader.createRootWindow( true, init, false, bounds );
win.load( new air.URLRequest( login.url ) );
}
XMLHttpRequest Limited in Classic Sandbox
This one is a real pain. Inside the classic sandbox the XMLHttpRequest object used to be capable of cross-domain requests. This is sadly no longer the case. By default, XMLHttpRequest is now limited to the originating domain for the document, or the domain specified in the “sandboxRoot” attribute in the application sandbox on the IFRAME. If you have constructive feedback on this change, I’d really like to hear it, so please leave a comment if you feel so compelled.
Update: Special thanks to Keeto O. who pointed out that you can change this behavior by setting the attribute “allowcrossdomainXMLHttpRequest” to “true” on the parent sandbox IFRAME (per the AIR FAQ).
Flash in HTML Now Supported
I think the header says it all - Flash content is finally supported inside the HTML engine! It’s true! Take a pass on by the hotly debated new Adobe web site to see for yourself with your own AIR application. What? You haven’t built your own little browser? Well fine then, here’s a simple one for you! If you get so excited about this that you want to send a screen capture to your friends, just drag the button labled “Drag” from the AIR application to the desktop.
Better than just Flash however, this is the latest and greatest version of the Player to include H.264 support for your high definition viewing, to include hardware acceleration. I have an example showing how to build a video player from JavaScript using the Flash Video class. This of course is now no longer necessary. If you’re a JavaScript developer looking to easily leverage Flash video, then take a look at the Flash-Ajax Video Component, which I’ll be covering in more detail in a future post.
There is a negative side effect to all this goodness however, namely that Flash support has been accomplished by including a complete version of the Flash Player itself, and not by using the latent one in the AIR runtime. Yes, the product team understands the dependency injection. Yes, the product team understands this increases the overall size of the runtime itself. Rest assured that the product team appreciates the potential problems by taking this approach, but after deep research and heated debate, they felt this was best for the long term.
Opening a Database Connection
This one is far more subtle, but you’ll run into it wherever you use the embedded SQLite database. In AIR Beta 2, the SQLConnection constructor took a boolean argument to specify if the connection was synchronous or asynchronous. In AIR Beta 3 the SQLConnection constructor no longer takes any arguments. Just like with file IO, you specify which mode you’re opening the database connection by calling the respective open method (i.e. SQLConnection.open() or SQLConnection.openAsync()).
One of the other subtle changes of the SQLConnection.open() methods (either one) is that the arguments have changed slightly. The second argument used to be a Boolean value indicating whether or not AIR should automatically create the database if it doesn’t exist. This has been replaced by various constants on the new SQLMode class.
The SQLMode constants are SQLMode.CREATE, SQLMode.READ and SQLMode.UPDATE. The SQLMode.CREATE option is what the old Boolean value used to represent, and specifies that the database should be created if it doesn’t exist and made available for updates. The SQLMode.READ option indicates that a database should be opened only for read operations. Last but not least is the SQLMode.UPDATE option which will expect an existing database to be opened for updates.
function doLoad()
{
var file = air.File.applicationDirectory.resolvePath( 'crm.db' );
db = new air.SQLConnection();
db.addEventListener( air.SQLEvent.OPEN, doDbOpen );
db.open( file, air.SQLMode.CREATE );
}
WebKit Drag and Drop
This one really turned into a time suck when I was porting over all my sample applications, as I had previously leveraged only the Flash drag and drop event handlers on HTMLControl. As mentioned previous, that control doesn’t exist and has been replaced by an HTMLLoader property. You can try to hook the old listeners to that property, and while you won’t get an error, you won’t get a drag and drop operation either. The way to accomplish this in AIR Beta 3 is to use the drag and drop hooks that WebKit itself provides.
In the browser world, I’ve found that most developers don’t use this Safari feature because a) it is generally a Safari feature and b) the documentation on the WebKit project site is atrociously lacking. I intend to cover this in more depth in a future blog post, but in the meantime I’ve attached a drag-and-drop example built by Dragos Georgita on the AIR product team. It covers most everything you’ll need to get the idea of the internals.
At a high level, if you are accepting drag content, then you add the onDragOver and onDrop event handlers to whatever elements you want to accept the operation. This is much better than my previous Flash implementation as it allows accepting a drag and drop operation on a per element basis (i.e. drag a photo to a DIV or IMG that represents a personalized frame). You can accept individual content types by preventing the default event behavior (i.e. e.preventDefault()) in the onDragOver event handler.
function doDrop( e )
{
var elem = document.createElement( 'div' );
elem.innerText = e.dataTransfer.getData( 'text/plain' );
elem.className = 'drag';
document.body.appendChild( elem );
}
function doOver( e )
{
e.preventDefault();
}
If you are dragging content out of AIR, then you’ll first need to add the style “-khtml-user-drag” for the elements you want to handle drag and drop. The next step is to listen for the onDragStart event and handle it by adding the desired content to the event. If you’re going to use a custom image for the drag thumbnail you have two options. The first option is to point to an IMG element. If you want to use a BitmapData object, then you’ll ignore all this and still just use the NativeDragManager. Oh, and that has changed too - used to be simply DragManager.
function doStart( e )
{
e.dataTransfer.setData( 'text/plain', 'testing' );
e.dataTransfer.effectAllowed = 'copy';
e.dataTransfer.setDragImage( dragImage, 24, 24 );
e.stopPropagation();
}
This isn’t intended to be a replacement for either the documentation, or the release notes, so please be sure you read those thoroughly. These are simply the changes that I’ve found and wanted to share with the community. I’ve tried to put code wherever I could to help you get started, and cover everything pretty thoroughly. If you have additional questions, don’t hesitate to leave a comment and I’ll get an answer for you. In the meantime, enjoy AIR Beta 3.
December 13th, 2007 at 3:14 pm
This is a great post, thanks for the tips. I hope they won’t change anymore the application description file contents (even though the changes are minimal this time).
December 14th, 2007 at 5:55 pm
Thanks for this post! It goes much farther than the official release notes and documentation currently go.
I’d really love to see some code about the XMLHttpRequest issues though. It’s broken in my app and I can’t find a single item related to changes to it anywhere on the release notes or documentation!
December 15th, 2007 at 11:48 am
Actually, you can perform cross-domain calls using an XMLHttpRequest by setting the allowcrossDomainxhr attribute of your classic sandbox to true.
Although I appreciate the effort of trying to stop malicious code from being loaded from untrusted domains, I think that it is overkill to actually limit the classic sandbox’s ability to perform cross-domain calls. The Beta 2 security model already works pretty well, and if enforced properly, the need to limit XHR request from the defined sandboxRoot seems unnecessary.
December 16th, 2007 at 10:02 pm
“Flash in HTML Now Supported”
I wanted to update my Adobe Air Derby submission to the latest beta (and be able to share it online) and because i had problems doing so i did a search and stumbled on your post. Thanks for all the tips..
But as my Adobe Air derby submission was for most part kind of a joke about the flash support in html (i had hacked a flash overlay in a html window using javascript api), it’s probably not worth doing the work.
With flash support in html… now Air start to be really interessing!
December 16th, 2007 at 10:13 pm
I have read all the post about flash support in html… maybe the overlay is not a bad idea after all!
The idea was to use temporary image in a div of the size of the flash that had to be embeded and let the html control do the reflow work. On a update event, get the position of the div using javascript and display the flash instances (actually created in the “flex/flash” context) accordingly. It was not perfect, there was problems like the need to have some “vertical” masking (i cheated on this by having the html control covering all the height of the window, but at least there was no need for another player instance!
December 17th, 2007 at 1:03 am
Keeto,
Good catch! Thanks for the note! I update the post to reflect that soon.
Thanks again,
Kevin
December 28th, 2007 at 5:32 pm
Kevin, have you run into this situation:
Create a simple html/js air app that has an embedded iframe. Make sure there is html above & to the side of the iframe. Now try implementing the webkit drag inside of the iframe, and you’ll notice that the drag image is not of the element you started dragging. It’s as if the drag image does not take in to account the offset of the iframe, and therefore you’re getting a completely useless drag image originating outside of the iframe.
many thanks
January 13th, 2008 at 6:14 am
I’ve lost hours trying to do cross-domain xhr …
try allowcrossDomainxhr=”true” instead of allowcrossdomainXMLHttpRequest=”true”
January 21st, 2008 at 3:58 am
I’ve tried a bunch of different things to get xhr to work once I put it inside the sandbox but I am having no luck. It seems to be running the function but is returning no data (and no errors) and doesnt’ seem to actually talk to the webserver because it doesn’t bring up the username password box it use to when I had it on the non-secure side. I’ve got the cross domain flag set and the sandboxRoot set to the domain I am trying to talk to.
Any ideas or any working samples with the xhr inside the secure side would be great.
Thanks
March 2nd, 2008 at 8:03 pm
That was interesting point of view. I hope that it is ok for you that i made spanish translation that you can read here:
http://www.secretosdelweb.blogspot.com/
March 6th, 2008 at 8:45 am
I read the post http://myflex.tistory.com/entry/AIR-Beta-3-Migration-Tips Thanks for this post.This article about other writes waiting.
March 7th, 2008 at 4:10 pm
Hi Kevin,
I have been having problems with the XMLHttpRequest, although keetos post gives me some hope, so ill do it now, Has there been an updated release of any documentation, with regards to this?
thanks
March 26th, 2008 at 3:30 pm
I used to have a lot of problems with the XMLHttpRequest aswell Louis, a post that helped me a lot you can find it at the http://lists.apple.com/archives/web-dev/2006/Jan/msg00026.html
March 26th, 2008 at 11:13 pm
Louis Neill may explain your problem maybe we can help!
March 27th, 2008 at 12:13 pm
Thanks for the post! It has alot more uses then written on the official documentation
April 7th, 2008 at 9:22 pm
Hi Kevin, I read in your bio you are from Parker, Co. Do you know Dona Mares, an artist, who lives there? She use to own a gallery on the main hwy called Kokopellis. She did the cover of my book. Anyway, my interest is in Macromedia so I hope you have more posts regarding that software. I’ve enjoyed reading about your travels and sharing your knowledge with other like-minded people. It’s good to know that people are connecting on different levels. Sounds like you have a wonderful life. Best, Greg
April 9th, 2008 at 2:53 am
hi Kevin, It just won’t play.. I can’t get any FLV files to play in Windows Vista AIR b3.
Bit strange - I guess you haven’t been able to test it on a PC yet.. I’ll look at the FLA and try to fix it.
April 12th, 2008 at 7:39 pm
I agree. And I have had difficulties just to use any FLV. It seems that once converted from a AVI or Mpeg, they just can’t start for any reason…
April 14th, 2008 at 5:48 am
Thank you kevin very good post with v good comments
April 15th, 2008 at 5:28 pm
Thanks for the tip kelvin. Your explaination is very detail and easy to understand.
April 16th, 2008 at 6:20 pm
Wish I had found this tutorial earlier, I had to hire someone to do migration for me. Anyways, thank you for writing this. I just hit Ctrl+P
April 17th, 2008 at 3:07 pm
Can’t comment much, but i can say you have done a great job making this post. They are pretty detail and good. Thanks for it.
April 18th, 2008 at 1:45 am
Nice article there Kelvin! Very detailed. Thanks
April 20th, 2008 at 3:40 am
Very useful tip for me. Thanks for it.
April 21st, 2008 at 8:30 pm
Hi kevin you have great site and very helpful programming tips thank you
April 23rd, 2008 at 6:13 pm
Great and detail explanation on AIR Beta 3. I love reading most of your post and it helps in improving my programming skill. Thanks!
April 23rd, 2008 at 7:48 pm
Nice article. Even though I had migrated already but this article was still helpful. Thanks for posting.
April 25th, 2008 at 10:37 am
Kevin, this was a huge help. I have to say you are great at explaining this stuff, I always get lost in the release docs. I will bookmark this for future use.
April 26th, 2008 at 9:10 pm
Has Air version 1 been released yet as I can’t find any reference to it. If not when is v1 due to be released?
April 26th, 2008 at 9:32 pm
Hey Kevin, This is a wonderful guide to back a really nice project! Kudos to you sir.
April 27th, 2008 at 1:39 am
Great tips for the migration. I have already bookmark this page. Thanks for it.
April 27th, 2008 at 7:01 am
My FLV recordings stop at “100% Reading… / 99% analyzed…”
Is this app supposed to be able to handle FLV files with data keyframes/metadata inserted with the NetStream.send() method?
April 27th, 2008 at 2:29 pm
Has there been a change to the number of concurrent XML socket connections allowed in AIR beta 3. It appears to be limited to 16.
April 27th, 2008 at 6:01 pm
Kevin
Thanks again for posting such great stuff!! I am new to your blog though more I look around the more impressed I am.
You have a great way of explaining things so a new comer like me to programing can also follow along.
Thanks again for taking the time and effort to create such great informative posts. I will book mark this page for future reference.
Thanks Ambit
April 27th, 2008 at 10:17 pm
Honestly, I see clearly how AJAX is getting to be the future of FLASH. Faster, easier (as it could be) and more convenient. It’s probably wise just to focus on AJAX now…My 2 cents though…
April 28th, 2008 at 12:35 pm
Thanks for the good info Kevin finally got it to work
April 28th, 2008 at 1:26 pm
Since i am still a newbie at this,i never got to use the beta version (went to the 1.0 version straight) I still found this article very helpful
I just subscribed to your feed.
April 28th, 2008 at 7:08 pm
Hey Kevin
Thanks for the post. Great stuff!! I do not think that AJAX will completely replace Flash though it is much faster and simpler!
Kevin I also need to say that the way you explain things really does make it easy for everyone to understand. I will book mark your blog for future needs.
Thanks again.
April 29th, 2008 at 8:42 am
Another interesting but moreover, useful article.
Great site!
April 29th, 2008 at 9:15 am
Thank you for the helpful information. It should help me figure out most of this stuff. Thanks.
April 29th, 2008 at 10:28 am
Awesome tutorial and guide. No wonder so many bloggers chose to republish your article. I am not so good at the technical part, but I’ve bookmarked for future reading.
Cheers,
April 29th, 2008 at 2:02 pm
Thanks for the extra code Kevin. However, I’d read a while back that if you installed Beta 3 you would not be able to install applications via install badge. Was that actually the case?
April 29th, 2008 at 2:30 pm
Thanks, this is very useful for me. Great post and, as always, you explain everything in a thorough, yet easy to follow way.
April 29th, 2008 at 3:32 pm
Kevin, thanks for great information, we are definitely on the right way what use in our new project.
April 30th, 2008 at 6:15 am
Hi,
I can’t find a change log for the new release. Does the new runtime allow Flash content on HTML pages?
I’ve been waiting for this really long time!
April 30th, 2008 at 2:54 pm
When I heard that the Linux version of AIR was ready for testing, I dropped everything I was working on and set up Ubuntu, Flex Builder on Linux, and installed AIR. It’s amazing enough that I’m writing desktop applications using web technologies like Flex, ActionScript, JavaScript, and HTML, but to be able to deploy them with no changes across Mac, Linux, and Windows is seriously revolutionary. Keep good work Kevin, you help us.
Thanks mate.
May 1st, 2008 at 4:19 pm
Thank you Kevin for your help
May 31st, 2008 at 12:31 pm
Thanx your articles
June 12th, 2008 at 2:13 pm
your blog is awesome kevin
thanks all these information