Mobile Optimizations with Adobe AIR

Squeeze some extra frames per second out of your app with some basic optimizations. In many cases your target device will have a 1Ghz processor and less then 100Mb of available ram. Trying to utilize more processing power or RAM than this will lead to erratic app behavior and in many cases will cause the application to crash.

Blitting – Moving Bitmaps

Attempting to move display objects around during transitions can be very slow and choppy. Moving Bitmaps is much faster and can provide a smooth animation. When using this technique there are two things to consider; speed and memory.

Speed
Creating BitmapData from a DisplayObject is CPU intensive. Your user will notice even a fraction of a second delay in a transition. One solution to this is to predict where the user will go and store the BitmapData up front. For example, you know the first page they will hit after the splash screen is the login page. While the user is on the splash screen take a snap shot of the login page. Once they’ve arrive at a new view, take a snap shot of the previous and next views.

Memory
BitmapData is expensive. Caching to much BitmapData is the fastest way to slow down and crash your app. Make sure to call destroy on any unused BitmapData or re-use the same two or three instances. Another technique is to use a matrix to take a picture of the screen at half the resolution. You save both processing power and memory when doing this. During transitions on a device with high DPI this is often un-noticed by the user.

How much memory are you using? Use the profiler in Flash Builder to check for leaks and check out Memory Doctor on the iOS store. Version 5 of iOS is said to include app memory monitoring as well.

More information on blitting can be found on Jesse Freeman’s blog: http://flash.developerartofwar.com/

CPU vs GPU

There are plenty of sites that explain the precise difference between these two rendering modes. In the end how should you decide? Guess and check. With AIR 2.7 increasing the performance of CPU on iOS by 4 times, I’ve found that many of my apps perform better and use less memory with CPU.

Run your app with one than check the other. I found that before 2.7, my app ran better with CPU mode for Android and Blackberry but faster in GPU mode on iOS. Now that 2.7 is out, it runs better with CPU on all three. Selecting GPU mode can cause the application to consume as much as twice the memory. My app used 100Mb of memory in GPU mode and only 56Mb in CPU mode.

Avoid Transparency Like the Plague

Changing the alpha on display objects will significantly cut the performance of your app. Keep everything at 100% alpha and minimize the number of transparent PNGs you use. Similar to alpha, adding filters to your display objects will also decrease performance and increase memory usage. Is that drop shadow, beveled, semi-transparent text really worth it?

Destroy Your Display Objects

This part gets complicated. It can be beneficial to re-use display objects rather than re-creating them, for example in a list control. One thing to keep in mind is that these controls consume lots of memory. Keeping a ScrollPane, List, Grid and Picker around in memory all at once will crash your app. Re-use instances when possible but never keep around expensive components when your done with them.

There are plenty more optimizations that you can make in the world of mobile. The list above is what got me through my latest app for a client. Flex Hero handles some of the transitions and memory management for you and with AIR 2.7 it performs quite well. Please post any additional optimizations you’ve found helpful when building mobile apps with AIR.

Detailed Review of the PlayBook (Including Videos)

Skeptical about the PlayBook? In this review we’ll size up the new BlackBerry PlayBook and show of some videos of the device in action. Leaving you with the opportunity to make your own decision by highlighting both the pros and cons. Despite what some people would have you believe, there is no one device that fits everyone’s needs. Before purchasing this tablet, I tried out the iPad2, the Motorola Xoom, the PlayBook and the Galaxy Tab. This review will get you started but I’d recommend trying each device before shelling out the cash.

Overview:
The PlayBook is a 7 inch tablet that has a great browser and specs that compare with many of the other current generation tablets. The operating system is fast, responsive and hasn’t crashed once in the four days I’ve had the device. Task management is made simple and I really like how easy it is to switch between apps shut down an app. After using this device for even just a few minutes the gestures felt natural. I picked up a Xoom the next day and wanted to use the swipe gestures to navigate.

Video Demo: High Level Overview

Video Demo: Games

