<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
<title>Christian Cantrell</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/" />
<modified>2009-11-20T18:01:56Z</modified>
<tagline>Adobe AIR Application Developer, Product Manager, and Evangelist</tagline>
<id>tag:blogs.adobe.com,2009:/cantrell/333</id>
<generator url="http://www.movabletype.org/" version="4.261">Movable Type</generator>
<copyright>Copyright (c) 2009, cantrell</copyright>

<entry>
<title>Which Storage Devices Are Considered Removable?</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/11/which_storage_devices_are_considered_removable.html" />
<modified>2009-11-20T18:01:56Z</modified>
<issued>2009-11-19T20:56:53Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.44156</id>
<created>2009-11-19T20:56:53Z</created>
<summary type="text/plain">How the new storage volume detection APIs work, and how AIR determines whether a volume is considered removable or not.</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>AIR 2 has the ability to detect the mounting and un-mounting of storage volumes like flash drives, hard drives, some types of digital cameras, etc. (to see this in action, see <a href="http://blogs.adobe.com/cantrell/archives/2009/11/storage_volume_detection_api_demo.html">A Demonstration of the New Storage Volume APIs in AIR 2</a>). This feature basically piggybacks off of the operating system's detection of storage devices. In other words, if the OS thinks something is a mass storage device, AIR will also recognize it as such and throw a <code>StorageVolumeChangeEvent</code>. If the OS does not recognize the device as a storage volume, AIR will not react to it. (Note: it is possible to detect and communicate with any type of peripheral in AIR 2 using external processes launched with the new <a href="http://www.adobe.com/devnet/air/flash/quickstart/interacting_with_native_process.html">NativeProcess API</a>; the <code>StorageVolume</code> APIs are only for, well, storage volumes.)</p>]]>
<![CDATA[<p>The <code>StorageVolumeChangeEvent</code> which is thrown in response to a volume being mounted contains a reference to the <code>StorageVolume</code> object representing the volume that was just mounted. The <code>StorageVolume</code> object contains several interesting properties:</p>

<ul>
  <li><code>name</code></li>
  <li><code>drive</code></li>
  <li><code>fileSystemType</code></li>
  <li><code>isRemovable</code></li>
  <li><code>isWritable</code></li>
  <li><code>rootDirectory</code></li>
</ul>

<p>The <code>isRemovable</code> property indicates whether the operating system considers the media it just detected as removable or not. Initially, this seemed pretty straightforward to me, but as I began playing with the APIs, I found I didn't always agree with the OS's assessment. For instance, my portable 500GB Western Digital USB hard drive is not considered removable even though I plug it in and remove it all the time (note that this is the operating system's decision -- not AIR's). And, for some reason, my Time Capsule is removable, but other network drives are not. Strange.</p>

<p>The table below shows the results of the testing I've done so far:</p>

<table width="100%" border="1" cellpadding="2">
    <tr align="center">
        <th rowspan="2">Type of Device</th>
        <th colspan="3"><code>StorageVolume.isRemovable</code></th>
    </tr>
    <tr align="center">
        <th>OS X</th>
        <th>Windows</th>
        <th>Linux</th>
    </tr>
    <tr align="center">
    	<td align="left">CD/DVD (fixed)</td>
        <td>true</td>
        <td>true</td>
        <td>true</td>
    </tr>
    <tr align="center">
    	<td align="left">USB Flash Drive</td>
        <td>true</td>
        <td>true</td>
        <td>true</td>
    </tr>
    <tr align="center">
    	<td align="left">USB Hard Drive</td>
        <td>false</td>
        <td>false</td>
        <td>true</td>
    </tr>
    <tr align="center">
    	<td align="left">FireWire Hard Drive</td>
        <td>?</td>
        <td>?</td>
        <td>?</td>
    </tr>
    <tr align="center">
    	<td align="left">Shared Volume</td>
        <td>true</td>
        <td>?</td>
        <td>n/a<sup>1</sup></td>
    </tr>
    <tr align="center">
    	<td align="left">Network Drive</td>
        <td>false</td>
        <td>false</td>
        <td>n/a<sup>2</sup></td>
    </tr>
    <tr align="center">
    	<td align="left">Storage Card Reader (empty)</td>
        <td>n/a<sup>3</sup></td>
        <td>false</td>
        <td>n/a<sup>3</sup></td>
    </tr>
    <tr align="center">
    	<td align="left">Storage Card Reader (with SD/CF card)</td>
        <td>true</td>
        <td>true</td>
        <td>true</td>
    </tr>
</table>

<p><sup>1</sup> Linux doesn't have a concept of a shared volume.</p>

<p><sup>2</sup> No StorageVolumeChangeEvent is thrown when drives are mounted using SMB on Linux.</p>

<p><sup>3</sup> Windows considers empty card readers to be non-removable devices while OS X and Linux do not react to them at all.</p>

<p>I'm hoping to get other developers to try out whatever devices they have lying around on whichever OS they favor so we can make this chart as comprehensive as possible. If you have the opportunity to provide data for any of the missing cells, or if you have devices that aren't listed, please leave the information in the comments and I'll update the table. Over time, this should become a very valuable resource for developers googling for answers.</p>

<p>If you need a quick way to test, I threw together <a href="/cantrell/files/StorageVolumeTest.air">this little utility</a> called StorageVolumeTest.air (<a href="/cantrell/files/StorageVolumeTest.zip">source code</a>) which will report all the StorageVolume properties as volumes are detected and mounted. This app requires the AIR 2 public beta <a href="http://labs.adobe.com/downloads/air2.html">which can be downloaded here</a>.</p>

<p>For more information on the new storage volume detection capabilities of AIR 2, see <a href="http://www.adobe.com/devnet/air/flex/articles/exploring_file_capabilities.html">Exploring the new file capabilities in Adobe AIR 2</a>. Thanks for your help!</p>]]>
</content>
</entry>

