<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Marc's Musings &#187; AIR</title>
	<atom:link href="http://www.rogue-development.com/blog2/category/air/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rogue-development.com/blog2</link>
	<description>Comments and thoughts on technology from Marc Hughes</description>
	<lastBuildDate>Wed, 14 Jul 2010 18:09:55 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>OpenID From AIR</title>
		<link>http://www.rogue-development.com/blog2/2008/08/openid-from-air/</link>
		<comments>http://www.rogue-development.com/blog2/2008/08/openid-from-air/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 02:03:35 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Actionscript]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[red5]]></category>

		<guid isPermaLink="false">http://www.rogue-development.com/blog2/2008/08/openid-from-air/</guid>
		<description><![CDATA[I&#8217;ve been working on some web services recently.&#160; There&#8217;s both plain old browser accessed HTML pages plus an AMF interface to them.&#160; One feature of the HTML version is OpenID authentication.&#160; Now OpenID is all fine and dandy for a web application, but we get some problems when we want to use an AIR desktop [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on some web services recently.&#160; There&#8217;s both plain old browser accessed HTML pages plus an AMF interface to them.&#160; One feature of the HTML version is OpenID authentication.&#160; Now OpenID is all fine and dandy for a web application, but we get some problems when we want to use an AIR desktop client to connect and authenticate through OpenID.&#160; </p>
<p>If you&#8217;re not familiar with how OpenID works, here&#8217;s a quick summary.</p>
<ol>
<li>User goes to an application (Usually a web-app)</li>
<li>User types in their OpenID URL to that app</li>
<li>They get forwarded to their OpenID page where they can either grant or deny access.</li>
<li>That page then forwards them back to the original web app with an authentication token set.</li>
</ol>
<p>Obviously, it&#8217;s kind of hard to redirect back to a desktop application.&#160; I was thinking up some wacky work-a-rounds for this but then it hit me. </p>
<p>In the AIR app I can just use the HTML component and point it towards the login form of the web services.&#160; The user can then log in using either username/password or OpenID just like they do on the website.&#160; Now, here&#8217;s the cool part&#8230;&#160; The AIR HTML component shares a network stack with the AIR/Flex NetConnection object.&#160; That means any session/cookies/whatever opened in the HTML component carry through to the remoting calls I want to make from Actionscript. So I can authenticate using a web form, but then consume BlazeDS/LiveCycleDS/AMFPHP/Red5 services using AMF over Netconnection. </p>
<p>I did up a quick proof of concept and it works on both Windows and OSX.&#160; I was able to successfully call a remoting service that requires an authenticated session.&#160; So this was actually a much easier problem to figure out than I had feared. </p>
<p><img src="http://www.rogue-development.com/uploads/adlScreenSnapz014.png" width="600" height="448" /></p>
<p>Now, I&#8217;ll just need to make the web page that loads after a successful login somehow indicate to the AIR app that the user is successfully logged in.&#160; I&#8217;ll probably either use a tiny Flash component that signals over LocalConnection, or I&#8217;ll just make the AIR app watch for when the HTML component gets to a specific URL. I&#8217;m pretty sure I can get this to be a completely seamless experience for the user.</p>
<p>Oh, and as a bonus&#8230; the user can sign up for a new account instead of log into an existing one from &quot;within the app&quot; instead of going to an external website to do that.  </p>
<p><br/>
		      </p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2008/08/openid-from-air/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Printing horrors</title>
		<link>http://www.rogue-development.com/blog2/2008/06/printing-horrors/</link>
		<comments>http://www.rogue-development.com/blog2/2008/06/printing-horrors/#comments</comments>
		<pubDate>Tue, 17 Jun 2008 13:45:32 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.rogue-development.com/blog2/?p=219</guid>
		<description><![CDATA[Printing in a Flash/Flex application can be tricky to get right.  I&#8217;ve been working on a very print-heavy application recently.  We&#8217;ve been having a long standing intermittent bug where we print a large document, but some things on that document that were created through the Flash drawing API wouldn&#8217;t be on the paper.
We added a
var [...]]]></description>
			<content:encoded><![CDATA[<p>Printing in a Flash/Flex application can be tricky to get right.  I&#8217;ve been working on a very <a href="http://www.tomsnyder.com/timelinerxe/">print-heavy application</a> recently.  We&#8217;ve been having a long standing intermittent bug where we print a large document, but some things on that document that were created through the Flash drawing API wouldn&#8217;t be on the paper.</p>
<p>We added a</p>
<p><strong>var options:Object = canvas.prepareToPrint( canvas );</strong></p>
<p>Before the print and a</p>
<p><strong>canvas.finishPrint( options, canvas);</strong></p>
<p>After the print, and it seems to have solved our problem even though the documentation says we shouldn&#8217;t ordinarily need to explicitly call those.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2008/06/printing-horrors/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Xray Viewer updated</title>
		<link>http://www.rogue-development.com/blog2/2008/06/xrayviewer-updated/</link>
		<comments>http://www.rogue-development.com/blog2/2008/06/xrayviewer-updated/#comments</comments>
		<pubDate>Mon, 16 Jun 2008 12:10:15 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[XRay]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.rogue-development.com/blog2/2008/06/xrayviewer-updated/</guid>
		<description><![CDATA[
The XRayViewer has been broken for quite some time.  I had originally done it with an AIR beta, and that has since stopped working.  So there&#8217;s now a newly compiled version just waiting for you to grab.

What is the XRayViewer?
So you may be asking yourself What exactly is the XRayViewer? 
All this little [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://rogue-development.com/images/icon128.png" alt="" width="128" height="128" /></p>
<p>The <a href="http://rogue-development.com/xrayviewer.html">XRayViewer</a> has been broken for quite some time.  I had originally done it with an AIR beta, and that has since stopped working.  So there&#8217;s now a newly compiled version just waiting for you to grab.</p>
<p><img src="http://rogue-development.com/images/xrayviewerscreenshot.png" alt="" width="645" height="518" /></p>
<h2>What is the XRayViewer?</h2>
<p>So you may be asking yourself <em>What exactly is the XRayViewer? </em></p>
<p>All this little app does is host the XRay connector and let you load a local swf. Then it displays the swf with some simple controls to play/stop/advance/back. The big benefit is you can then use <a href="http://www.osflash.org/xray/">XRay</a> (By <a href="http://www.rockonflash.com/">John Grden</a> + Others) to inspect the swf without changing any code around.</p>
<p>There&#8217;s three new (very minor) features in this version:</p>
<ol>
<li>There&#8217;s a button to launch the XRay interface in your default browser.</li>
<li>The path to the loaded swf is displayed in the top toolbar.  (You can copy &amp; paste that into Xray so you don&#8217;t have to navigate as far into the hierarchy)</li>
<li>New logo / icons</li>
</ol>
<h2>Now Open Source!</h2>
<p>The entire project is now licensed under the MIT license.  If you install the application and then right click on it you can &#8220;View Source&#8221; to get the source code for it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2008/06/xrayviewer-updated/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Case Study: Three large Flex/AIR applications</title>
		<link>http://www.rogue-development.com/blog2/2008/05/case-study-three-flex-applications/</link>
		<comments>http://www.rogue-development.com/blog2/2008/05/case-study-three-flex-applications/#comments</comments>
		<pubDate>Mon, 12 May 2008 14:08:45 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Actionscript]]></category>
		<category><![CDATA[AgileAgenda]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.rogue-development.com/blog2/2008/09/06/case-study-three-flex-applications/</guid>
		<description><![CDATA[I&#8217;m currently wrapping up three different fairly large AIR applications developed in different ways. In this blog post I hope to describe the methods used in them, what worked well, and what didn&#8217;t work so well.    Hopefully this will be useful to others starting up projects in the near future.
I&#8217;m going to call these [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently wrapping up three different fairly large AIR applications developed in different ways. In this blog post I hope to describe the methods used in them, what worked well, and what didn&#8217;t work so well.    Hopefully this will be useful to others starting up projects in the near future.</p>
<p>I&#8217;m going to call these &#8220;large&#8221; applications since they go a lot deeper than a simple toy or small experience site that most Flex apps seem to be.  Your definition of &#8220;large&#8221; may differ.  These are full blown desktop applications, not a web-app ported to the desktop or a simple desktop app to augment a web-app.  All three were planned on being desktop apps from the start.  It&#8217;s not a common target audience for AIR, but I believe in the platform for this use.</p>
<h2>A description of the projects</h2>
<p>First, a quick rundown of the apps.</p>
<p><strong>AgileAgenda</strong></p>
<p><img src="http://www.rogue-development.com/blog2/wp-content/uploads/2008/05/agileagendascreensnapz002.png" alt="" width="611" height="444" /></p>
<p>This was my entry for the Adobe AIR Derby so the beginnings were a rapid no-holds barred get-something-out-the-door effort.  There was no good planning that went into this, and no framework used.  This is one of my solo projects.</p>
<p>It&#8217;s since gone through several major UI revisions, with some parts of the application completly changing how they work or look several times over.</p>
<p>It&#8217;s a project scheduling application focusing on allowing users to create a schedule by entering tasks, priorities, and durations while letting the software calculate start/end dates.  Besides that it&#8217;s got some nifty sharing functionality, a PDF export, and a few different ways to look at your data.  I&#8217;ve been <a href="http://www.agileagenda.com/">selling it commercially</a> for while and not doing too bad, take a look and let me know what you think.  I&#8217;m always interested in feedback.</p>
<p> </p>
<p> </p>
<hr /> </p>
<p><strong>AgileTracker</strong></p>
<p><img src="http://www.rogue-development.com/blog2/wp-content/uploads/2008/05/agiletrackerscreensnapz002.png" alt="" width="526" height="405" /></p>
<p>AgileAgenda was doing pretty good, and a time-tracking application to work with it seemed like the next logical step.  I had been looking around and found Parsley and was fairly impressed so I decided to give it a shot. This is also one of my solo projects.</p>
<p>The AgileTracker allows you to subscribe to a schedule in AgileAgenda to get your list of tasks.  Then you can use the built in timer, or manually enter time to keep track of how long you spend on various tasks.  Someday, it&#8217;ll have full read/write capabilities to AgileAgenda for a full round trip exchanging of data.</p>
<p> </p>
<p> </p>
<hr /> </p>
<p><strong>TimeLiner XE </strong></p>
<p><img src="http://www.rogue-development.com/blog2/wp-content/uploads/2008/05/adlscreensnapz001.png" alt="" width="635" height="418" /></p>
<p>This is probably where I learned the most.  I acted as the project lead on a 3-5 engineer team that grew or shrunk throughout the process depending on other needs.  It was developed in a commercial setting (at Tom Snyder Productions, my <a href="http://www.tomsnyder.com/">day-job</a>, which I&#8217;ve been very fortunate to find)  We&#8217;ve got a formal art, engineering, and QA team over there.</p>
<p>TimeLiner XE is the 6th major revision of one of the best selling desktop applications my employer publishes.  Previous versions were written in C++ with a proprietary cross platform layer.  It was a big gamble betting on Flex/AIR instead of sticking with C++, but we&#8217;ve been pretty happy so far.  The built in WebKit HTML renderer made one of our features (a web based research mode) a &#8220;killer feature&#8221; and doing that in a cross platform way in C++ would have been a huge investment compared to what we accomplished in AIR fairly simply.</p>
<p>You can see a pre-recorded webcast seminar at the TimeLinerXE web page. <a href="http://www.tomsnyder.com/timelinerxe/">http://www.tomsnyder.com/timelinerxe/</a><br />
If you jump to about the 3 minute mark, that&#8217;s where they start actually showing off the software. </p>
<p> </p>
<p> </p>
<hr /> </p>
<p><strong>Quick summary</strong>&#8230;</p>
<table border="1" cellspacing="0" cellpadding="6" width="491" bgcolor="#FFFFFF" bordercolor="#000000">
<tbody>
<tr valign="top">
<td width="83" valign="top"><strong>App Name </strong></td>
<td width="199" valign="top">Info</td>
<td width="165" valign="top"><strong>Framework</strong></td>
</tr>
<tr valign="top">
<td valign="top"><a href="http://www.agileagenda.com/">Agile Agenda </a></td>
<td valign="top">~ 25,000 Lines of Code             </p>
<p>1 Developer</p>
<p>First released on AIR Beta 1</td>
<td valign="top">None             </p>
<p>(Developed Quickly &amp; AdHoc for the <a href="http://labs.adobe.com/showcase/special/airderby/">Adobe AIR Derby</a>)</td>
</tr>
<tr valign="top">
<td valign="top"><a href="http://www.agileagenda.com/download/">Agile Tracker </a></td>
<td valign="top">~ 8,000 Lines of Code             </p>
<p>1 Developer</p>
<p>First released on AIR 1.0</td>
<td valign="top"><a href="http://spicefactory.org/">Parsley</a> MVC + IoC</td>
</tr>
<tr valign="top">
<td height="83" valign="top"><a href="http://www.tomsnyder.com/Products/product.asp?SKU=TIMV50">TimeLiner XE </a>             </p>
<p> </td>
<td valign="top">~ 100,000 Lines of Code             </p>
<p>3-5 Developers</p>
<p>1 Designer</p>
<p>Several QA engineers</p>
<p>Not yet released</td>
<td valign="top"><a href="http://labs.adobe.com/wiki/index.php/Cairngorm">Cairngorm</a></td>
</tr>
</tbody>
</table>
<p>LoC numbers above are just to give an idea of the scope of the project and does not include code from libraries (either internally developed or open source).  There&#8217;s a similar coding style in all three, so it&#8217;s purely meant to give an idea of the relative size of the projects.  The AgileTracker is larger than listed, because it reused a bunch of code from AgileAgenda which isn&#8217;t reflected in those numbers.</p>
<p> </p>
<p> </p>
<hr /> </p>
<p> </p>
<h2>Things we did right</h2>
<p><strong>QA / Bug Tracking</strong></p>
<p>Tom Snyder has a first class QA team. Having them involved early in the project helped direct it to be a project that was easier to test, and of higher quality than might otherwise have been possible.  Having a dedicated and passionate QA team is the single best thing that can happen to any software project.  We&#8217;re using Bugzilla for tracking which works pretty well, but will be moving to HP&#8217;s Quality Center in the near future (which I hope works even better!)</p>
<p>On the AgileAgenda side of things, this wasn&#8217;t so great.  I&#8217;m looking to rectify that in the near future, but finding the right person (at the right price) is difficult.  Since it&#8217;s a simple 1-person project I&#8217;ve been using <a href="http://hogbaysoftware.com/products/taskpaper">TaskPaper</a> to keep track of  my list of bugs, my list of future features, and my general todo list.  I&#8217;m currently looking for a good end-user bug reporting system, but haven&#8217;t found anything that really fits my needs yet.</p>
<p><strong>Open Source!</strong></p>
<p>All three applications use some very good open source projects.  Without these, the development would have taken a lot longer, and been a lot more labor intensive.  Two of the more important libraries were&#8230;</p>
<p><strong>Object Handles</strong> (Open Source)</p>
<p><a href="http://www.rogue-development.com/objectHandles.html">ObjectHandles</a> is a library I wrote a while back that makes it easy to create interfaces that let the user drag and resize components around the screen.  It&#8217;s amazing how having a library like that can make you add that type of functionality into places where you may not have wanted to spend the time implementing without it.  Take a look at AgileAgenda&#8217;s <a href="http://www.agileagenda.com/help/lightTable.html">Light Table</a>.  The Light Table is one of the features I get the most positive feedback about.  It took an afternoon to implement with this libray.  Without it, it would likely have taken a week and would have never gone into the 1.0 version.  Almost the entire TimeLiner interface was build with this library.</p>
<p><strong>AlivePDF</strong> (Open Source)</p>
<p>The printing in AgileAgenda is completly done with <a href="http://alivepdf.bytearray.org">AlivePDF</a>.  This lets the usercreate a PDF to print, send to a colleague, post on a website, etc.   It&#8217;s amazing easy to use and creates high quality PDF&#8217;s.  (Yeah, AgileAgenda doesn&#8217;t deal with margins well right now, that&#8217;s my fault and not AlivePDF&#8217;s).  </p>
<p><strong>Parsley<span style="font-weight: normal;"> (Open Source)</span></strong></p>
<p><a href="http://spicefactory.org/parsley/">Parsley</a> is great, unfortunately it was only used in the AgileTracker.  Using an IoC container for applications like these makes perfect sense, and the MVC infrastructure it provides makes it super easy to stick to the MVC model without being tempted to just have the UI muck around with your data.  The only frustrating thing I&#8217;ve found with it, is that it&#8217;s harder to debug a parsley based application when problems occur.</p>
<p>When you&#8217;re using Java/Spring on the server side, it&#8217;s also helpful to use a client side framework where you can think in the same way. </p>
<p><strong>Perforce</strong></p>
<p>We use <a href="http://www.perforce.com/">Perforce</a> for the version control system for all the mentioned projects.  It rocks, hardcore.  Even for my single-developer projects I find myself more organized with less of chance for losing something important because of it.  Subversion, CVS, whatever other version control system you use is fine too, but just make sure to use one!</p>
<p><strong>ANT</strong></p>
<p>All three projects can be fully built through a single <a href="http://ant.apache.org/">ANT</a> command.  The release builds of all the projects are made in this way.  It doesn&#8217;t matter if a developer updates his build environment, or if your FlexBuilder license gets funky, you can always make a known-good build through a simple single command line. </p>
<p>For AgileAgenda we actually end up making several builds (<a href="http://www.rogue-development.com/blog2/2008/03/01/self-signed-vs-ca-signed-air-apps/">ready why</a>), plus update the download page all automatically from the build script.  No more creating a release version from FlexBuilder, copying it to the web directory, using FTP to transfer it and editing a file to update the version on the website!</p>
<p>If you&#8217;re making release builds of your software from within Flex Builder, you really are missing out and wasting a lot of time.</p>
<p><strong>CruiseControl</strong> (Continuos integration)</p>
<p>For TimeLiner we&#8217;re automatically running builds through CruiseControl after every single code checkin.  When you have between 3 and 5 developers, it&#8217;s very easy to submit code that builds for you but nobody else.  By using CruiseControl, whoever submits a change to perforce like that gets an email telling them within 10 minutes.  No more yelling &#8220;Who forgot to add SomeWeirdClass.as to version control?&#8221;</p>
<p>For a while we had it running our unit tests as well, but unfortunately we don&#8217;t anymore (see below).</p>
<p><strong>We didn&#8217;t try to hire Flex developers</strong></p>
<p>Well, we did try, and then gave up.  Flex Developers are hard to find.  Really hard.  Many people out there claiming to be a Flex Developer are really just coders and not software engineers.   Going into TimeLiner there was Me and one contractor that knew flex well.  Everyone else was either completely new to ActionScript or only had Flash experience.  But every single one of our developers was a good engineer.  Having smart people who can get things done (certainly not my <a href="http://www.joelonsoftware.com/articles/fog0000000073.html">original idea</a>) was the best way to go, especially given the duration of the project.  Teaching an engineer flex is easy compared with teaching a flex coder to be a flex engineer.</p>
<p>I think a big part of the problem here (besides Flex being so new) is Adobe doesn&#8217;t really focus on the developer market all that much.  A lot of (non-flash/flex) developers out there still see Flash simply as a way to make annoying advertisements where you punch a monkey or watch a video of a kid setting himself on fire.  Adobe is really great to their developers, but I really wish they would go after those developers letting them know what most of us know, that Actionscript is a full featured application development language, and Flex provides a great set of components.  When do we get to see Kevin Lynch on stage shouting &#8220;<em><a href="http://www.youtube.com/watch?v=KMU0tzLwhbE">DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS</a></em>&#8220;?  Of course, I hope they never lose their designer focus, it&#8217;s what sets the platform apart.</p>
<p><strong>Design / Artwork</strong></p>
<p>Having a great design team on TimeLiner really made the project.  It looks amazing.  Unfortunately, I didn&#8217;t have the budget for that in AgileAgenda.  I ended up getting my design from three main sources.</p>
<p>1)  An eager student in France was willing to do some of this for me.  Unfortunately as time went one his priorities changed and it was hard keeping that relationship going.  (You rock Olivier)</p>
<p>2) I bought a pack of icons from <a href="http://www.iconshock.com/">IconShock</a>.  I don&#8217;t know how I lived without these.  Now, whenever I&#8217;m creating something new I can look through that library of images and pop on an icon that really spruces things up and maintains a consistent feel throughout the app.  Just imagine this, without any icons, booooring.</p>
<p><img src="http://www.rogue-development.com/blog2/wp-content/uploads/2008/05/agileagendascreensnapz001.png" alt="" width="519" height="301" /></p>
<p>3) And lastly, I needed a logo.  For $150 I ran a contest on a logo design website and got my final design.  You can&#8217;t beat that price, and it&#8217;s better than anything I could have done myself.</p>
<p><img src="http://www.rogue-development.com/blog2/wp-content/uploads/2008/05/site-name-white.png" alt="" width="269" height="84" /></p>
<p>It may not win any awards, but it looks pleasing enough and the process of creating it didn&#8217;t distract me too much from the development of the software.</p>
<p> </p>
<h2>Things we did wrong</h2>
<p><strong>Plan for modules</strong></p>
<p>The biggest thing I learned is to plan for modules in large applications from the start.  At one point during the TimeLiner development we were approaching compile times of 2-3 minutes.  Making a 1-line change and then waiting for several minutes kills productivity.  We abstracted all of our styles, graphics, and sounds into modules and got that back down to a semi-reasonable compile time, but I think if we had properly planned for modules and broke the application up in a logical manner it would have been even better.</p>
<p><strong>Printing </strong>(AlivePDF for screen grabs)</p>
<p>If you&#8217;ve been reading along, you might have noticed AlivePDF above and be suprised to see it listed here as well.  Well, it&#8217;s not a problem with the library, but a problem with how we chose to use it in TimeLiner.  We made the mistake of thinking we could take an on screen visual timeline, grab a screen scrape, and dump it into a PDF for all of the benefits mentioned above.  Turns out that the antialiasing of text looks horrible after you print one of these out.  It&#8217;s a problem with the difference in resolution from screen to print.  We wrote a lot of printing code targetted at AlivePDF and it turned out not to be high enough quality when we put those PDF&#8217;s on paper.  Luckily, at least 80% of that code was re-used to create a printing system using the normal Flash/Flex printing API.  So in TimeLiner, you can now use a file-&gt;export command to make a PDF using AlivePDF to get a PDF that looks great until you print it (and then it just looks &#8220;ok&#8221;) or you can use the File-&gt;Print command to get a great looking printout.  This lets people share it either in paper or digitally with decent results in both.</p>
<p>Using AlivePDF&#8217;s methods to add text does not have this type of problem.</p>
<p><strong>Unit Tests</strong></p>
<p>For a while we were running our unit tests as a part of the TimeLiner build, but AIR 1.0 broke our unit tests and we never found the time to go back and fix them.  I wish we had, because it would have prevented some bugs from going through the QA/Fix/Verify process and saved us some time.</p>
<p><strong>Data Binding directly to the model</strong></p>
<p>TimeLiner and AgileAgenda&#8217;s interface both used to bind directly to the data model.  That&#8217;s fine for smaller applications, but for things of this complexity they break down.  Try using AgileAgenda sometime, the interface feels sluggish.  That&#8217;s because I haven&#8217;t done anything about it over there yet.  But we did do something about it in TimeLiner. Instead of binding the user interface to the data model, we created intermediary &#8220;model adapters&#8221;.  These adapters act as delegates to the model and only pass on the events that cause binding updates when they&#8217;re active.  This makes it easy to &#8220;turn off&#8221; a big part of the UI in on central place.  It also makes it easy to present the model data in different formats so we can do things like summarize a table of data for a &#8220;totals&#8221; label right inside these.  Using these adapters, it&#8217;s easy to turn on or off access to the model to various parts of the UI without complicated logic in the UI iteself.  The work we did covered about half the binding that was in place and makes a noticeable difference.  Given more time, I&#8217;d convert the entire app over to data model adapters.</p>
<p><strong>Cairngorm</strong></p>
<p>Cairngorm is a great framework.  It&#8217;s a good implementation of the command pattern and does define a decent set of methodologies of doing things.  It suited TimeLiner well and hasn&#8217;t given us many problems.  It has certainly solved far more problems than it has caused.  The only reason I place it in the &#8220;things done wrong&#8221; category is I believe Parsley to be superior, I wish we had used it for all three projects.  Parsley solved all the problems that Cairngorm solved for us, but it also managed to solve a few more.</p>
<p>Also, Cairngorm needs an easier name to say and spell <img src='http://www.rogue-development.com/blog2/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Not using AIR distribution</strong></p>
<p>For business reasons, we&#8217;re not using the AIR distribution model for TimeLiner.  It&#8217;s a shame that we have to ship a physical CD to our customers since keeping a .air file on a website somewhere is so much more cost effective. Making an installer, pressing CD&#8217;s, printing a user&#8217;s guide, and shipping all of that is just a pain and keeps the software away from the end user for an extra few weeks after the end of development.  Plus, it&#8217;s a whole lot harder to get program udpates out there.  (AgileAgenda does not suffer from this problem)</p>
<h2>Problems with the tools</h2>
<p>Disclaimer&#8230; I like Flex Builder.  It works well and gets the job done.  With Thermo focusing on the designer crowd and Flex Builder reportedly re-focusing on the developer, I think most of these problems will be worked out in future versions.</p>
<p>Eclipse/Flex Builder doesn&#8217;t do the &#8220;Run in background&#8221; thing very well and will constantly re-pop that compile progress dialog up.   Before going the module route, this absolutely killed TimeLiner.  Afterwards, it was still a constant annoyance.  Even with modules we might be interrupted, at seemingly random times, by the &#8220;Building workspace&#8221; dialog for 5-25 seconds.  If the little &#8220;stop&#8221; button would always work instantly, this wouldn&#8217;t be a problem.  But it doesn&#8217;t.  Turning off automatic compiling can help, but then you don&#8217;t get all the functionality of FlexBuilder.  When <a href="http://fdt.powerflasher.com/">FDT</a> gets decent MXML supprt, I&#8217;m going to seriously look into it.  In the past I&#8217;ve used it on AS2 projects and problems like this simply didn&#8217;t happen over there.</p>
<p>Coming from an Eclipse/JDT and an Eclipse/FDT world, FlexBuilder is missing a lot of functionality.  Snippets, decent code generation, and refactoring like &#8220;extract method&#8221; or &#8220;create delegate&#8221; would be very helpful.  From what I hear, with Thermo coming out, the FlexBuilder team will be focusing on developer-centric ideas like this which will be great.  If Adobe just made it easier for people to extend FlexBuilder, I&#8217;m sure those things would get written by the developer community.</p>
<p>The Flex compiler will sometimes, seemingly randomly, start throwing unknown variable errors in code completely unrelated to what we&#8217;re working on.  Doing a clean build doesn&#8217;t fix it.  Going in, editing the file where the &#8220;error&#8221; is found by deleting and re typing a character, and letting it rebuild seems to be the only solution.  I think this has to do with the Flex compile cache, but I haven&#8217;t had time to investigate it further.  It happens at least once a day to me.  </p>
<p>Much of the development was done with Beta versions of AIR and Flex Builder.  I underestimated the impact that would have on development.  Beta versions are buggy, and they do suck time out of your schedule.  Little things like installing new versions every few weeks, or crashing more often add up.  But I do think the benefit of using those vs. using the older stuff was worth it this time around.  Unfortunately, I don&#8217;t know if that would always be the case, and I don&#8217;t know how to judge that impact before a project starts.  I guess I&#8217;ll just tend to opt for released versions unless the project requires something in a beta version.</p>
<h2>The future</h2>
<p>I&#8217;ll be moving AgileAgenda over to Parsley bit by bit. Thinking about that framework, it should be pretty easy to move smaller pieces over that I might be working on without disrupting the bigger picture.  AgileAgenda will most likely be in light continuous development for years to come.</p>
<p>The AgileTracker will continue on as-is.  I&#8217;m very happy with how it works and flushing out the rest of the features and functionality is &#8220;all&#8221; that&#8217;s left <img src='http://www.rogue-development.com/blog2/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>TimeLiner will stay a Cairngorm application.  Due to the way commercial educational software companies work it will probably go through cycles of being untouched for months, and then heavy development for a new release.   Those months of quiet and then bursts of activity will give us further insight on how easy it is to maintain a Cairngorm app.  Someday, I hope we do a web version of the software.</p>
<h2>Conclusion</h2>
<p>Overall, I believe Flex/AIR is the way to go for cross platform applications like these. I&#8217;ve done both Java and C++/QT cross platform apps, and neither of those was as easy to get working consistently accross platforms as AIR and Flex. </p>
<p>So, if I were to start a new project today I&#8217;d probably go with the Parsley MVC + IoC approach.  I found it to be easy to work in and it solved more of my problems than the Cairngorm approach. </p>
<p>If I could find experienced Flex engineers, I&#8217;d make my team out of them, but it wouldn&#8217;t be a must-have since I&#8217;m convinced any smart software engineer can pick this stuff up. </p>
<p>I&#8217;ll be using the data model adapter &#8220;pattern&#8221; instead of direct binding for now on for anything except the most trivial of applications.  I&#8217;ll write a full blog post really explaining this sometime.</p>
<p>Modules will be planned  from the start.  I think a lot more in all three applications could have been split into modules without any additional labor if we had just kept it in our minds from the beginning.</p>
<p><em>Disclaimer</em> &#8211; <em>I&#8217;m  an employee of Tom Snyder Productions.  Anything said in this blog post should be considered solely my own opinion, and may not be representative of my employer.</em></p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2008/05/case-study-three-flex-applications/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>AgileAgenda on Linux</title>
		<link>http://www.rogue-development.com/blog2/2008/05/agileagenda-on-linux/</link>
		<comments>http://www.rogue-development.com/blog2/2008/05/agileagenda-on-linux/#comments</comments>
		<pubDate>Sat, 10 May 2008 00:54:32 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[AgileAgenda]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.rogue-development.com/blog2/2008/05/agileagenda-on-linux/</guid>
		<description><![CDATA[This was kind of neat.  I grabbed an Ubuntu VMWare image, installed the AIR Alpha, and then installed AgileAgenda on it.  It mostly worked, except for one crippling problem.  For some reason the hotkey for &#8220;Save&#8221; was set to &#8220;S&#8221; instead of &#8220;Ctrl-S&#8221;&#8230; so you couldn&#8217;t type any task name with an &#8220;S&#8221; in it.  [...]]]></description>
			<content:encoded><![CDATA[<p>This was kind of neat.  I grabbed an Ubuntu VMWare image, installed the AIR Alpha, and then installed AgileAgenda on it.  It mostly worked, except for one crippling problem.  For some reason the hotkey for &#8220;Save&#8221; was set to &#8220;S&#8221; instead of &#8220;Ctrl-S&#8221;&#8230; so you couldn&#8217;t type any task name with an &#8220;S&#8221; in it.  I&#8217;ll have to look into that to see if it&#8217;s just an AIR Alpha bug, or if it&#8217;s a problem I need to fix with something I&#8217;m doing.  I can&#8217;t wait for the full Linux AIR to come out, it&#8217;ll be a great way for Linux users to get applications.</p>
<p>One of the best things about AIR is it&#8217;s application distribution model.  It&#8217;s just so darned easy for people to install apps.  One of the worst things about Linux is application distribution.  There&#8217;s just too many package formats and different ways to install.  I really hope AIR can bring a single, simple, installation method for AIR apps to all of the popular distributions.  Something that my wife could sit down at a Linux computer and do.</p>
<p><span style="text-decoration: underline;"><a href="http://www.rogue-development.com/blog2/wp-content/uploads/2008/05/agileagendalinux.png"></a><a href="http://www.rogue-development.com/blog2/wp-content/uploads/2008/05/agileagendalinux1.png"><img class="alignnone size-thumbnail wp-image-202" title="agileagendalinux.png" src="http://www.rogue-development.com/blog2/wp-content/uploads/2008/05/agileagendalinux1.png" alt="" width="600" /></a></span></p>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2008/05/agileagenda-on-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AIR / Browser API example</title>
		<link>http://www.rogue-development.com/blog2/2008/03/air-browser-api-example/</link>
		<comments>http://www.rogue-development.com/blog2/2008/03/air-browser-api-example/#comments</comments>
		<pubDate>Mon, 24 Mar 2008 11:00:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=156</guid>
		<description><![CDATA[AIR / Browser API example

 
The other day I blogged about a wrapper class that I wrote to handle the AIR / Browser integration API.  Below is an example of another class that I wrote that uses that wrapper class.  It&#8217;s capable of detecting two different AIR applications, installing them, and running them.  It relies on the [...]]]></description>
			<content:encoded><![CDATA[<div>AIR / Browser API example</div>
<div></div>
<div> </div>
<div>The <a id="bw8j" href="http://www.rogue-development.com/blog/2008/03/interacting-with-air-app-from-browser.html" title="other day">other day</a> I blogged about a <a id="g_0." href="http://rogue-development.com/uploads/AirSwfAPI.zip" title="wrapper class">wrapper class</a> that I wrote to handle the AIR / Browser integration API.  Below is an example of another class that I wrote that uses that wrapper class.  It&#8217;s capable of detecting two different AIR applications, installing them, and running them.  It relies on the wrapper class to do all the heavy lifting, but I thought this might be a good example to help people get started.</div>
<div> </div>
<div> </div>
<div>
<div id="znci" style="margin-top: 0px; margin-bottom: 0px"></div>
<div id="znci" style="margin-top: 0px; margin-bottom: 0px"><span class="Apple-style-span" style="color: rgb(153, 0, 204); font-family: Monaco;"><br /></span></div>
<div id="znci" style="margin-top: 0px; margin-bottom: 0px"><span class="Apple-style-span"  style=" ;font-family:Monaco;"><span style="color: rgb(153, 0, 204)"><span class="Apple-style-span" style="font-size: medium;">package</span></span><span class="Apple-style-span" style="font-size: medium;"> com.agileagenda.web<span class="Apple-style-span" style="font-family: Georgia; "></span></span></span></div>
<div id="znci" style="margin-top: 0px; margin-bottom: 0px"><span class="Apple-style-span"  style=" ;font-family:Monaco;"><span class="Apple-style-span" style="font-size: medium;"><span class="Apple-style-span" style="font-family: Georgia; ">{</span></span></span></div>
<div id="znci" style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px; margin-top: 0px; margin-bottom: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">import</span> com.roguedevelopment.air.AIRBrowserRuntime;</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">import</span> com.roguedevelopment.air.AIRBrowserRuntimeEvent;</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">import</span> flash.events.IOErrorEvent;</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(153, 0, 204)">class</span> InstalledApplications</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(0, 51, 255)">static</span> <span style="color: rgb(51, 153, 102)">function</span> <span style="color: rgb(0, 51, 255)">get</span> instance() : InstalledApplications</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">if</span>( _instance == <span style="color: rgb(0, 51, 255)">null</span> ) { _instance = <span style="color: rgb(0, 51, 255)">new</span> InstalledApplications(); }</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">return</span> _instance;</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(0, 51, 255)">static</span> <span style="color: rgb(102, 153, 204)">var</span> _instance:InstalledApplications = <span style="color: rgb(0, 51, 255)">null</span>;</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(102, 153, 204)">var</span> api:AIRBrowserRuntime;   </p>
<p style=" color: rgb(153, 0, 0); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(0, 51, 255)">static</span> <span style="color: rgb(0, 51, 255)">const</span><span style="color: rgb(0, 0, 0)"> PUBLISHER_ID:String = </span>&#8220;F49A4D8DF78A1FEE7A3BE440DC11BAB18D922274.1&#8243;<span style="color: rgb(0, 0, 0)">;</span></p>
<p style=" color: rgb(153, 0, 0); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(0, 51, 255)">static</span> <span style="color: rgb(0, 51, 255)">const</span><span style="color: rgb(0, 0, 0)"> TRACKER_ID:String =  </span>&#8220;com.agileagenda.AgileTracker&#8221;<span style="color: rgb(0, 0, 0)">;</span></p>
<p style=" color: rgb(153, 0, 0); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(0, 51, 255)">static</span> <span style="color: rgb(0, 51, 255)">const</span><span style="color: rgb(0, 0, 0)"> MAIN_APP_ID:String = </span>&#8220;com.agileagenda.AgileAgenda&#8221;<span style="color: rgb(0, 0, 0)">;</span></p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"></p>
<p style=" color: rgb(153, 0, 0); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(0, 51, 255)">static</span> <span style="color: rgb(0, 51, 255)">const</span><span style="color: rgb(0, 0, 0)"> AGILE_AGENDA_INSTALL:String =  </span>&#8220;http://www.agileagenda.com/download/AgileAgenda.air&#8221;<span style="color: rgb(0, 0, 0)">;</span></p>
<p style=" color: rgb(153, 0, 0); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(0, 51, 255)">static</span> <span style="color: rgb(0, 51, 255)">const</span><span style="color: rgb(0, 0, 0)"> AGILE_TRACKER_INSTALL:String = </span>&#8220;http://www.agileagenda.com/download/AgileTracker.air&#8221;<span style="color: rgb(0, 0, 0)">;</span></p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">[<span style="color: rgb(0, 51, 255)">Bindable</span>] <span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(102, 153, 204)">var</span> isReady:Boolean=<span style="color: rgb(0, 51, 255)">false</span>;</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">[<span style="color: rgb(0, 51, 255)">Bindable</span>] <span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(102, 153, 204)">var</span> hasAIR:Boolean;</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">[<span style="color: rgb(0, 51, 255)">Bindable</span>] <span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(102, 153, 204)">var</span> agileAgendaVersion:String = <span style="color: rgb(153, 0, 0)">&#8220;&#8221;</span>;</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">[<span style="color: rgb(0, 51, 255)">Bindable</span>] <span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(102, 153, 204)">var</span> agileTrackerVersion:String = <span style="color: rgb(153, 0, 0)">&#8220;&#8221;</span>;</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(51, 153, 102)">function</span> InstalledApplications()</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api = <span style="color: rgb(0, 51, 255)">new</span> AIRBrowserRuntime();</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.addEventListener(AIRBrowserRuntimeEvent.READY, onReady );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.addEventListener(IOErrorEvent.IO_ERROR, onAirFail );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.load();</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"></p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(51, 153, 102)">function</span> onAirFail(event:IOErrorEvent) : <span style="color: rgb(0, 51, 255)">void</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(204, 102, 102)">  trace</span>( event.text );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(51, 153, 102)">function</span> onReady(event:AIRBrowserRuntimeEvent ) : <span style="color: rgb(0, 51, 255)">void</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  hasAIR = api.getStatus() == <span style="color: rgb(153, 0, 0)">&#8216;installed&#8217;</span>;</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  isReady = <span style="color: rgb(0, 51, 255)">true</span>;</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.addEventListener(AIRBrowserRuntimeEvent.APP_VERSION_RESULT, onTrackerVersionResult );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.getApplicationVersion( TRACKER_ID, PUBLISHER_ID );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(51, 153, 102)">function</span> onTrackerVersionResult(event:AIRBrowserRuntimeEvent) : <span style="color: rgb(0, 51, 255)">void</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(204, 102, 102)">  trace</span>(<span style="color: rgb(153, 0, 0)">&#8220;Tracker version installed: &#8220;</span> + event.detectedVersion );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  agileTrackerVersion = event.detectedVersion</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.removeEventListener(AIRBrowserRuntimeEvent.APP_VERSION_RESULT, onTrackerVersionResult );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.addEventListener(AIRBrowserRuntimeEvent.APP_VERSION_RESULT, onAppVersionResult );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.getApplicationVersion( MAIN_APP_ID, PUBLISHER_ID );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">protected</span> <span style="color: rgb(51, 153, 102)">function</span> onAppVersionResult(event:AIRBrowserRuntimeEvent ) : <span style="color: rgb(0, 51, 255)">void</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" color: rgb(153, 0, 0); margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(204, 102, 102)">  trace</span><span style="color: rgb(0, 0, 0)">(</span>&#8220;Application version installed: &#8220;<span style="color: rgb(0, 0, 0)"> + event.detectedVersion );</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  agileAgendaVersion  = event.detectedVersion</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.removeEventListener(AIRBrowserRuntimeEvent.APP_VERSION_RESULT, onAppVersionResult );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(51, 153, 102)">function</span> launchAgileAgenda( args:Array ) : <span style="color: rgb(0, 51, 255)">void</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.launchApplication( MAIN_APP_ID, PUBLISHER_ID, args );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(51, 153, 102)">function</span> launchAgileTracker( args:Array ) : <span style="color: rgb(0, 51, 255)">void</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.launchApplication( TRACKER_ID, PUBLISHER_ID, args );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(51, 153, 102)">function</span> installAgileAgenda(args:Array) : <span style="color: rgb(0, 51, 255)">void</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.installApplication(AGILE_AGENDA_INSTALL, <span style="color: rgb(153, 0, 0)">&#8220;1.0&#8243;</span>, args );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span style="color: rgb(0, 51, 255)">public</span> <span style="color: rgb(51, 153, 102)">function</span> installAgileTracker(args:Array) : <span style="color: rgb(0, 51, 255)">void</span></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">{</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">  api.installApplication(AGILE_TRACKER_INSTALL, <span style="color: rgb(153, 0, 0)">&#8220;1.0&#8243;</span>, args );</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
</p>
<p style=" min-height: 15px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"></p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<p style=" margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">}</p>
<div><span class="Apple-style-span"   style="font-family:Monaco;font-size:100%;"><span class="Apple-style-span"  style="font-size:11px;"> </span></span></div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2008/03/air-browser-api-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interacting with an AIR app from a browser based app</title>
		<link>http://www.rogue-development.com/blog2/2008/03/interacting-with-an-air-app-from-a-browser-based-app/</link>
		<comments>http://www.rogue-development.com/blog2/2008/03/interacting-with-an-air-app-from-a-browser-based-app/#comments</comments>
		<pubDate>Sun, 23 Mar 2008 15:25:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=155</guid>
		<description><![CDATA[Interacting with an AIR app from a browser based app
 
            We&#8217;ve all seen the AIR installation badges that let you install an AIR application from a website.  But the API exposed to do that lets you do more than just a simple [...]]]></description>
			<content:encoded><![CDATA[<div><span class="Apple-style-span"><b>Interacting with an AIR app from a browser based app</b></span></div>
<div> </div>
<p>            We&#8217;ve all seen the AIR installation badges that let you install an AIR application from a website.  But the API exposed to do that lets you do more than just a simple badge.  I&#8217;ve been working on a web-based service for AgileAgenda.  One of the components of that is to manage the list of files you&#8217;ve saved to the service and be able to open those in the desktop AIR application.  So right from within the online Flex based app it sure would be nice to detect if the application is installed, give the user the option to install, and then launch it for them and automatically open the desired file.  Something like this&#8230;
<div>
<div id="x6zu">
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="h9ls"><a target="_blank" href="http://www.blogger.com/File?id=dfxczdkr_16gxh5mvcz"><img src="http://docs.google.com/File?id=dfxczdkr_16gxh5mvcz" style="width: 640px; height: 373.145px" /></a></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="h9ls">To implement that we need to:</div>
<div id="h9ls">
<ol>
<li>Detect whether or not the application is installed.</li>
<li>Display the version number if it is.  (Disable the &#8220;Open schedule in&#8230;&#8221; button if it&#8217;s not)</li>
<li>When clicking on the &#8220;Open&#8221; link, launch the application with a few parameters so it know what to open.</li>
<li>When clicking on the &#8220;Install&#8221; link, install the application and pass a few parameters so it know what to open when it launches directly after the install.</li>
</ol>
<div> </div>
<div>Doing things like that falls outside of the normal AS3 web development API.  But Adobe provides a swf that you can load at runtime and them make calls to.  You can read all about that over here: <a id="hjad" href="http://livedocs.adobe.com/air/1/devappshtml/help.html?content=distributing_apps_3.html" target="_blank" title="http://livedocs.adobe.com/air/1/devappshtml/help.html?content=distributing_apps_3.html">http://livedocs.adobe.com/air/1/devappshtml/help.html?content=distributing_apps_3.html.</a></div>
<div> </div>
<div>But there&#8217;s an annoying thing with that.  You need to load up that remote swf and then access it like a dynamic object.  No compiler-time type checking.  Not the standard event mechanism.  And no code-completion from within Flex Builder.</div>
<div> </div>
<div>Luckily for you, I went through and made a wrapper class that you can download from here:</div>
<div><a id="imj5" href="http://rogue-development.com/uploads/AirSwfAPI.zip" title="http://rogue-development.com/uploads/AirSwfAPI.zip" target="_blank">http://rogue-development.com/uploads/AirSwfAPI.zip</a> </div>
<div> </div>
<div>This will handle the loading of the remote swf, dispatching events when it loads (or fails to load) and then wraps the API for the entire process.  There&#8217;s nothing revolutionary in there, it&#8217;s mostly takendirectly from that livedocs page above.</div>
<div> </div>
<div>So now that you have that handy-dandy wrapper class, lets look at how to actually get something done.  </div>
<div> </div>
<div><b>Setting up your AIR application to work with your website (<span class="Apple-style-span"  style="color:#990000;">Important</span>)</b></div>
<div> </div>
<div>First thing, go into your AIR application&#8217;s -app.xml file and make sure allowBrowserInvocation is set to true.  By default it&#8217;s set to false.  </div>
<div> </div>
<div>
<p  style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color:#3f7f7f;"><span style="color:#008080;">&lt;</span>allowBrowserInvocation<span style="color:#008080;">&gt;</span><span style="color:#000000;">true</span><span style="color:#008080;">&lt;/</span>allowBrowserInvocation<span style="color:#008080;">&gt;</span></p>
<p  style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color:#3f7f7f;"><span class="Apple-style-span"  style="color:#008080;"> </span></p>
<p>If you don&#8217;t do this, you won&#8217;t even be able to query version information on your application.  But, be careful.  By doing this you&#8217;re letting any website launch your AIR application from a web page. You need to be careful in how much your app trusts command line arguments passed to it.  For instance, you should never pass a file to delete on the command line. </p>
</p>
<p>Now that you&#8217;ve set <i>allowBrowserInvocation</i> to true, create a new .air file and post that to your website somewhere.</p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"  style="font-family:Verdana;"><span class="Apple-style-span"><b>Using the wrapper class to interact with your application</b></span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">Either open an existing Flex or Actionscript project in FlexBuilder and put the source to the AIRBrowserRuntime.as somewhere that the compiler will find it.  Somewhere in your main application, create an AIRBrowserRuntime object, set some event listeners, and call the load() method to load the air.swf file from Adobe&#8217;s servers.</span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">var api:<span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;">AIRBrowserRuntime;</span></span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">&#8230;</p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px">
<p><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">api = <span style="color:#0033ff;">new</span> AIRBrowserRuntime();</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">api.addEventListener(AIRBrowserRuntimeEvent.READY, onReady );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-style-span"  style="color:#38761D;"><i>// Optional: api.addEventListener(IOErrorEvent.IO_ERROR, onAirFail );</i></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">api.load();</p>
<p></span>
</p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">Once the READY event is dispatched, you can start calling methods to query application versions, install apps, or launch applications.  </span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"  style="font-family:Verdana;"><span class="Apple-style-span"><b>Checking if AIR is installed</b></span></span></p>
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p>To see if the AIR runtime is installed, call the <i>getStatus</i>() method.  It will return one of three values.</p>
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">available &#8211; The AIR runtime can be installed on this computer but currently it is not installed</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">unavailable &#8211; The AIR runtime cannot be installed on this computer.</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">installed &#8211; The AIR runtime is installed on this computer.</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">Example:</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">switch(  api.getStatus()  )</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">{</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">   case &#8220;available&#8221;: trace(&#8220;AIR is available, but not installed.&#8221;); break;</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">   case &#8220;unavailable&#8221;: trace(&#8220;AIR is not available for this computer.&#8221;); break;</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">   case &#8220;installed&#8221;: trace(&#8220;AIR is already installed on this computer.&#8221;); break;</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">}</span></span></p>
<p><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #3f5fbf">
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"><b><span class="Apple-style-span"  style="font-family:Verdana;">Checking the version of an installed application</span></b></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #3f5fbf">
<p>The getApplicationVersion method will check to see if a given application is installed and give you the version if it is.  This method operates asynchronously so you have to create an event listener before you call it.  If you look at the method signature&#8230;</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #3f5fbf">
</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color:#0033ff;">public</span> <span style="color:#339966;">function</span> getApplicationVersion(applicationID:String, publisherID:String) : <span style="color:#0033ff;">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">
<p style="text-align: auto;margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px"><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;"> </span></span></p>
<p><span class="Apple-style-span"   style="font-family:Verdana;font-size:100%;"><span class="Apple-style-span"  style="font-size:13px;">You&#8217;ll see that it takes an applicationID and a publisherID.  The applicationID is just value of the &lt;id&gt; tag of your application descriptor (the -app.xml file).  It&#8217;ll probably be something like this, but you need to make sure to make each application unique:</span></span></p>
</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color:#008080;">&lt;</span><span style="color:#3f7f7f;">id</span><span style="color:#008080;">&gt;</span>com.agileagenda.AgileTracker<span style="color:#008080;">&lt;/</span><span style="color:#3f7f7f;">id</span><span style="color:#008080;">&gt;</span></p>
</p>
<p>The publisherID is a little trickier to find.  That doesn&#8217;t get assigned until you actually sign your .AIR file with your code-signing key.  I know of 2 ways of finding it, but there&#8217;s probably an easier way (please leave a comment if you know how).</p>
</p>
<p><span class="Apple-style-span"  style="color:#660000;"><i>Warning about Publisher ID:  If you change the key your sign your app with, the publisher ID will change.</i></span></p>
</p>
<p><b>Option 1: Get it at runtime.</b></p>
</p>
<p>In your application&#8217;s main MXML throw up an Alert message with the publisher ID.  Then build a .air, install the .air and run it.  Copy &amp; Paste the result.  Example:</p>
</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;utf-8&#8243;?&gt;</p>
<p  style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color:#990000;"><span style="color:#0000ff;">&lt;mx:WindowedApplication</span><span style="color:#000000;"> xmlns:mx=&#8221;</span>http://www.adobe.com/2006/mxml<span style="color:#000000;">&#8221; </span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">    creationComplete=&#8221;init()&#8221; <span class="Apple-style-span" style="color: rgb(0, 0, 255)">&gt;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-style-span"  style="color:#0000FF;"> </span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #990000">
<p><span class="Apple-style-span"  style="color:#0000FF;">
<p  style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color:#006633;"><span class="Apple-style-span" style="color: rgb(0, 0, 255)">  &lt;<span class="Apple-style-span" style="color: rgb(0, 102, 51)">mx:Script&gt;</span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;">  &lt;![CDATA[</span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">
<p></span>
</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #990000">
<p><span class="Apple-style-span"  style="color:#0000FF;">
<p  style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color:#0033ff;"><span class="Apple-style-span" style="color: rgb(0, 0, 255)"><span class="Apple-style-span" style="color: rgb(0, 51, 255)"><span class="Apple-style-span" style="color: rgb(0, 0, 255)"><span class="Apple-style-span" style="color: rgb(0, 51, 255)">    protected <span style="color:#339966;">function</span><span style="color:#000000;"> init() : </span>void </span></span></span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;">    {</span></span></span></span></span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;">      Alert.show( nativeApplication.publisherID);</span></span></span></span></span></span></span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;"><span class="Apple-style-span"   style=" ;font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;">    }</span></span></span></span></span></span></p>
<p></span>
</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #990000">
<p><span class="Apple-style-span"  style="color:#0000FF;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">  ]]&gt;</p>
<p  style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color:#006633;"><span class="Apple-style-span"   style="color: rgb(0, 0, 255);  font-family:Verdana;font-size:13px;"><span class="Apple-style-span"   style="color: rgb(0, 102, 51);  font-family:Monaco;font-size:11px;">  &lt;/mx:Script&gt;</span></span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #006633">
<p></span>
</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #990000">
<p><span class="Apple-style-span"  style="color:#0000FF;">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #0000ff">&lt;/mx:WindowedApplication&gt;</p>
<p></span>
</p>
<p>Which results in something resembling:</p>
</p>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci"><img src="http://docs.google.com/File?id=dfxczdkr_178g528pdz" style="width: 370px; height: 153px" /></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci">It&#8217;s hard to see in that picture, but the publisher ID is: F49A4D8DF78A1FEE7A3BE440DC11BAB18D922274.1 as it wraps to two lines.</div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci"><b>Option 2: Get it after install </b></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci">This is probably a bit easier, but I&#8217;m not 100% sure where this directory goes on a windows box.</div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci">On OSX (maybe on Windows, I&#8217;m not sure exactly where) the application storage directory that gets created for your application has the publisher ID appended to it.  So if you look in your user directory -&gt; Library -&gt; Preferences, you should see a directory that starts with your application ID and ends with your publisher ID.</div>
<div id="znci">
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="aax4"><img src="http://docs.google.com/File?id=dfxczdkr_18jfj8vg54" style="width: 737px; height: 126px" /></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="aax4">As you can see there, we get the same publisher ID value as Option #1.</div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="aax4"><b>On to checking installed version</b></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="aax4">Now that you have your application ID and your publisher ID you can make a call from your web application to the API to request the installed version of your AIR application.  This operates asynchronously so you&#8217;ll need an event listener for the result.</div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="aax4">Example:</div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="aax4">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">api.addEventListener(AIRBrowserRuntimeEvent.APP_VERSION_RESULT, onTrackerVersionResult );</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">api.getApplicationVersion( <span class="Apple-style-span" style="color: rgb(153, 0, 0)">&#8220;com.agileagenda.AgileTracker&#8221;</span>, <span class="Apple-style-span" style="color: rgb(153, 0, 0)">&#8220;F49A4D8DF78A1FEE7A3BE440DC11BAB18D922274.1&#8243;</span> );</p>
</div>
<div id="aax4">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-style-span"  style="color:#0033FF;">&#8230;</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span class="Apple-style-span"  style="color:#0033FF;"> </span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco"><span style="color:#0033ff;">protected</span> <span style="color:#339966;">function</span> onTrackerVersionResult(event:AIRBrowserRuntimeEvent) : <span style="color:#0033ff;">void</span></p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">{</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">  <span style="color:#cc6666;">trace</span>(<span style="color:#990000;">&#8220;Tracker version installed: &#8220;</span> + event.detectedVersion );     </p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">}</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">The event.detectedVersion that comes back will be the value in your application descriptor version tag.  Mine looks like this:</p>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">
</p>
<p  style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color:#3f7f7f;"><span style="color:#008080;">&lt;</span>version<span style="color:#008080;">&gt;</span><span style="color:#000000;">v1</span><span style="color:#008080;">&lt;/</span>version<span style="color:#008080;">&gt;</span></p>
<p  style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color:#3f7f7f;"><span class="Apple-style-span"  style="color:#008080;"> </span></p>
<p>So the trace output looks like this:</p>
<p></p>
<p><span class="Apple-style-span"  style="color:#073763;">Tracker version installed: v1</span></p>
</p>
<p><span class="Apple-style-span"><b>Launching an installed AIR application</b></span></p>
</p>
</div>
</div>
<div id="znci">Assuming you followed along in the previous section, you have an Application ID and a Publisher ID ready.  To launch an AIR app from a web app you just call</div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci"><b>
<p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco">api.launchApplication( <span class="Apple-style-span" style="color: rgb(153, 0, 0)">&#8220;com.agileagenda.AgileTracker&#8221;</span>, <span class="Apple-style-span" style="color: rgb(153, 0, 0)">&#8220;F49A4D8DF78A1FEE7A3BE440DC11BAB18D922274.1&#8243;</span> );</p>
<p></b></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci">launchApplication has a third, optional, parameter called arguments and is typed as an array.  Anything you pass into that will be passed along to the application in an INVOKE event.  This way you can pass information from the web application to the AIR application.  Example:</div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;">api.launchApplication( <span class="Apple-style-span" style="color: rgb(153, 0, 0)">&#8220;com.agileagenda.AgileTracker&#8221;</span>, <span class="Apple-style-span" style="color: rgb(153, 0, 0)">&#8220;F49A4D8DF78A1FEE7A3BE440DC11BAB18D922274.1&#8243;, ["Argument1","Argument2" ]</span> );</span></div>
<div id="znci">Be careful, the arguments are <b>very restrictive</b> in what characters can be passed.  Things like dashes, percent signs, underscores, all cause a runtime exception on the web application.  You&#8217;re probably safest only using alphanumeric characters.  I haven&#8217;t found a comprehensive list of what characters are or are not valid.  If someone has that, please leave a comment below.  This was done for security reasons.</div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci"><span class="Apple-style-span"  style="font-size:180%;"><span class="Apple-style-span"  style="font-size:18px;"><b>Installing an AIR application</b></span></span></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci">To install an AIR application, all you need to do is call the <span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;"><i>installApplication</i> with the absolute URL to the .air file you want to install.  Example:</span></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci"><span class="Apple-style-span"   style=" ;font-family:Monaco;font-size:11px;">api.installApplication(&#8220;<span class="Apple-style-span" style="color: rgb(153, 0, 0)">http://www.agileagenda.com/download/AgileTracker.air&#8221;</span>);</span></div>
<p>This will take care of installing the AIR runtime, installing the application, and launching it for the first time.  installApplication has two more optional parameters.  The AIR runtime that the application requires, and arguments that can be passed to the application for it&#8217;s first run.  Example:</p>
<div id="znci"> </div>
<div id="znci"><span class="Apple-style-span">api.installApplication(&#8220;<span class="Apple-style-span" style="color: rgb(153, 0, 0)">http://www.agileagenda.com/download/AgileTracker.air&#8221;,&#8221;1.0&#8243;,["Arg1","Arg2"]</span>);</span></div>
<div id="znci"> </div>
<div id="znci"><span class="Apple-style-span"><b>That&#8217;s all there is to it.</b></span></div>
<div id="znci"><span class="Apple-style-span"  style="font-size:180%;"><span class="Apple-style-span"  style="font-size:18px;"><b> </b></span></span></div>
<div id="znci">So that&#8217;s it, pretty simple, huh?  You might also want to look into using a LocalConnection to do realtime communication between your web-app and your air-app once the air-app has been launched.  Recap of the links:</div>
<div id="znci"> </div>
<div id="znci"> </div>
<div id="znci">Wrapper Class:</div>
<div id="znci"><a id="imj5" href="http://rogue-development.com/uploads/AirSwfAPI.zip" title="http://rogue-development.com/uploads/AirSwfAPI.zip" target="_blank">http://rogue-development.com/uploads/AirSwfAPI.zip</a></div>
<div id="znci"> </div>
<div id="znci">Adobe&#8217;s Documentation:</div>
<div id="znci"><a id="hjad" href="http://livedocs.adobe.com/air/1/devappshtml/help.html?content=distributing_apps_3.html" target="_blank" title="http://livedocs.adobe.com/air/1/devappshtml/help.html?content=distributing_apps_3.html">http://livedocs.adobe.com/air/1/devappshtml/help.html?content=distributing_apps_3.html</a></div>
<div id="znci"> </div>
<div id="znci">My Blog (where any updates to the wrapper class will be posted)</div>
<div id="znci"><a id="tk_d" href="http://www.rogue-development.com/blog/" title="http://www.rogue-development.com/blog/">http://www.rogue-development.com/blog/</a> </div>
<div id="znci"> </div>
<div id="znci">The actual air.swf that does all the heavy lifting (This URL is wrong in some of the docs!)</div>
<div id="znci">
<p>http://airdownload.adobe.com/air/browserapi/air.swf</p>
</div>
<div id="znci"> </div>
<div id="znci"> </div>
<div id="znci"> </div>
<div id="znci"></div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci"> </div>
<div style="text-align: left; padding-top: 1em; padding-bottom: 1em; padding-right: 0px; padding-left: 0px" id="znci"> </div>
</p></div>
</p></div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2008/03/interacting-with-an-air-app-from-a-browser-based-app/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>AgileAgenda &#8211; New Version</title>
		<link>http://www.rogue-development.com/blog2/2008/01/agileagenda-new-version-3/</link>
		<comments>http://www.rogue-development.com/blog2/2008/01/agileagenda-new-version-3/#comments</comments>
		<pubDate>Mon, 07 Jan 2008 12:08:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[AgileAgenda]]></category>
		<category><![CDATA[Schedule]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=113</guid>
		<description><![CDATA[Posted a new version of AgileAgenda over the weekend.  Fixed a few minor bugs, redesigned the opening screens, and put in our new logo.  The entire initial user experience should be better now.   Here&#8217;s a quick glimpse of what it looks like now:
 



]]></description>
			<content:encoded><![CDATA[<p>Posted a new version of <a href="http://www.agileagenda.com/download/">AgileAgenda</a> over the weekend.  Fixed a few minor bugs, redesigned the opening screens, and put in our new logo.  The entire initial user experience should be better now.   Here&#8217;s a quick glimpse of what it looks like now:
<div> </div>
<div>
<div></div>
<p><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px;" src="http://www.agileagenda.com/screenshots/screenshot1.png" border="0" alt="" /></div>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2008/01/agileagenda-new-version-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AIR Badge installer + swfobject + ExpressInstall</title>
		<link>http://www.rogue-development.com/blog2/2007/12/air-badge-installer-swfobject-expressinstall/</link>
		<comments>http://www.rogue-development.com/blog2/2007/12/air-badge-installer-swfobject-expressinstall/#comments</comments>
		<pubDate>Sat, 15 Dec 2007 16:05:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[AgileAgenda]]></category>
		<category><![CDATA[badge]]></category>
		<category><![CDATA[swfobject]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=103</guid>
		<description><![CDATA[I&#8217;ve put together a page to install AgileAgenda using SWFObject with the ExpressInstall feature and the AIR Installation Badge.
This means people with a Flash Player less than 9.0.115 should be able to first upgrade their flash player, and then use the easy badge installation method for AIR + the application.  I gave it a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve put together a page to install <a href="http://www.agileagenda.com/download/">AgileAgenda</a> using <a href="http://www.swffix.org/">SWFObject</a> with the ExpressInstall feature and the AIR Installation Badge.</p>
<p>This means people with a Flash Player less than 9.0.115 should be able to first upgrade their flash player, and then use the easy badge installation method for AIR + the application.  I gave it a try on Firefox + Safari on OSX and IE + Firefox on WinXP, all of them with a 9.0.47 flash player and it all seemed to work well.  The code also displays a message suggesting people install Flash player or install the AIR application manually if they don&#8217;t have any version of Flash.</p>
<p>I&#8217;ve put together a <a href="http://rogue-development.com/AgileBadgeInstaller.zip">small archive</a> of the necessary files to make this work.  It contains files from the <a href="http://code.google.com/p/swfobject/">swfobject</a> guys released under the MIT license, and you can consider anything I wrote to make this work also under that license (which allows you to pretty much use it any way you like).</p>
<div>Thanks go to the swfobject guys, they really made this a no-brainer on how to implement!</div>
<div>Hope this helps some people.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2007/12/air-badge-installer-swfobject-expressinstall/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>AgileAgenda &#8211; New Version</title>
		<link>http://www.rogue-development.com/blog2/2007/12/agileagenda-new-version-2/</link>
		<comments>http://www.rogue-development.com/blog2/2007/12/agileagenda-new-version-2/#comments</comments>
		<pubDate>Fri, 14 Dec 2007 20:05:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[AgileAgenda]]></category>
		<category><![CDATA[Schedule]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=101</guid>
		<description><![CDATA[For those of you new here, AgileAgenda is a project scheduling application built on Adobe AIR.  
There&#8217;s a new version of AgileAgenda now available on the website.
It&#8217;s been updated for AIR Beta 3, and includes a lot of bug fixes and minor enhancements, with a couple large feature improvements thrown in for good measure. [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-style: italic;">For those of you new here, AgileAgenda is a project scheduling application built on Adobe AIR.  </span></p>
<p>There&#8217;s a new version of AgileAgenda now available on <a href="http://www.agileagenda.com/">the website.</a></p>
<p>It&#8217;s been updated for AIR Beta 3, and includes a lot of bug fixes and minor enhancements, with a couple large feature improvements thrown in for good measure.  You can read the list on the <a href="http://www.agileagenda.com/blog/">project blog</a>.</p>
<p>The biggest change for me is file open/save dialogs work on OSX Leopard!  Yay.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2007/12/agileagenda-new-version-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AIR Mime type</title>
		<link>http://www.rogue-development.com/blog2/2007/10/air-mime-type/</link>
		<comments>http://www.rogue-development.com/blog2/2007/10/air-mime-type/#comments</comments>
		<pubDate>Mon, 22 Oct 2007 11:24:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=76</guid>
		<description><![CDATA[I&#8217;ve been having some problems with some browsers  downloading my .air apps as .zip files, even replacing the file extension.  I figured it was a Mime type problem, and sure-enough&#8230;
This is from the AIR release notes:
Setting the mime type in your Web Server for AIR applications
In order for client browsers to recognize an [...]]]></description>
			<content:encoded><![CDATA[<h3 style="font-weight: normal;">I&#8217;ve been having some problems with some browsers  downloading my .air apps as .zip files, even replacing the file extension.  I figured it was a Mime type problem, and sure-enough&#8230;</h3>
<h3 style="font-weight: normal;">This is from the AIR release notes:<br /></h3>
<blockquote><h3>Setting the mime type in your Web Server for AIR applications</h3>
<p>In order for client browsers to recognize an AIR application when being downloaded, the Web Server hosting the AIR applications needs to map the following MIME Content Type “application/vnd.adobe.air-application-installer-package+zip” to the Apollo extension “.air”. For example, for an Apache Web Server you will add to the AddType section: AddType application/vnd.adobe.air-application-installer-package+zip .air</p>
</blockquote>
<p></p>
<p>So for Apache, just add this to your config:</p>
<p>AddType application/vnd.adobe.air-application-installer-package+zip .air</p>
<p>I had some weird problems with the badge-installer not working on a couple OSX machines, I wonder if this will fix it.</p>
<p>
<p></p>
<p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2007/10/air-mime-type/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Native code in air apps?</title>
		<link>http://www.rogue-development.com/blog2/2007/10/native-code-in-air-apps/</link>
		<comments>http://www.rogue-development.com/blog2/2007/10/native-code-in-air-apps/#comments</comments>
		<pubDate>Mon, 01 Oct 2007 20:12:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=70</guid>
		<description><![CDATA[I just watched a demo of running the PDF reader in an AIR app.  One interesting caveat is the reader starts with every installed reader plugin the user has.   I wonder if this means we could use that mechanism for running native code by writing a reader plugin&#8230;
]]></description>
			<content:encoded><![CDATA[<p>I just watched a demo of running the PDF reader in an AIR app.  One interesting caveat is the reader starts with every installed reader plugin the user has.   I wonder if this means we could use that mechanism for running native code by writing a reader plugin&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2007/10/native-code-in-air-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AirDerbyEntries++</title>
		<link>http://www.rogue-development.com/blog2/2007/09/airderbyentries/</link>
		<comments>http://www.rogue-development.com/blog2/2007/09/airderbyentries/#comments</comments>
		<pubDate>Wed, 05 Sep 2007 18:48:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[AgileAgenda]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=54</guid>
		<description><![CDATA[Last night I submitted  agile agenda for the AIR derby.  I wasn&#8217;t going to originally since I didn&#8217;t think I had a chance in hell, but then I got thinking.  Even making some kind of entry-list might generate some good publicity.  With beta starting within the next week or two, I [...]]]></description>
			<content:encoded><![CDATA[<p>Last night I submitted  <a href="http://www.agileagenda.com/">agile agenda</a> for the AIR derby.  I wasn&#8217;t going to originally since I didn&#8217;t think I had a chance in hell, but then I got thinking.  Even making some kind of entry-list might generate some good publicity.  With beta starting within the next week or two, I could use a little press.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2007/09/airderbyentries/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>XRay Viewer</title>
		<link>http://www.rogue-development.com/blog2/2007/08/xray-viewer/</link>
		<comments>http://www.rogue-development.com/blog2/2007/08/xray-viewer/#comments</comments>
		<pubDate>Wed, 29 Aug 2007 21:00:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[XRay]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=50</guid>
		<description><![CDATA[A lot of the time a designer gives me a swf, and I want to know how they structured it.  I have two options.
1) Open up the Flash IDE and explore it 2) Add an instance of it to my project, and then use XRay to explore it.
Now, I have a third option.  [...]]]></description>
			<content:encoded><![CDATA[<p>A lot of the time a designer gives me a swf, and I want to know how they structured it.  I have two options.</p>
<p>1) Open up the Flash IDE and explore it <br />2) Add an instance of it to my project, and then use XRay to explore it.</p>
<p>Now, I have a third option.  I can open it up in the XRayViewer AIR application I just put together and then use XRay to look through it.</p>
<p><a href="http://www.rogue-development.com/blog/XRayViewer.air">XRayViewer.air</a></p>
<p>All this little app does is host the XRay connector and let you load a local swf (File->Open).  Then it displays the swf with some simple controls to play/stop/advance/back.  </p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.rogue-development.com/blog/uploaded_images/xrayviewer-732582.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://www.rogue-development.com/blog/uploaded_images/xrayviewer-732579.jpg" border="0" alt="" /></a></p>
<p>But the real power is you can go off to the XRay interface and look through that loaded swf!</p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.rogue-development.com/blog/uploaded_images/xray-767455.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://www.rogue-development.com/blog/uploaded_images/xray-767447.jpg" border="0" alt="" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2007/08/xray-viewer/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>AgileAgenda progress</title>
		<link>http://www.rogue-development.com/blog2/2007/08/agileagenda-progress/</link>
		<comments>http://www.rogue-development.com/blog2/2007/08/agileagenda-progress/#comments</comments>
		<pubDate>Sat, 25 Aug 2007 13:40:00 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[AgileAgenda]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://rogue-development.com/blog2/?p=49</guid>
		<description><![CDATA[With the release of AlivePDF, I&#8217;ve started on the printed reports of the project, arguably one of the most important features of software like this.  Here is a sample report for the first few hours of working on this stuff.  I&#8217;m quite pleased with how easily and quickly it was to develop that. [...]]]></description>
			<content:encoded><![CDATA[<p>With the release of <a href="http://www.alivepdf.org/">AlivePDF</a>, I&#8217;ve started on the printed reports of the project, arguably one of the most important features of software like this.  Here is a <a href="http://www.agileagenda.com/sample.pdf">sample report</a> for the first few hours of working on this stuff.  I&#8217;m quite pleased with how easily and quickly it was to develop that.  It needs a lot of work visually, but I think it&#8217;s actually a useful report.  When printing these out you can choose which sections of the report will go in.  Eventually I want to get the outline/bookmark PDF features working to make it easy to jump around in the document.  I still have to tackle printing out the gantt style chart, but that&#8217;s for another day.  (Note on sample&#8230; that project is an amazingly simple project not really needing software like this.  I&#8217;ve also been using this software for a project I&#8217;ve been working on at my &#8220;real job&#8221; and that is actually useful)</p>
<p>I&#8217;ve also been working with a young designer from France on some of the visual aspects of the software.  He&#8217;s been making icons for a while now and agreed to let me use some of them in my project.  On top of that he did a mockup on a screen that took my thoughts on design to a completely new direction.  He&#8217;s working on a project of his own as well, I&#8217;ll make sure to post about it when it&#8217;s ready.  Here&#8217;s an example of what the software might look like come release time:</p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.rogue-development.com/blog/uploaded_images/mockup-770602.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://www.rogue-development.com/blog/uploaded_images/mockup-770596.png" alt="" border="0" /></a></p>
<p>Even that look still has a couple rounds of revisions left, but it&#8217;s getting closer.</p>
<p>We&#8217;re still accepting <a href="http://www.agileagenda.com/betaSignup.html">beta applications</a> for anyone interested in trying this stuff out in the first round of beta.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rogue-development.com/blog2/2007/08/agileagenda-progress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