Video Demo: The Keyboard

The Good:
>Swipe gestures and multi-tasking actually feel like a tablet rather than a big phone
>The operating system is fast
>Full web browsing is great with both Flash and HTML5
>Over the AIR updates (approx 245 MB) that finish in under 30 minutes
>Battery life is great, even when viewing lots of Flash content in the web
>My preferred size is 7 inches for a tablet, on the bus I use my thumbs to type on the keyboard
>The web browsing experience is great, you don’t need a million apps with a browser like this
>Mirco HDMI out and micro USB port

The Bad:
>I tried connecting a Bluetooth stereo gateway and mouse with no luck
>Light boxes in HTML content don’t always play well with the keyboard
>The power button is hard to push, you won’t ever accidentally turn this thing on…
>Apps that force orientation change can be frustrating
>No removable battery
>Maximum timeout is 5 minutes

Getting Started:

First thing after turning the device on, it does an over the air update which takes about 30 min depending on your wifi connection speed. After the update there is a brief tutorial on how to use the swipe gestures followed by a form where you must enter an e-mail and password to create an app world account. After you create an account with your e-mail the device is ready to go.

When you plug the device into your computer for the first time it will show up as a CD Rom drive. How cool is that? Just run the auto run, install the drivers, re-plug the device and it’s recognized as a tablet with full file system access. Don’t have a computer? That’s fine. They PlayBook works out of the box without needing a computer. Don’t want to supply your credit card? That’s fine too. I’ve been downloading free apps and using the device without ever giving credit card info. When you want to purchase an app you have the option to use PayPal as well. The getting started experience was much better than Android and iOS which both require a credit card.

Power / Battery Life:

I was using the device quite frequently over a 48 hour period before having to charge it. The device is rated at 10 hours of continual use and has many power options that assist with customizing the device on performance vs. battery life. There are two options that are missing, the ability to set the screen timeout past 5 minutes and the ability to play music from the browser when the screen turns off. The built in music player will play with the screen off but music playing in the browser stops when the screen times out (after 5 minutes). I’d imagine this is fairly easy to fix on RIM’s part, hopefully we’ll see a solution for this in a future OS release. For now, you’ll have to stick with the built in music player or tap your device every 5 minutes when playing Pandora in the browser.

Notice: The tablet will not charge via standard USB while the device is on. Batteries in all tablets have a much higher drain than phones and a much higher capacity (5300mAh vs 1200mAh). Since USB only supplies a max of 500mA the charge rate is slower than the consumption rate of the device. Basically it would be like trying to charge your laptop via USB, which you’d never expect to be able to do. Charge the device while it’s on is the supplied 5V, 1.8A charger or try using a high powered USB port.

The App World:

The App World is very easy to navigate and has what I would consider a large amount of apps for a new to market device. The apps range in quality but there are definitely a number of great apps in the market already. Apps range in size from 1MB (Doodle Blast) to 343MB (Need for Speed). The update process is simple and easy.

Many of the base applications like Twitter and Gmail are in the browser right now instead of in an app. I actually prefer this. The JavaScript and Flash rendering on the device is great. I was able to navigate and write an entire blog post using WordPress in the browser on the device. Aside from light boxes acting a little goofy, web browsing is the way to go for apps that you might be missing. When I can play games, watch tv and check my mail in the browser, why do I need an app for that?

The one app / webpage that is missing right now is Netflix. They use Silverlight which isn’t supported on the PlayBook and they don’t have an app. Every other webpage I frequent works great.

Swipe Gestures / Multi-tasking:

After trying out an iPad2 and Xoom, the PlayBook felt the most like a tablet. Why is that? Mostly due to the swipe gestures and multi-tasking. I know the iPad2 has 5 finger gestures to navigate apps and both have multi-tasking. The PlayBook just makes it really easy to visualize your apps. This is one is going to be more of a personal preference and something you’ll have to experience for yourself.