<entry>
<title>Demonstration of Gesture APIs in AIR 2</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/11/gesture_api_demo.html" />
<modified>2009-11-18T16:23:36Z</modified>
<issued>2009-11-18T14:50:09Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.44133</id>
<created>2009-11-18T14:50:09Z</created>
<summary type="text/plain">I don&apos;t have a multi-touch computer (yet), but I do have a MacBook with a multi-touch trackpad which means I can write AIR 2 applications that incorporate gestures. The video below demonstrates a few of the new gesture APIs in AIR 2...</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>Apollo</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>I don't have a multi-touch computer (yet), but I do have a MacBook with a multi-touch trackpad which means I can write AIR 2 applications that incorporate gestures. The video below demonstrates a few of the new gesture APIs in AIR 2:</p>

<div align="center"><object width="480" height="385"><param name="movie" value="http://www.youtube.com/v/aka-thuRf5k&hl=en_US&fs=1&color1=0x5d1719&color2=0xcd311b"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/aka-thuRf5k&hl=en_US&fs=1&color1=0x5d1719&color2=0xcd311b" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed></object></div>

<p>The code below shows how to indicate that you want to receive gesture events (as opposed to multi-touch, or no touch events at all), and registers for zoom, rotate, and pan gesture events (the <code>watch</code> variable refers to a Sprite which contains the bitmap image of the watch):</p>

<code><pre>Multitouch.inputMode = MultitouchInputMode.GESTURE;
watch.addEventListener(TransformGestureEvent.GESTURE_ZOOM, onZoom);
watch.addEventListener(TransformGestureEvent.GESTURE_ROTATE, onRotate);
watch.addEventListener(TransformGestureEvent.GESTURE_PAN, onPan);</pre></code>

<p>The three functions below show responding to each of the gesture events:</p>

<code><pre>private function onZoom(e:TransformGestureEvent):void
{
    var watch:Sprite = e.target as Sprite;
    watch.scaleX *= e.scaleX;
    watch.scaleY *= e.scaleY;
}

private function onRotate(e:TransformGestureEvent):void
{
    var watch:Sprite = e.target as Sprite;
    watch.rotation += e.rotation;
}

private function onPan(e:TransformGestureEvent):void
{
    var watch:Sprite = e.target as Sprite;
    var watchBitmap:Bitmap = watch.getChildAt(0) as Bitmap;
    watchBitmap.x += e.offsetX;
    watchBitmap.y += e.offsetY;
}</pre></code>
  
<p>For much more information on how multi-touch and gestures work in both AIR 2 and Flash Player 10.1 (including OS and hardware support, which gestures are supported where, and a thorough review of the APIs), and to download sample code, see <a href="http://www.adobe.com/devnet/flash/articles/multitouch_gestures.html">Multi-touch and Gesture Support on the Flash Platform</a>. Or, if you just want to see the code for this sample, you can <a href="/cantrell/files/zoomexample.zip">download it here</a>.</p>]]>

</content>
</entry>

<entry>
<title>AIR 2 Public Beta Resources</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/11/air_2_public_beta_resources.html" />
<modified>2009-11-17T05:09:04Z</modified>
<issued>2009-11-17T04:51:48Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.44096</id>
<created>2009-11-17T04:51:48Z</created>
<summary type="text/plain">The AIR 2 public beta is now live! Below are all the links you&apos;ll need to learn more and get started...</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>Apollo</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>The AIR 2 public beta is now live! Below are all the links you'll need to learn more and get started:</p>
	
<h4>Adobe Labs</h4>
<ul>
    <li><a href="http://labs.adobe.com/technologies/air2/">AIR 2 Beta on Adobe Labs</a></li>
    <li><a href="http://labs.adobe.com/downloads/air2.html">Download the AIR 2 Public Beta</a></li>
    <li><a href="http://labs.adobe.com/technologies/air2/samples/">AIR 2 Beta Sample Applications</a></li>
    <li><a href="http://labs.adobe.com/wiki/index.php/AIR_2:Release_Notes">AIR 2 Beta Release Notes</a></li>
    <li><a href="http://labs.adobe.com/wiki/index.php/AIR_2:Developer_FAQ">AIR 2 Developer FAQ</a></li>
</ul>

<h4>Adobe Developer Center</h4>
<ul>
    <li><a href="http://www.adobe.com/devnet/logged_in/rchristensen_air_2.html">Introducing Adobe AIR 2 Beta</a></li>
    <li><a href="http://www.adobe.com/devnet/air/flash/quickstart/interacting_with_native_process.html">Interacting with a Native Process</a></li>
    <li><a href="http://www.adobe.com/devnet/flash/articles/multitouch_gestures.html">Multi-touch and Gesture Support on the Flash Platform</a></li>
    <li><a href="http://www.adobe.com/devnet/air/flex/articles/exploring_file_capabilities.html">Exploring the New File Capabilities in Adobe AIR 2</a></li>
    <li><a href="http://www.adobe.com/devnet/air/flex/articles/using_file_promises.html">Drag-and-drop Support of Remote Files in Adobe AIR 2</a></li>
    <li><a href="http://www.adobe.com/devnet/air/flex/articles/creating_socket_server.html">Creating a Socket Server in Adobe AIR 2</a></li>
    <li><a href="http://www.adobe.com/devnet/air/flex/articles/using_mic_api.html">Using the Microphone Capabilities in Adobe AIR 2</a></li>
    <li><a href="http://www.adobe.com/devnet/air/flex/articles/creating_accessible_apps_in_air_and_flex.html">Creating Accessible Applications in Adobe AIR and Flex</a></li>
</ul>

<h4>Adobe TV</h4>
<ul>
    <li><a href="http://tv.adobe.com/watch/adc-presents/preview-desktop-integration-in-adobe-air-2/">Desktop Integration in Adobe AIR 2 (video)</a></li>
    <li><a href="http://tv.adobe.com/watch/adc-presents/preview-command-line-integration-in-adobe-air-2/">Command Line Integration in Adobe AIR 2 (video)</a></li>
    <li><a href="http://tv.adobe.com/watch/flash-platform-in-action/kevin-lynch-demos-adobe-air-2-features/">Kevin Lynch Demos AIR 2 Features at MAX (video)</a></li>
    <li><a href="http://tv.adobe.com/watch/max-2009-develop/multitouch-demos-in-adobe-air-2-and-flash-player-101">Multi-touch Demos in Adobe AIR 2 and Flash Player 10.1 (video)</a></li>
    <li><a href="http://tv.adobe.com/watch/max-2009-develop/whats-coming-in-adobe-air-2-">What's Coming in Adobe AIR 2 (MAX presentation video)</a></li>
    <li><a href="http://tv.adobe.com/watch/max-2009-develop/building-accessible-flex-and-adobe-air-applications">Building Accessible Flex and Adobe AIR Applications (MAX presentation video)</a></li>
