The Challenge
There’s much talk of creating content once with Adobe Flash and running it just about anywhere. Now anyone who’s had experience writing Flash content for mobile will know that it’s not that simple (all devices aren’t equal after all) but hey, I’m always up for a challenge and thought I’d try and port some web-based content to a wide range of handsets.
So what to port? Well I recently posted about the WeeWorld Fame Game, which we released a few weeks back, and thought that it would be an ideal candidate. Now I appreciated the sensible thing would be to plan with mobile in mind from the outset but I was genuinely interested to see how difficult it would be to take content that was designed primarily for the web.
Now if you can’t be bothered reading on – it’s quite a long post – or don’t have the time then why not just watch the video above where you can see the results of my little experiment. If you want to know more then read on.
The Devices
The first step was to decide on some phones. I could just have picked a bundle of devices that supported the same Flash runtime but that would have been cheating so I went with the following handsets and flavours of Flash:
- iPhone & iPod touch – Adobe AIR / ActionScript 3
- Google Nexus One – Adobe AIR / ActionScript 3
- Nokia 5800 XpressMusic – Flash Lite 3.1 / ActionScript 2
- Nokia N95 – Flash Lite 2.0 / ActionScript 2
- Nokia 5310 XpressMusic – Flash Lite 2.1 / ActionScript 2
Now that the handsets had been selected it was time to actually do some work.
ActionScript 3 to ActionScript 2
From the device list above there’s an obvious problem. In order to work on the Flash Lite handsets the Fame Game needed to be ported from AS3 to AS2. This was by far the biggest obstacle and took a few days to re-write. Maintaining two code bases for a project is hardly ideal but considering the extra device coverage it would give it was worth the effort.
Sure, Flash Lite 4 supports ActionScript 3. However until Flash Lite 4 devices start to gain some penetration most developers will probably have to fall-back to lower versions of Flash Lite, which unfortunately means using ActionScript 2 for the time being.
We’re clearly in a transitional phase for Flash and mobile. Flash Lite was a very good toe in the water for Adobe but considering the pace at which people upgrade their handsets, it’s clear that ActionScript 2’s days are numbered. From this point onwards devices are going to support either Adobe AIR (high-end devices) or Flash Lite 4 (lower-end devices) both of which support ActionScript 3.
However for the time being you’ll probably have to stick with AS2 to capture as wide an audience as possible.
Layout
One major headache for any mobile developer, no matter what language they’re using, is the fact that screen dimensions vary wildly across devices. Ensuring your application fits all these different screens is difficult enough when considering mobile from the outset, but I had the added problem of working with something that had originally been designed for the web where one size fits all.
Thankfully the Fame Game’s original layout was such that it could quite easily be tailored for different dimensions. The big question was whether to write code to dynamically alter the layout on-the-fly or to simply code for each screen. I opted to code for and create separate builds for each screen. I felt this would give me more control over the layout and with minimal effort.
This also allowed me to create multiple FLAs – one for each target device. Although the original code base performed much of the layout, where appropriate, layout was taken care of on the Stage. The visual assets themselves were all pre-sized and stored in the library. By creating multiple FLAs I was able to re-purpose the original artwork for each of the target screens, without resorting to bundling multiple versions of the same artwork into the one FLA.
Now you might think that coding for multiple screen layouts would bloat the final build size. After all, if you target five difference screen sizes then surely you’d have to include in the final SWF code to perform the layout for all five screens? Well I managed to avoid that by creating separate layout classes for each screen and ensuring that each build pointed to only the layout class that was required.
Here’s roughly how the folder structure looked for this code:
src/platform/android/Layout.as
src/platform/iphone/Layout.as
src/platform/web/Layout.as
The important thing to note from the folder structure above is that although each class is in a different folder, they all have identical fully-qualified class paths. Essentially it is the same class but in three different locations. Each class holds static data that is used to define layout information related to a particular device’s screen dimensions.
Now to target the Google Nexus One I simply added a class path to its FLA’s publish profile that pointed to src/platform/android
. For the iPhone FLA I added a class path that pointed to src/platform/iphone
, and for the standard web version’s FLA I added a class path to src/platform/web
.
The final step was to work my way through the existing Fame Game code and replace any layout-specific code with calls to the Layout class. So whereas before there might have been screen-specific code that looked like this:
// Position the WeeMee just off-screen.
weemee.x = -340;
weemee.y = -30;
We now have the following screen-independent code, where the Layout class used is determined by the class path set in the publish profile:
// Position the WeeMee just off-screen.
weemee.x = Layout.weemee.x;
weemee.y = Layout.weemee.y;
With this implementation, any new screen sizes can be implemented without bulking up the final SWF size. It also provides tighter control over the layout compared to a dynamic layout implementation.
The WeeMees
Central to the WeeWorld site is the WeeMee avatar and it’s these little cute characters you get to vote for in the Fame Game. WeeMees are dynamically generated on our server using Blue Pacific’s Turbine and served as Flash 7 SWFs with a smattering of ActionScript 2 used to perform certain animations and effects.
Although this approach works a treat on our live site things were a little different for my mobile versions. Only the Nokia 5800, which supports Flash Lite 3, was able to actually load the WeeMee SWFs.
Both the N95 and the Nokia 5310 were restricted to Flash Lite 2.x, which had some rendering issues with the WeeMees. AIR for iPhone does not support the loading of external SWFs that contain ActionScript so SWFs were out of the question for that. And although AIR for Android can load external SWFs it only supports SWFs with ActionScript 3, so WeeMee SWFs were a no-no there too.
Thankfully at WeeWorld we can fall-back to using PNGs of our WeeMees, which turned out to be quite handy for this challenge. So for the iPhone and Google Nexus One versions I changed the config settings for each to request PNG WeeMees from the server.
Unfortunately the Flash Lite runtimes on both the Nokia N95 and 5310 didn’t support PNGs so a few additional changes had to be made. Instead of serving PNGs to these devices some code was written on the server to convert the PNGs to JPEG. This had one side-effect – any transparency behind the WeeMee was lost, which in turn blocked-out the nice gradient background within the app and generally looked quite ugly.
It wasn’t a big deal though. For these two devices I removed the gradient background and replaced it with a solid colour. I then ensured that the same colour was rendered behind the WeeMee JPGs that were now coming from the server. It worked quite well and most people wouldn’t have been aware of the changes when using it.
You might think that this all sounds like a huge amount of ActionScript changes were required for each target device. However, the reality was that the work was really all done on the server, and the ActionScript itself actually remained relatively unchanged.
Keypad Support
The final hurdle was to add keypad support for the Nokia N95 and Nokia 5310. The other devices supported touch-screen meaning that no code changes were required from the original web version – both AIR and Flash Lite 3 can handle the touch events as if they are mouse events, which in my case was a major time saver.
Keypad support was required to allow the user to move between the three voting icons and make a selection. The voting icons were all managed by a VoteIcons
class, and adding keypad support wasn’t that difficult. These changes were only made to the ActionScript 2 code base since all the ActionScript 3 builds were for touch screen phones.
The first step was to move VoteIcons
into the root of the platforms
folder that was first created to help with layout. The class was then renamed to VoteIconsBase
and a new method named onKeyDown
was added. The top-level application class was then made to listen for key events and pass them to the VoteIconsBase
class.
Within each of the platform specific folders a new class was created called VoteIcons
that extended VoteIconsBase
. The folder structure looked like this:
src/platform/ VoteIconsBase.as n5310/ VoteIcons.as n95/ VoteIcons.as n5800/ VoteIcons.as
The implementation for onKeyDown
within VoteIconsBase
does nothing. Instead it relies on the sub-classes overriding it. Since the Nokia 5800 is a touch-screen device, it's sub class does nothing with the onKeyDown
method. Both the Nokia 5310 and Nokia N95 versions of VoteIcons
however do have implementations for this method, ensuring that the key events are handled and the correct icon is highlighted and selected.
As with the layout handling, certain class paths had to be added to each FLA's publish profile depending on the target device.
Every FLA required the VoteIconsBase
class, so the following was added to each FLA's class path: /src/platform
.
Then one additional class path was added depending on the target device. So the Nokia 5800's publish profile was pointed towards /src/platform/n5800
; the Nokia 5300 FLA looked for the VoteIcons
class in /src/platform/n5300
; and the Nokia N95 build got its code from /src/platform/n95
.
Optimisation
While porting to the various mobile devices I attempted not to optimise the code - I felt it went against the spirit of the challenge. However I did allow myself to make some tweaks to each of the FLAs where I felt it might help device performance.
With the exception of the Google Nexus One I reduced the frame rates to suit each device:
- Google Nexus One - 30fps
- iPhone - 16fps
- Nokia 5800 XpressMusic - 16fps
- Nokia N95 - 12fps
- Nokia 5310 XpressMusic - 12fps
When repurposing the graphics for each FLA I was careful to ensure that all library clips were already scaled to fit the device's screen - Resizing instances on the stage is a very bad idea and can seriously hurt performance on mobile.
The iPhone's FLA also got some extra attention. I replaced some of the vector graphics with bitmap versions (I really should have done this for all devices) and also set many of the movie clip instances to 'Cache as bitmap' ensuring that they got stored on the iPhone's GPU for faster rendering.
I could have spent more time on the iPhone version to bring its frame rate up to 30fps, but it would have required code changes and considering Apple's ban on Flash content anyway I felt it wasn't worth the effort, and as I had stated before it went against the spirit of the challenge.
Coverage
So I ended up with the Fame Game running on five different devices. I was also planning on creating a version for my Sony Ericsson W705 but unfortunately it recently died and is now looking down on us from Silicon Heaven.
Now given the sheer number of devices out there, five doesn't seem like that many so let's spend a little time explaining why I selected these devices - it wasn't random you know.
Both the Nokia N95 and Nokia 5800 use the Symbian S60 operating system. For those who don't know, Symbian phones are everywhere and the OS currently holds the lions share of the smartphone market. In the first quarter of this year over 25 million Symbian S60 smartphones were sold. That's 44% of all smartphones sold worldwide in that quarter!
I performed a quick check in Adobe Device Central CS5 and counted 72 Nokia handsets alone that would run the exact same builds of the Fame Game that I deployed to the N95 and 5800. I'm not entirely sure just how many different handsets Nokia has but I'm pretty sure those 72 listed in Device Central would cover a significant number of them. So by targeting Flash Lite 2 and Symbian S60 you're effectively targeting millions of devices.
The Nokia 5310 XpressMusic isn't a smartphone, it's a fairly inexpensive mass market handset that runs the S40 operating system. Device Central listed 35 S40 phones that would run the same build of the Fame Game that was deployed to the Nokia 5310. Again that seems like a fairly good result to me and shows the value in continuing to target Flash Lite in the short term.
Now onto the iPhone/iPod touch. Okay I know Apple has banned any content written in Flash from the App Store but I had my iPod touch lying around and thought it would be a shame not to include it in the challenge. But if Apple were to have a change of heart then the Fame Game would run on the 51 million iPhones and 20 million iPod touches that have been sold over the last 3 years or so.
Finally there's the Google Nexus One, which runs the Android operating system. With 5 million handsets being sold in the first quarter of this year alone Android is gathering some significant momentum and going forward could be the mobile platform of choice for Flash developers.
So you see by carefully targeting a few key handsets I've managed to capture quite a large slice of the mobile space for the Fame Game app.
Conclusion
Okay, so it's clear Adobe isn't quite there yet with its "Write Once, Run Anywhere" vision but I honestly don't think they're that far off - In my case it was "Write Twice, Run on Lots of Devices".
In the short term it's probably still beneficial to target some of the older handsets that only support ActionScript 2, but as Adobe AIR and Flash Lite 4 roll out across more smartphones AS2 will quickly become irrelevant.
The Flash Platform is an excellent development platform and it's comforting to know that you can use the same tools and language to develop across a wide range of devices. Sure there will always be a need for native apps where performance is critical, but for a vast number of projects out there Flash will be an ideal choice.
So exactly how long did it take me to get the Fame Game running on these devices? After all this has turned into a monster blog entry and that might give the misconception that it took quite some time. Here's a breakdown for you:
Task | Hours | Notes |
---|---|---|
Port AS3 to AS2 | 16 | By far the biggest task. |
iPhone | 4 | Layout class, Graphics work. |
Google Nexus One | 3 | Layout class, Graphics work. |
Nokia N95 | 5 | Layout class, Graphics work, Keypad interaction. |
Nokia 5310 | 1 | Layout class. |
Nokia 5800 | 3 | Layout Class, Graphics work. |
Total Time | 32 |
As a side-note, I've always been happy with Nokia's commitment to Flash, and I'm looking forward to getting my hands on a Flash Lite 4 device at some point. It's relatively easy to write Flash content, test it in Device Central then deploy it onto one of their handsets.
It's also comforting to know that this also holds true for Flash development on the Google Nexus One (and hopefully other Android devices). From the relatively short amount of time I've had to play with it I can honestly say it's the easiest device yet to get Flash content installed and running on. The performance of Flash on the Nexus One is also seriously impressive.
So there you have it. Approximately four days effort has produced Flash content that can run on millions of handsets. Impressive stuff if you ask me.
And if you made it all the way to the end then thanks for persevering!
Didn’t you have to write it 3 times though? Web plus the two main phone versions?
The iPhone and Android versions are as good as identical to the web version’s code – just had to re-factor the layout code a little and change the URL for retrieving the WeeMees. So let’s call it “Write x2.1, Run On Lots of Devices” 😉
Also, don’t you end up with a SWF per device? Or am I missing something about how the layout and graphics are bundled?
It’s a good post incidentally, I’m just not certain “Write Once, Run Anywhere” is any more within the grasp of Flash than it is for, say, Java, .Net or JavaScript. At least, not for things with a user interface. It’s one of those developer silver bullet phrases like “there will be cake”.
There seem to be 298 devices listed by Nokia: http://www.forum.nokia.com/Devices/Device_specifications/matrix_all_1.html. However, given that Nokia are going to fade into obscurity in a couple of years, it doesn’t matter all that much 😉 Running on Android is the important one.
More importantly, however, does this mean your free for our little experiment now? 😉 And congrats on your first vocal starring role!
Not quite free to start our little experiment yet. In the meantime I’ll leave it to you to convince Stuart to take part 😉