When you hold a PlayBook, swipe up from the bottom black bar to pull up your apps, swipe from the left and right black bars to navigate your apps, swipe in from the top left corner to pull down the status bar and down from the top black bar for the app specific settings. There is a great, quick tutorial on this when you turn the device on. Once you used the PlayBook for a few minutes you’ll be trying to use swipes on every other tablet you hold.

The Keyboard:

Using the keyboard while riding the bus is easy as all of the keys are accessible easily while holding the device with two hands. Bring up (or close) the keyboard at anytime by swiping in from the bottom left corner. Tap and hold a key to bring up alternate characters. It is possible to type on the keyboard with all fingers while in landscape mode but I would only do it for short periods of time. Typing lengthy articles on any touch screen device is a pain. I’ve read that you are able to attach a Bluetooth keyboard to the device but haven’t been able to test that yet.

What BlackBerry Needs to Fix:
>Better light box support in the browser with the keyboard
>A complete set of Bluetooth drivers for common peripherals (stereo gateway)
>Music in the browser should play when the screen is off
>Allow apps to force orientation but don’t update the actual swipe orientation until the device is turned

Summary:
This is a very solid device and is my preference when compared to the iPad2 and Xoom. I would recommend trying out all tablets before you make a decision. To me, the iPod touch is the least intuitive device I own. To others, the iPod is very intuitive. There is no single device that meets everyone’s needs. Try them all and buy the one that suites you.

Enjoy!

Keyboard comparison:

My devices:

Requesting Permissions for your PlayBook App

Does your PlayBook app use local storage, camera roll, media sound or other device APIs? If so, you must add action requests in your blackberry-tablet.xml file when publishing your BAR file for these features to work on the device.

Problem:
The camera roll in my painting application worked with the virtual machine (0.9.4 SDK) but didn’t work on the actual device.

Solution:
I added acess_shared to my blackberry-tablet.xml file and the camera roll worked great. The device prompts on first run notifying the user of which permissions you requested, similar to how Android works.

BlackBerry has a list of actions documented here:
http://docs.blackberry.com/en/developers/deliverables/23959/Overview_1352483_11.jsp#Accessing_secure_APIs_1524628_11

Here is a photo of items added to my camera roll:

Stay tuned for a full video review of the PlayBook coming this week.

Blog post created on my PlayBook

iOS, Android and BlackBerry in a Single Click with ANT

***Update: Use package.blackberry OR install.blackberry when running the ANT task, using both will overwrite the BAR file and remove signing. Verify your BAR is signed by renaming it from app.bar to app.zip, extract and ensure you have META-INF/AUTHOR.EC and META-INF/RDK.EC included in the zip.***

Create your market ready AIR apps for iOS, Android and the BlackBerry PlayBook in a single click using the same code. This ANT task compiles, signs and pushes out to attached devices (iOS requires dragging into iTunes). All of the signed apps created with this ANT task can be published to the market.

Overview:
The AIR 2.6 SDK is great but doesn’t have full Flash Builder support yet. This ANT task can be used in Flash Builder, Flash Develop, FDT or even the command line. Using Flash Develop, you can create apps for all devices without paying for expensive software!

Pre-requisites:
You will need to install Flash Builder Burrito, the BlackBerry PlayBook SDK, the AIR 2.6 SDK and acquire signing keys for all three devices. If using Flash Develop, you will need to follow some additional steps for ANT integration. You’ll also want to download the base project from Google Code: http://code.google.com/p/air-mobile-tools/

Video Tutorial:

Wiki:
The wiki on Google code contains more information on getting started with this base project: http://code.google.com/p/air-mobile-tools/wiki/BaseMobileActionScriptProject

ANT Task:

<?xml version="1.0" encoding="UTF-8"?>
<!--
MIT License:
Copyright (c) 2010 Christopher Black

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sub license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Resources:
http://www.terrenceryan.com/blog/post.cfm/using-ant-to-package-the-same-air-app-to-multiple-devices
http://technophi.com/2011/03/08/using-ant-to-compile-a-flex-mobile-project-for-ios/
http://www.adobe.com/devnet/flex/articles/flex_ant_pt1.html
http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-5d0f4f25128cc9cd0cb-7ffb.html
-->
<project name="Box2D" default="main" basedir="."><property name="environment" value="local" /><property file="settings.properties"/>