</ul>

<h4>This Blog</h4>
<ul>
    <li><a href="http://blogs.adobe.com/cantrell/archives/2009/10/everything_new_in_air_2.html">Exhaustive List of Everything That's New in AIR 2</a></li>
    <li><a href="http://blogs.adobe.com/cantrell/archives/2009/10/global_error_handling_in_air_20.html">Global Error Handling in AIR 2.0 and Flash 10.1</a></li>
    <li><a href="http://blogs.adobe.com/cantrell/archives/2009/10/a_screencast_showing_file_promises.html">A Screencast Explaining and Demoing File Promises (video)</a></li>
    <li><a href="http://blogs.adobe.com/cantrell/archives/2009/11/server_socket_demo_in_air_2.html">A Demonstration of the ServerSocket API in AIR 2 (video)</a></li>
    <li><a href="http://blogs.adobe.com/cantrell/archives/2009/11/storage_volume_detection_api_demo.html">A Demonstration of the New Storage Volume APIs in AIR 2 (video)</a></li>
    <li><a href="http://blogs.adobe.com/cantrell/archives/2009/11/demo_of_nativeprocess_apis.html">A Demonstration of the NativeProcess APIs in AIR 2 (video)</a></li>
    <li><a href="http://blogs.adobe.com/cantrell/archives/2009/11/a_demonstration_of_encrypted_sockets.html">A Demonstration of Encrypted Socket Support in AIR 2 (video)</a></li>
    <li><a href="http://blogs.adobe.com/cantrell/archives/2009/10/introducing_urlrequest_idletimeout.html">New AIR 2 API: URLRequest.idleTimeout</a></li>
</ul>

<h4>Community</h4>
<ul>
    <li><a href="http://search.twitter.com/search?q=%23air">#air on Twitter</a></li>
    <li><a href="http://feeds.adobe.com/index.cfm?query=bySmartCategory&smartCategoryId=28&smartCategoryName=AIR&smartCategoryKey=F2DFD9E0-FBB6-4C2D-2AFE6AFD941FDDB1">AIR Smart Category on Adobe Feeds</a></li>
    <li><a href="http://blogsearch.google.com/blogsearch?hl=en&ie=UTF-8&q=adobe+air&btnG=Search+Blogs">Google Blog Search for "Adobe AIR"</a></li>
    <li><a href="http://forums.adobe.com/community/labs/air2/">Labs Forum for AIR 2</a></li>
    <li><a href="http://groups.google.com/group/air-tight/topics">Adobe AIR-Tight Google Group</a></li>
    <li><a href="http://forums.adobe.com/community/air/air_general_discussion?view=discussions">Adobe AIR Support Forum</a></li>
    <li><a href="https://www.adobe.com/cfusion/mmform/index.cfm?name=wishform&product=102">Feature Request and Bug Report Form</a></li>
</ul>]]>

</content>
</entry>

<entry>
<title>A Demonstration of Encrypted Socket Support in AIR 2</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/11/a_demonstration_of_encrypted_sockets.html" />
<modified>2009-11-13T15:31:45Z</modified>
<issued>2009-11-13T15:20:24Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.44065</id>
<created>2009-11-13T15:20:24Z</created>
<summary type="text/plain">I&apos;ve been wanting to write my own email notifier in AIR for a long time, but without support for encrypted sockets, it wasn&apos;t easy to do. But now that AIR 2 added the new SecureSocket class, I was able to write a pretty functional email notifier in just a couple of days...</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>I've been wanting to write my own email notifier in AIR for a long time, but without support for encrypted sockets, it wasn't easy to do. But now that AIR 2 added the new <code>SecureSocket</code> class, I was able to write a pretty functional email notifier in just a couple of days:</p>]]>
<![CDATA[<div align="center"><object width="640" height="505"><param name="movie" value="http://www.youtube.com/v/eVsc_r3XCJw&hl=en_US&fs=1&color1=0x5d1719&color2=0xcd311b"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/eVsc_r3XCJw&hl=en_US&fs=1&color1=0x5d1719&color2=0xcd311b" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"></embed></object></div>

<p>The new <code>SecureSocket</code> class extends <code>Socket</code>, so MenuMail can use either encrypted or non-encrypted sockets without really having to know the difference:</p>

<code><pre>this.socket = (this.secure) ? new SecureSocket() : new Socket();</pre></code>

<p>The MenuMail application, and all the code for MenuMail, will be available on Adobe Labs after the AIR 2 public beta launch (which is very close!).</p></body>]]>
</content>
</entry>

<entry>
<title>A Demonstration of the NativeProcess APIs in AIR 2</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/11/demo_of_nativeprocess_apis.html" />
<modified>2009-11-20T15:11:09Z</modified>
<issued>2009-11-12T15:25:33Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.44047</id>
<created>2009-11-12T15:25:33Z</created>
<summary type="text/plain">SearchCentral uses the new NativeProcess APIs in AIR 2 in order to integrate with Spotlight and provide very fast local file system search. Here&apos;s a demo...</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>SearchCentral uses the new NativeProcess APIs in AIR 2 in order to integrate with Spotlight and provide very fast local file system search. Here's a demo:</p>]]>
<![CDATA[<div align="center"><object width="640" height="505"><param name="movie" value="http://www.youtube.com/v/GbqmsJgeggw&hl=en_US&fs=1&color1=0x5d1719&color2=0xcd311b"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/GbqmsJgeggw&hl=en_US&fs=1&color1=0x5d1719&color2=0xcd311b" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"></embed></object></div>

<p>The NativeProcess APIs are very simple to use. The code below invokes the <code>mdfind</code> command on OS X, and sets up an event listener to read the results from standard out:</p>

<code>
<pre>private function onSearch():void
{
    var npInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
    npInfo.executable = this.mdfindFile; // A reference to the mdfind command
    var args:Vector.&lt;String&gt; = new Vector.&lt;String&gt;;
    args.push(&quot;-interpret&quot;);
    args.push(this.searchTerm.text);
    npInfo.arguments = args;
    this.processBuffer = new ByteArray();
    this.nativeProcess = new NativeProcess();
    this.nativeProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onStandardOutputData);
    this.nativeProcess.addEventListener(NativeProcessExitEvent.EXIT, onStandardOutputExit);
    this.setStatus(&quot;Searching for &quot; + this.searchTerm.text + &quot;...&quot;, true);
    this.nativeProcess.start(npInfo);
}</pre></code>

<p>The code below shows buffering the data from standard out:</p>

<code><pre>private function onStandardOutputData(e:ProgressEvent):void
{
    this.nativeProcess.standardOutput.readBytes(this.processBuffer, this.processBuffer.length);
}</pre></code>

<p>And finally, the code blow is an abbreviated version of the function that parses the data from standard out and puts it into the data grid:</p>

<pre><code>private function onStandardOutputExit(e:Event):void
{
    var output:String = new String(this.processBuffer);
    var outputArray:Array = output.split(&quot;\n&quot;);
    var data:Array = new Array();
    for each(var path:String in outputArray)
    {
        var f:File = new File(path);
        if (!f.exists) continue;
        var o:Object = new Object();
        if (f.isDirectory)
        {
            o.name = &quot;/&quot; + f.name;
        }
        else
        {
            o.name = f.name;
        }
        o.type = f.extension;
        o.lastModified = f.modificationDate;
        o.path = f.nativePath;
        data.push(o);
    }
    var dp:ArrayCollection = new ArrayCollection(data);
    this.fileGrid.dataProvider = dp;
    this.setStatus(dp.length + &quot; items found&quot;);
}</code></pre>

<p><strike>The code for SearchCentral will be available on on <a href="http://labs.adobe.com/">Adobe Labs</a> as soon as the AIR 2 Beta is public (very soon!)</strike>. The code for SearchCentral is <a href="http://code.google.com/p/searchcentral/">now available on Google Code</a>. If you have any questions, drop them in the comments below.</p>]]>
</content>
</entry>

<entry>
<title>A Demonstration of the New Storage Volume APIs in AIR 2</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/11/storage_volume_detection_api_demo.html" />
<modified>2009-11-11T14:55:10Z</modified>
<issued>2009-11-11T14:52:30Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.44035</id>
<created>2009-11-11T14:52:30Z</created>
<summary type="text/plain">A screencast of an application demonstrating the new storage volume detection APIs in AIR 2 (along with some code snippets).</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>Below is a screencast of an application I wrote called <a href="http://code.google.com/p/filetile/">FileTile</a> in order to validate the new storage volume APIs in AIR 2:</p>]]>
<![CDATA[<div align="center"><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/EEGog5buzcs&hl=en&fs=1&color1=0x5d1719&color2=0xcd311b"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/EEGog5buzcs&hl=en&fs=1&color1=0x5d1719&color2=0xcd311b" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></div>

<p>Detecting the mounting and unmounting of a storage volume in AIR 2 is very easy. The code below shows using the new StorageVolumeInfo class to register for mount and unmount events:</p>
<code><pre>StorageVolumeInfo.storageVolumeInfo.addEventListener(StorageVolumeChangeEvent.STORAGE_VOLUME_MOUNT, onVolumeMount);
StorageVolumeInfo.storageVolumeInfo.addEventListener(StorageVolumeChangeEvent.STORAGE_VOLUME_UNMOUNT, onVolumeUnmount);</pre></code>

<p>Below are the two functions that react to the mounting and unmounting of storage volumes:</p>

<code><pre>private function onVolumeMount(e:StorageVolumeChangeEvent):void
{
    if (e.storageVolume.isRemovable)
    {
        this.nativeWindow.activate();
        this.volumeName.text = e.storageVolume.name;
        this.targetVolume = e.storageVolume.rootDirectory;
        this.currentVolumeNativePath = this.targetVolume.nativePath;
        this.start();
    }
}

private function onVolumeUnmount(e:StorageVolumeChangeEvent):void
{
    if (this.currentVolumeNativePath == e.rootDirectory.nativePath)
    {
        this.reset();
        this.mainView.selectedChild = instructionBox;
    }
}</pre></code>

<p>FileTile is a free, open-source application. The code can be <a href="http://code.google.com/p/filetile/">downloaded from Google Code</a>.</p>]]>
</content>
</entry>

<entry>
<title>A Demonstration of the ServerSocket API in AIR 2</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/11/server_socket_demo_in_air_2.html" />
<modified>2009-11-04T16:29:19Z</modified>
<issued>2009-11-04T16:20:56Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43918</id>
<created>2009-11-04T16:20:56Z</created>
<summary type="text/plain">In order to validate the new ServerSocket APIs in AIR 2, I wrote an HTTP proxy server in ActionScript. Check out the screencast, and if you&apos;re interested, download the code.</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>In order to validate the new <code>ServerSocket</code> APIs in AIR 2, I wrote an application called <a href="http://code.google.com/p/httpeek/">HTTPeek</a>. HTTPeek is a proxy server that sits between your browser and the network, and can show you HTTP request and response headers. It can handle compressed content, chunked content, binary content, etc. Check out the video below to see it in action:</p>]]>
<![CDATA[<div align="center"><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/tUGGA1Ibzq4&hl=en&fs=1&color1=0x5d1719&color2=0xcd311b"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/tUGGA1Ibzq4&hl=en&fs=1&color1=0x5d1719&color2=0xcd311b" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></div>

<p>Most of the HTTPeek code is dedicated to implementing just enough of the HTTP protocol to be an effective proxy, but the socket portion of the code is actually not all that complex. And the creation of the <code>ServerSocket</code> itself is very simple. The function below gets called when the user clicks on the &quot;Listen&quot; button:</p>

<code><pre>private function onListen():void
{
    this.sockets = new Array();
    this.server = new ServerSocket();
    this.server.addEventListener(Event.CONNECT, onConnect);
    try
    {
        this.server.bind(Number(this.portNumber.text), String(this.interfaces.value));
        this.server.listen();
        this.listenButton.label = &quot;Close&quot;;
    }
    catch (e:Error)
    {
        Alert.show(e.message, &quot;Error&quot;, Alert.OK);
        return;
    }
    this.debugButton.enabled = true;
}</pre></code>

<p>HTTPeek is open-source and hosted <a href="http://code.google.com/p/httpeek/">here on Google Code</a>. Feel free to check out the source to see how it works.</p>]]>
</content>
</entry>