<!-- Path to the Flex task libraries. -->
<path id="flextasks.classpath">
  <fileset dir="${FLEX_HOME}/ant/lib">
    <include name="*.jar"/>
  </fileset>
</path>
<typedef resource="flexTasks.tasks" classpathref="flextasks.classpath" />

<!-- Add dependencies here (android, blackberry, apple) or uninstall.blackberry -->
<target name="main" depends="android, blackberry, apple" />
<target name="android" depends="prepPackage, package.android, install.android" />
<!-- Use package.blackberry OR install.blackberry, using both will overwrite the .bar file and remove signing. -->
<target name="blackberry" depends="prepPackage, package.blackberry" />
<target name="apple" depends="prepPackage, package.apple" />
<target name="clean">
  <echo message="Cleaning Build Space"/>
  <delete dir="${build.dir}"/>
</target>
<target name="prepPackage" depends="compile,handleDevices" />
<target name="compile" depends="clean">
  <echo message="Compiling swf"/>
  <mxmlc file="${projectFile}" output="${swfFile}" optimize="true" configname="airmobile" debug="false">
    <load-config filename="${FLEX_HOME}/frameworks/airmobile-config.xml"/>
    <source-path path-element="${FLEX_HOME}/frameworks"/>
    <static-link-runtime-shared-libraries />
    <compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
      <include name="libs/*" />
    </compiler.library-path>
    <compiler.library-path dir="${basedir}/libs" append="true">
      <include name="*" />
    </compiler.library-path>
  </mxmlc>
</target>

<!-- Create Android directory. -->
<target name="collect.android">
  <echo message="Creating device folder for Android"/>
  <mkdir dir="${build.dir}/android"/>
  <echo message="Copying SWF for Android"/>
  <copy file="${cert.dir}/androidcert.p12" todir="${build.dir}/android" />
  <copy file="${swfFile}" todir="${build.dir}/android" />
  <echo message="Copying Application Description File for Android"/>
  <copy file="${dev.dir}/${app.name}-app.xml" todir="${build.dir}/android" preservelastmodified="true" />
  <copy todir="${build.dir}/android/assets">
    <fileset dir="${dev.dir}/assets" />
  </copy>
  <echo message="Modifying application description file"/>
  <replace file="${build.dir}/android/${app.name}-app.xml">
    <replacefilter token="${contentText}" value="${app.name}.swf" />
  </replace>
</target>
	
<!-- Create BlackBerry directory. -->
<target name="collect.blackberry">
  <echo message="Creating Device Folder for BlackBerry"/>
  <mkdir dir="${build.dir}/blackberry"/>
  <echo message="Copying SWF for BlackBerry"/>
  <copy file="${swfFile}" todir="${build.dir}/blackberry" />
  <copy file="${cert.dir}/${bb.cert}" todir="${build.dir}/blackberry" />
  <echo message="Copying Application Description File for BlackBerry"/>
  <copy file="${dev.dir}/${app.name}BlackBerry-app.xml" todir="${build.dir}/blackberry" preservelastmodified="true" />
  <copy file="${dev.dir}/blackberry-tablet.xml"
  	todir="${build.dir}/blackberry" preservelastmodified="true" />
  <copy todir="${build.dir}/blackberry/assets">
    <fileset dir="${dev.dir}/assets" />
  </copy>
  <echo message="Modifying application description file"/>
  <replace file="${build.dir}/blackberry/${app.name}BlackBerry-app.xml">
    <replacefilter token="${contentText}" value="${app.name}.swf" />
  </replace>
</target>
	
<!-- Create Apple directory. -->
<target name="collect.apple">
  <echo message="Creating device folder for apple"/>
  <mkdir dir="${build.dir}/apple"/>
  <echo message="Copying SWF for Apple"/>
  <copy file="${swfFile}" todir="${build.dir}/apple" />
  <copy file="${cert.dir}/${apple.cert}" todir="${build.dir}/apple" />
  <copy file="${cert.dir}/${apple.provision}" todir="${build.dir}/apple" />
  <echo message="Copying Application Description File for Apple"/>
  <copy file="${dev.dir}/${app.name}Apple-app.xml" todir="${build.dir}/apple" preservelastmodified="true" />
  <copy todir="${build.dir}/apple/assets">
    <fileset dir="${dev.dir}/assets" />
  </copy>
  <echo message="Modifying Application Description File"/>
  <replace file="${build.dir}/apple/${app.name}Apple-app.xml">
    <replacefilter token="${contentText}" value="${app.name}.swf" />
  </replace>
</target>
	
<target name="handleDevices" depends="collect.android, collect.blackberry, collect.apple"/>
<target name="package.android">
  <echo message="Packaging for Android ${cert}"/>
  <exec executable="${ADT}" dir="${build.dir}/android">
    <arg value="-package"/>
    <arg line="-target apk"/>
    <arg line="-storetype pkcs12"/>
    <arg line="-keystore ${cert}" />
    <arg line="-storepass ${cert.password}" />
    <arg value="${app.name}"/>
    <arg value="${app.name}-app.xml"/>
    <arg value="${app.name}.swf"/>
    <arg line="assets" />
  </exec>
</target>
<target name="package.blackberry">
  <echo message="Packaging for BlackBerry"/>
  <exec executable="${BBPackager}" dir="${build.dir}/blackberry">
    <arg value="-package"/>
    <arg value="${app.name}.bar"/>
    <arg value="${app.name}BlackBerry-app.xml"/>
    <arg value="blackberry-tablet.xml"/>
    <arg value="${app.name}.swf"/>
    <arg line="assets" />
  </exec>
  <exec executable="${BBSigner}" dir="${build.dir}/blackberry"> 
  	<arg value="-verbose"/>
  	<arg line="-cskpass ${bb.cert.password}"/>
  	<arg line="-keystore ${bb.cert}"/>
  	<arg line="-storepass ${bb.store.password}"/>
  	<arg value="${app.name}.bar"/>
  	<arg value="RDK" />
  </exec>
  <exec executable="${BBSigner}" dir="${build.dir}/blackberry"> 
	<arg line="-keystore ${bb.cert}"/>
	<arg line="-storepass ${bb.store.password}"/>
	<arg value="${app.name}.bar"/>
	<arg value="author" />
  </exec>
</target>
<target name="package.apple">
  <exec executable="${ADT}" dir="${build.dir}/apple">
    <arg line="-package -target '${apple.target}'" />
    <arg line="-provisioning-profile '${apple.provision}'" />
    <arg line="-storetype pkcs12" />
    <arg line="-keystore '${apple.cert}'" />
    <arg line="-storepass '${apple.cert.password}'" />
    <arg line="'${app.name}.ipa'" />
    <arg line="'${apple.descriptor}'" />
    <arg line="'${app.name}.swf'" />
    <arg line="assets" />
  </exec>
</target>
<target name="install.android">
	  <echo message="Uninstalling attached Android Device"/>
	  <exec executable="${ADT}">
	    <arg line="-uninstallApp"/>
	    <arg line="-platform android"/>
	  	<arg line="-appid '${app.name}'"/>
	  </exec>
  <echo message="Installing onto attached Android Device"/>
  <exec executable="${ADT}">
    <arg line="-installApp"/>
    <arg line="-platform android"/>
    <arg line="-package '${build.dir}/android/${app.name}.apk'"/>
  </exec>
  <echo message="Launching on attached Android Device"/>
  <exec executable="${ADT}">
    <arg line="-launchApp"/>
    <arg line="-platform android"/>
    <arg line="-appid '${app.name}'"/>
  </exec>