<entry>
<title>Some Interesting AIR Marketplace Statistics</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/11/air_marketplace_stats_part_1.html" />
<modified>2009-11-03T17:33:42Z</modified>
<issued>2009-11-03T15:54:56Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43895</id>
<created>2009-11-03T15:54:56Z</created>
<summary type="text/plain">A little over a year ago, I wrote a Python script to screen scrape the entire Adobe AIR Marketplace, download all the listed AIR applications, crack open the installers, and extract some statistics. My primary interest was how many HTML-based AIR applications were listed versus SWF-based applications, but I recorded some other interesting stats, as well.</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>Apollo</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>A little over a year ago, I wrote a Python script to screen scrape the entire <a href="http://www.adobe.com/cfusion/marketplace/index.cfm?event=marketplace.home&marketplaceid=1">Adobe AIR Marketplace</a>, download all the listed AIR applications, crack open the installers, and extract some statistics. My primary interest was how many HTML-based AIR applications were listed versus SWF-based applications, but I recorded some other interesting stats, as well.</p>
<p>I ran the script again the other day (after some updating since screen scraping scripts always break), and here's what I found:</p>]]>
<![CDATA[<table width="100%" border="1" cellpadding="2">
    	<tr>
        	<th align="center">Statistic</th>
            <th align="center">Data</th>
            <th align="center">Description</th>
        </tr>
        <tr>
        	<td>Total AIR apps on the Marketplace</td>
          <td align="right">724</td>
            <td>Total number of AIR applications listed on the Adobe AIR Marketplace as of 10/29/2009.</td>
        </tr>
        <tr>
        	<td>Total testable apps</td>
          <td align="right">536</td>
          <td>
            	The total number of applications I was able to download and test.
                121 applications don't have direct links to their AIR files on the marketplace,
                and the rest couldn't be tested because of 404s or network timeouts.
            </td>
        </tr>
        <tr>
        	<td>Total SWF-based AIR apps</td>
          <td align="right">443 (82.6%)</td>
            <td>Total number of applications that use a SWF as their main content. There is no distinction between Flash and Flex apps.</td>
        </tr>
        <tr>
        	<td>Total confirmed AS2 apps</td>
          <td align="right">2</td>
            <td>Total number of SWF-based applications that use ActionScript 2 rather than ActionScript 3. (I'd be alarmed if this were much higher.)</td>
        </tr>
        <tr>
        	<td>Total HTML-based AIR apps</td>
          <td align="right">93 (17.4%)</td>
            <td>Total number of applications that use an HTML file as their main content.</td>
        </tr>
</table>

<p>Some things to keep in mind about this data:</p>

<ul>
	<li>I was only able to test applications that were listed on the Adobe AIR Marketplace. These stats don't include the (hundreds? thousands?) of AIR applications not listed.</li>
    <li>I was only able to test applications that have direct links to their AIR files on the Marketplace. 121 applications only have links to their sites rather than links to their AIR apps, so that's a fair percentage of missing data (16.7%). Maybe I'll fix that limitation in the future.</li>
    <li>I don't have any statistic on "hybrid" apps, or applications that load a SWF as their main content, but then load HTML/JS into an HTMLLoader (or the opposite -- HTML apps that load Flash content). I've personally written several applications that combine Flash/ActionScript/HTML/JS, and I suspect a substantial portion of the SWF-based applications on the Marketplace are hybrids, as well.</li>
</ul>

<p>I plan on updating the script to look for any HTML/JS files in the application bundle in order to give an indication of the number of hybrid applications out there.  I'll post the results when I have them.</p>

<p>So my questions for you guys are:</p>

<ul>
	<li>Any other statistics you'd like to see?</li>
    <li>Anything we can do for the HTML/JS/Ajax developers out there to get more HTML-based apps?</li>
    <li>Will any of the <a href="http://blogs.adobe.com/cantrell/archives/2009/10/everything_new_in_air_2.html">new HTML features in AIR 2</a> give HTML devs what they need to build on AIR?</li>
</ul>]]>
</content>
</entry>

<entry>
<title>A Screencast Explaining and Demoing File Promises</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/10/a_screencast_showing_file_promises.html" />
<modified>2009-10-30T15:02:46Z</modified>
<issued>2009-10-30T13:11:47Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43843</id>
<created>2009-10-30T13:11:47Z</created>
<summary type="text/plain">File promises are kind of a difficult concept to describe, so I decided to explain them using a video. Hopefully this clarifies what file promises are, and why it&apos;s such a cool new feature of AIR 2.0...</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>File promises are kind of a difficult concept to describe, so I decided to explain them using a video. Hopefully this clarifies what file promises are, and why it's such a cool new feature of AIR 2.0:</p>]]>
<![CDATA[<div align="center"><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/znXCkzfMHr4&hl=en&fs=1&color1=0x5d1719&color2=0xcd311b"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/znXCkzfMHr4&hl=en&fs=1&color1=0x5d1719&color2=0xcd311b" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></div>

<p>Here's the code that creates a <code>URLFilePromise</code> for every file to be downloaded and puts them on the clipboard. But first, some code context:</p>

<ul>
  <li><code>onDragStart</code> is the event handler that gets called when the user starts dragging items from the list of objects.</li>
  <li><code>bucketList</code> is the ComboBox of bucket names.</li>
  <li><code>objectList</code> is the DataGrid of objects.</li>
  <li>The function <code>s3.getTemporaryObjectURL(...)</code> generates a temporary public URL that points to the specified object. It's the URL that the <code>URLFilePromise</code> will use to access the file.</li>
</ul>

<code><pre>private function onDragStart(e:DragEvent):void
{
    if (bucketList.selectedIndex == 0 || objectList.selectedItems == null) return;
    var c:Clipboard = new Clipboard();
    var items:Array = objectList.selectedItems;
    this.filePromises = new Array();
    for each (var item:Object in items)
    {
        var fp:URLFilePromise = new URLFilePromise();
        var req:URLRequest = new URLRequest(s3.getTemporaryObjectURL(bucketList.selectedItem.name, item.key, 60));
        fp.request = req;
        fp.relativePath = item.key;
        this.filePromises.push(fp);
    }
    c.setData(ClipboardFormats.FILE_PROMISE_LIST_FORMAT, this.filePromises);
    NativeDragManager.doDrag(objectList, c, null, null, null);
}</pre></code>

<p>Below is the function that gets called when the drop is complete. It's responsible for opening the <code>ProgressWindow</code> component and passing it the array of <code>URLFilePromise</code> objects which the <code>ProgressWindow</code> component hooks into in order to receive progress events.</p>

<pre><code>private function onDragComplete(e:DragEvent):void
{
    var progressWindow:ProgressWindow = new ProgressWindow();
    progressWindow.open(false);
    progressWindow.setFilePromises(this.filePromises);
}</code></pre>

<p>The code for S3E is open source and <a href="http://code.google.com/p/s3e/">available on Google Code</a>.]]>
</content>
</entry>

<entry>
<title>Exhaustive List of Everything That&apos;s New in AIR 2.0</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/10/everything_new_in_air_2.html" />
<modified>2009-11-06T21:23:55Z</modified>
<issued>2009-10-29T17:44:46Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43830</id>
<created>2009-10-29T17:44:46Z</created>
<summary type="text/plain">This morning, I was going to start making videos demoing some of the new features in AIR 2.0 when I realized that I should probably start with a list of everything that&apos;s new. Below is an exhaustive list of everything that we&apos;re planning on including in AIR 2.0.</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>Apollo</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>This morning, I was going to start making videos demoing some of the new features in AIR 2.0 when I realized that I should probably start with a list of everything that's new. Below is an exhaustive list of everything that we're <em>planning</em> on including in AIR 2.0. I use the word <em>planning</em> because even at this relatively late stage, things can change. Consider yourself warned.</p>
<p>Feel free to post questions in the comments.</p>]]>
<![CDATA[<ul>
  <li><strong>Multi-touch</strong>: Touch events are similar to mouse events, but on multi-touch enabled devices, you can track multiple touch points simultaneously.
    <ul>
      <li>Multi-touch support:
        <ul>
          <li>Windows 7 and beyond.</li>
          <li>Requires multi-touch enabled hardware (obviously).</li>
        </ul>
      </li>
    </ul>
  </li>
  <li><strong>Gestures</strong>: Applications can listen for multi-touch events, <em>or</em> gesture events (not both at the same time). Gestures are the synthesis of multi-touch events into a single event.
    <ul>
      <li>Gesture support:
        <ul>
          <li>Windows 7 and beyond.</li>
          <li>Macs running 10.6 and beyond with multi-touch trackpads.</li>
        </ul>
      </li>
      <li>Type of gestures we support:
        <ul>
          <li><code>GESTURE_TWO_FINGER_TAP</code> (tapping with two fingers)</li>
        </ul>
        <ul>
          <li><code>GESTURE_PRESS_AND_TAP</code> (holding one finger down, then tapping with another -- convention on some Windows devices for bringing up context menus)</li>
        </ul>
        <ul>
          <li><code>GESTURE_PAN</code></li>
          <li><code>GESTURE_ROTATE</code></li>
          <li><code>GESTURE_SWIPE</code></li>
          <li><code>GESTURE_ZOOM</code></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><strong>Open Files With  Default Application</strong>: The new <code>File.openWithDefaultApplication</code> API lets you open a file instance with whatever application it happens to be associated with. This is a good cross-platform way to integrate with other applications since you don't have to know what applications are installed, or where.</li>
  <li><strong>OS Download Security Dialog</strong>: The new <code>File.downloaded</code> property lets you indicate that a file was downloaded from the network and the OS should prompt the user with a confirmation dialog before opening it.
    <ul>
      <li>Supported platforms:
        <ul>
          <li>Windows XP SP2 and later.</li>
          <li>Mac OS 10.5 (Leopard) and later.</li>
          <li>(No Linux support because Linux doesn't have this concept.)</li>
        </ul>
      </li>
    </ul>
  </li>
  <li><strong>Storage Volume Detection</strong>: The new storage volume APIs let you listen for the mounting and unmounting of storage volumes, list accessible volumes, and get information on storage volumes such as the file system type, whether it's removable, whether it's writable, the drive letter, and the drive label.</li>
  <li><strong>Native Processes</strong>: Launch and communicate with native &quot;out-of-band&quot; processes. Bundle your own native executables, or call executables that you know are already on the machine. This feature requires that your application be installed with a native installer rather than though a .AIR file (we provide tools for building native installers).
    <ul>
      <li>Types of installers: 
        <ul>
          <li>OS X: DMG</li>
          <li>Windows: EXE</li>
          <li>Linux: Debian and Red Hat Package Manager</li>
        </ul>
      </li>
    </ul>
  </li>
  <li><strong>File Promises</strong>: File promises let users drag and drop files that either don't exist yet (because you want to generate them on-demand), or that exist on a remote server. We provide an implementation that will automatically download remote files for you and save them to the drop location, and we provide an interface for you to implement if you want to generate files on-demand.</li>
  <li><strong>Server Sockets</strong>: The new <code>ServerSocket</code> API let you listen on a socket so that you can implement inter-application communication, P2P applications, advanced network protocols like FTP, etc.</li>
  <li><strong>Datagram Sockets</strong>: In addition to TCP sockets, AIR 2.0 will now support UDP sockets.</li>
  <li><strong>Encrypted Sockets</strong>: Sockets can now be encrypted using TLS/SSL.</li>
  <li><strong>IPv6 Support</strong>.</li>
  <li><strong>Access to Low-Level Network Information</strong>: The <code>NetworkInfo</code> object lets you enumerate network interfaces on the machine and get access to properties such as whether they are active, their IP address, and their display name.</li>
  <li><strong>Bind Sockets to Specific Network Interfaces</strong>: The new <code>Socket.bind</code> function can be used to bind to a specific network interface (discovered through the <code>NetworkInfo</code> API) rather than always binding to the default. This can allow you to pick the best network connection for your particular application.</li>
  <li><strong>DNS Resolution</strong>: Use <code>DNSResolver</code> to look up the following types of resource records:
    <ul>
      <li>ARecord (IPv4 address for a host)</li>
      <li>AAAARecord (IPv6 address for a host)</li>
      <li>MXRecord: mail exchange record for a host</li>
      <li>PTRRecord: host name for an IP address</li>
      <li>SRVRecord: service record for a service</li>
    </ul>
  </li>
  <li><strong>Configurable HTTP Idle Timeout</strong>. <code>URLRequest.idleTimeout</code> and <code>URLRequestDefaults.idleTimeout</code> let you specify the amount of time (in milliseconds) that a connection will remain open before it receives any data. This is useful for things like <a href="http://en.wikipedia.org/wiki/Push_technology#Long_polling">long polling</a>.</li>
  <li><strong>Local Audio Encoding</strong>: Access audio data directly from the microphone. You used to have to send the data to a server and access it from there, but now you can do it entirely on the client.</li>
  <li><strong>Global Error Handling</strong>: Global error handling lets you handle all uncaught errors (both synchronous errors and asynchronous error events) in one place in your code. (<a href="http://blogs.adobe.com/cantrell/archives/2009/10/global_error_handling_in_air_20.html">More information on Global Error Handling.</a>)</li>
  <li><strong>Accessibility</strong>: AIR 2.0 will have the same level of support for screen readers as Flash. (<a href="http://blogs.adobe.com/koestler/2009/10/adobe_max_and_accessibility_in.html">More information on accessibility in AIR 2.0.</a>)</li>
  <li><strong><code>NativeWindow</code> and <code>Bitmap</code> Size Increases</strong>: The maximum size of a <code>NativeWindow</code> and <code>Bitmap</code> instance used to be 2880x2880. In AIR 2.0, it will be 4095x4095.</li>
  <li><strong>Improved Printing</strong>.
    <ul>
      <li>Vector printing on Mac (already in FP 10).</li>
      <li>Complex transparency support.</li>
    </ul>
  </li>
  <li><strong>Nested Transactions</strong>. SQLite will now support nested transactions.</li>
  <li><strong>Exiting Event on Shutdown</strong>. In AIR 2.0, you will be able to handle the <code>Event.EXITING</code> event when the computer is shutting down so you will have an opportunity to save any unsaved work or data.</li>
  <li><strong>WebKit Upgrades</strong>:
    <ul>
      <li>Nitro JavaScript Engine (SquirrelFish Extreme).</li>
      <li>CSS3 Module support (2D transformations, transitions, animations, etc.).</li>
      <li>Scrollbar styling.</li>
      <li>Break up text across columns.</li>
      <li>Latest Canvas enhancements.</li>
    </ul>
  </li>
  <li><strong>General Optimizations</strong>:
    <ul>
      <li>Lower CPU utilization when idle.</li>
      <li>Lower memory consumption.</li>
    </ul>
  </li>
</ul>
<p>I think that's everything. A beta of AIR 2.0 will be on <a href="http://labs.adobe.com/">Adobe Labs</a> late this year, and we hope to release in the first half of 2010. Questions?</p>]]>
</content>
</entry>

<entry>
<title>Global Error Handling in AIR 2.0 and Flash 10.1</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/10/global_error_handling_in_air_20.html" />
<modified>2009-11-10T15:08:48Z</modified>
<issued>2009-10-28T17:46:31Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43822</id>
<created>2009-10-28T17:46:31Z</created>
<summary type="text/plain">One of the most popular feature announcements during my MAX presentation was global error handling (GEH). GEH lets you handle all uncaught errors (both synchronous errors and asynchronous error events) in one place in your code. Here&apos;s an example of how it will work...</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>One of the most popular feature announcements during my MAX presentation was global error handling (GEH). GEH lets you handle all uncaught errors (both synchronous errors and asynchronous error events) in one place in your code. Here's an example of how it will work:</p>

<code>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:WindowedApplication xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; applicationComplete=&quot;onApplicationComplete();&quot;&gt;

    &lt;mx:Script&gt;
        &lt;![CDATA[
            private function onApplicationComplete():void
            {
                loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
            }

            private function onUncaughtError(e:UncaughtErrorEvent):void
            {
                // Do something with your error.
                if (e.error is Error)
                {
                    var error:Error = e.error as Error;
                    trace(error.errorID, error.name, error.message);
                }
                else
                {
                    var errorEvent:ErrorEvent = e.error as ErrorEvent;
                    trace(errorEvent.errorID);
                }
            }
            
            private function onCauseError(e:MouseEvent):void
            {
                var foo:String = null;
                try
                {
                    trace(foo.length);
                }
                catch (e:TypeError)
                {
                    trace(&quot;This error is caught.&quot;);
                }
                
                // Since this error isn't caught, it will cause the global error handler to fire.
                trace(foo.length);
            }
        ]]&gt;
    &lt;/mx:Script&gt;
      
    &lt;mx:Button label=&quot;Cause TypeError&quot; click=&quot;onCauseError(event);&quot;/&gt;
 
&lt;/mx:WindowedApplication&gt;</pre></code>

<p>Registering for uncaught errors is hugely convenient, but it doesn't entirely excuse developers from handling errors where they're most likely to happen. For instance, you should still always register for things like IOError events and other errors that are likely to happen at some point, and that you can usually recover from. But starting with AIR 2.0 (and FP 10.1), you will also be able to register globally for errors that you weren't able to anticipate, and handle them at least somewhat gracefully.</p>
<p>The big question is what you do once you've caught an unhandled error. That will probably depend on the application. Since it's likely that a function exited without executing all the way through, there's no telling what state your app will be in. The safest thing to do is probably to log the error, show a very contrite dialog box, and then exit the app (after all, if the error had been predictable and easy to recover from, you should have caught it explicitly). You might try sending the error message to your server, including instructions for emailing the log file to a support email address, or if it's an internal application, provide a telephone extension to call for someone to come take a look. It's entirely up to you. We provide the API, you provide the solution.</p>]]>

</content>
</entry>

<entry>
<title>New AIR 2.0 API: URLRequest.idleTimeout</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/10/introducing_urlrequest_idletimeout.html" />
<modified>2009-10-27T18:17:36Z</modified>
<issued>2009-10-27T18:15:53Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43811</id>
<created>2009-10-27T18:15:53Z</created>
<summary type="text/plain">We recently added a new AIR 2.0 API which didn&apos;t make it into my MAX presentation: URLRequest.idleTimeout, and URLRequestDefaults.idleTimeout.</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>We recently added a new AIR 2.0 API which didn't make it into my <a href="http://blogs.adobe.com/cantrell/archives/2009/10/max_2009_presentation.html">MAX presentation</a>:</p>

<ul>
    <li><code>URLRequest.idleTimeout</code></li>
    <li><code>URLRequestDefaults.idleTimeout</code></li>
</ul>
<p>These setters specify the amount of time (in milliseconds) that a connection will remain open before receiving any data. Certainly not as sexy as some of our other new features (native processes, file promises, multi-touch, accessibility, volume detection, socket servers, etc.), but if you're trying to use <a href="http://en.wikipedia.org/wiki/Push_technology#Long_polling">long polling</a>, you'll probably find this API useful.</p>]]>

</content>
</entry>

<entry>
<title>Referencing ActionScript Reserved Words in E4X</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/10/referencing_reserved_words_in_e4x.html" />
<modified>2009-10-26T20:22:13Z</modified>
<issued>2009-10-26T20:19:09Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43795</id>
<created>2009-10-26T20:19:09Z</created>
<summary type="text/plain">How to use E4X to access XML nodes that use reserved ActionScript words.</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>If you have a chunk of XML with <a href="http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3_Flex/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f9b.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7f6e">reserved ActionScript words</a> in it, you won't be able to use E4X syntax like you're used to. For instance, say you need to parse the following XML:</p>
<code><pre>var codeXML:XML =
&lt;code&gt;
    &lt;class name=&quot;Order&quot;&gt;
        &lt;function name=&quot;getId&quot;&gt;
            &lt;access&gt;public&lt;/access&gt;
            &lt;return&gt;Number&lt;/return&gt;
        &lt;/function&gt;
    &lt;/class&gt;
&lt;/code&gt;;</pre></code>

<p>Since this XML is full of reserved words, you won't be able to access nodes like this:</p>

<code><pre>trace(codeXML.class.function.return);</pre></code>

<p>Instead, use bracket syntax like this:</p>

<code><pre>trace(codeXML[&quot;class&quot;].@name);
trace(codeXML[&quot;class&quot;][&quot;function&quot;].access);
trace(codeXML[&quot;class&quot;][&quot;function&quot;][&quot;return&quot;]);</pre></code>]]>