</target>
<target name="uninstall.blackberry">
  <echo message="Uninstalling from Blackberry VM"/>
  <exec executable="${BBDeploy}" dir="${build.dir}/blackberry">
    <arg value="-uninstallApp"/>
    <arg value="-device"/>
    <arg value="${bb.ip}"/>
    <arg value="-password"/>
    <arg value="${bb.password}"/>
    <arg value="-package"/>
    <arg value="${app.name}.bar"/>
  </exec>
</target>
<target name="install.blackberry">
  <echo message="Installing onto Blackberry VM"/>
  <exec executable="${BBPackager}" dir="${build.dir}/blackberry">
    <arg value="-package"/>
    <arg value="${app.name}.bar"/>
    <arg value="-installApp"/>
    <arg value="-launchApp"/>
    <arg value="${app.name}BlackBerry-app.xml"/>
    <arg value="blackberry-tablet.xml"/>
    <arg value="${app.name}.swf"/>
    <arg value="-device"/>
    <arg value="${bb.ip}"/>
    <arg value="-password"/>
    <arg value="${bb.password}"/>
    <arg value="assets"/>
  </exec>
</target>
</project>
flex.path = C:/Program Files (x86)/Adobe/Flash Builder Burrito/Adobe Flash Builder Burrito/sdks
flex.sdkVersion= 4.5.0_air
flex.sdkPath= ${flex.path}/${flex.sdkVersion}
FLEX_HOME= ${flex.sdkPath}
BB_HOME = ${flex.path}/blackberry-tablet-sdk-0.9.4
contentText = [This value will be overwritten by Flash Builder in the output app.xml]

ADB = C:/Users/Chris/Desktop/Froyo/android-sdk-windows/platform-tools/adb.exe
ADT = ${flex.sdkPath}/bin/adt.bat
adt.path = ${flex.sdkPath}/bin/
IPHONE_PACKAGER = adt

BBDeploy = ${flex.path}/blackberry-tablet-sdk-0.9.4/bin/blackberry-deploy.bat
BBPackager = ${flex.path}/blackberry-tablet-sdk-0.9.4/bin/blackberry-airpackager.bat
BBSigner = ${flex.path}/blackberry-tablet-sdk-0.9.4/bin/blackberry-signer.bat
bb.ip = [PLAYBOOK_IP]
bb.password = [YOUR_PASSWORD]

## Directories
build.dir = bin-release
dev.dir = ${basedir}/src
cert.dir = ${basedir}/certs
app.name = BaseMobileActionScriptProject

## mxml or as
app.type = as

## Apple cert info: ipa-test | ipa-debug | ipa-app-store | ipa-ad-hoc
apple.target = ipa-ad-hoc
apple.cert = [APPLE_CERT_NAME].p12
apple.cert.password = [CERT_PASSWORD]
apple.provision = [PROVISION_NAME].mobileprovision
apple.descriptor = ${dev.dir}/${app.name}Apple-app.xml

## Android cert info
cert = [ANDROID_CERT_NAME].p12
cert.password = [YOUR_PASSWORD]

## PlayBook cert info
bb.cert = [BB_CERT_NAME].p12
bb.cert.password = [YOUR_PASSWORD]
bb.store.password = [YOUR_STORE_PASSWORD]
bb.descriptor = ${dev.dir}/${app.name}BlackBerry-app.xml

## General
swfFile=${build.dir}/${app.name}.swf
projectFile=${dev.dir}/${app.name}.${app.type}

Resources:
http://www.terrenceryan.com/blog/post.cfm/using-ant-to-package-the-same-air-app-to-multiple-devices
http://technophi.com/2011/03/08/using-ant-to-compile-a-flex-mobile-project-for-ios/
http://www.adobe.com/devnet/flex/articles/flex_ant_pt1.html
http://help.adobe.com/en_US/air/build/WSfffb011ac560372f-5d0f4f25128cc9cd0cb-7ffb.html