</content>
</entry>

<entry>
<title>Generating Dynamic XML With E4X in ActionScript</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/10/generating_dynamic_xml_with_e4x.html" />
<modified>2009-10-23T16:10:22Z</modified>
<issued>2009-10-23T16:08:52Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43736</id>
<created>2009-10-23T16:08:52Z</created>
<summary type="text/plain">E4X makes working with XML in ActionScript extremely simple. But what if you want to generate the XML dynamically and use variables as attribute values or text nodes?</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>ActionScript</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>E4X makes working with XML in ActionScript extremely simple. Creating some XML is as easy as this:</p>

<code><pre>var inventory:XML =
	&lt;inventory&gt;
		&lt;product id=&quot;111&quot; price=&quot;2999.99&quot;&gt;Laptop&lt;/product&gt;
	&lt;/inventory&gt;;</pre></code>

<p>But what if you want to generate the XML dynamically and use variables as attribute values or text nodes? Just use curly braces like this:</p>

<code><pre>var products:Array = new Array();

products.push({name:&quot;Laptop&quot;, id:111, price:2999.99});
products.push({name:&quot;Mouse&quot;, id:222, price:49.99});
products.push({name:&quot;Phone&quot;, id:333, price:199.99});

var inventory:XML = &lt;inventory/&gt;;

for each (var o:Object in products)
{
	inventory.appendChild(&lt;product id={o.id} price={o.price}&gt;{o.name}&lt;/product&gt;);
}</pre></code>

<p>The resulting XML is exactly what you'd expect:</p>

<code><pre>&lt;inventory&gt;
	&lt;product id=&quot;111&quot; price=&quot;2999.99&quot;&gt;Laptop&lt;/product&gt;
	&lt;product id=&quot;222&quot; price=&quot;49.99&quot;&gt;Mouse&lt;/product&gt;
	&lt;product id=&quot;333&quot; price=&quot;199.99&quot;&gt;Phone&lt;/product&gt;
&lt;/inventory&gt;</pre></code>

<p>Simple and elegant!</p>]]>

</content>
</entry>

<entry>
<title>My MAX Presentation is Online: What&apos;s Coming in AIR 2.0</title>
<link rel="alternate" type="text/html" href="http://blogs.adobe.com/cantrell/archives/2009/10/max_2009_presentation.html" />
<modified>2009-10-09T17:30:18Z</modified>
<issued>2009-10-09T17:15:47Z</issued>
<id>tag:blogs.adobe.com,2009:/cantrell/333.43483</id>
<created>2009-10-09T17:15:47Z</created>
<summary type="text/plain">A video of my MAX 2009 presentation entitled &quot;What&apos;s Coming in AIR 2.0&quot; is now online. You can also download the slides (PDF) separately.</summary>
<author>
<name>cantrell</name>

<email>ccantrel@adobe.com</email>
</author>
<dc:subject>Conferences</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://blogs.adobe.com/cantrell/">
<![CDATA[<p>A video of my MAX 2009 presentation entitled &quot;What's Coming in AIR 2.0&quot; is <a href="http://tv.adobe.com/watch/max-2009-develop/whats-coming-in-adobe-air-2-">now online</a>. You can also <a href="http://blogs.adobe.com/cantrell/files/MAX_2009_Presentation.pdf">download the slides</a> (PDF) separately.</p>

<p>Feel free to leave questions in the comments.</p>]]>

</content>
</entry>

</feed>