Using the iPad retina display with Adobe Air

Last Friday, the new iPad was launched by Apple, with its new retina display. I did a few tests to try to use the high-resolution retina screen at its maximum resolution from Adobe Air. Here are the results.

The simple option doesn’t work

The first thing to note is that Apple deliberately limited the new retina resolution to Apps built with the iOS 5.1 SDK. This is to avoid incompatibility issues with Apps that were released before the new iPad was available. So apps built with earlier versions of the iOS SDK use pixel doubling and have an effective resolution of 1024×768 pixels, like the iPad 2.

By default, Adobe Air compiles with iOS 4.0. I don’t know what’s special about iOS 4.0 that Adobe can distribute this version with Air but not later versions, but that’s the way it is. So, if you compile your Air app the normal way, you will not get retina resolution on the new iPad. Everything will still work fine, but it will use pixel doubling to get the same results as on the iPad 2.

Compiling with iOS 5.1

If you have a Mac, there is a solution. Adobe Air (since Air 3.1) includes a build setting to specify the version of the iOS SDK to use. The setting is the platformsdk and you can read more about it on this Adobe blog. If you read through the comments in that post you’ll see that this is only supported when compiling on OSX, at the moment, but Adobe hope to bring it to Windows sometime in the future.

So, if you have a Mac, download and install XCode. In the new XCode, the SDK is inside the application package – the filepath is /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/. Now use the playformsdk setting to build against iOS 5.1.

The test

To test this I built a little app, with just a few lines of code –

package com.sticksports.test
{
  import flash.display.Sprite;
  import flash.display.StageAlign;
  import flash.display.StageScaleMode;
  import flash.events.Event;
  import flash.system.Capabilities;
  import flash.text.TextField;

  public class RetinaTest extends Sprite
  {
    public function RetinaTest()
    {
      stage.scaleMode = StageScaleMode.NO_SCALE;
      stage.align = StageAlign.TOP_LEFT;
      addEventListener( Event.ENTER_FRAME, getStats );
    }
    
    private function getStats( event : Event ) : void
    {
      removeEventListener( Event.ENTER_FRAME, getStats );
      
      var textField : TextField = new TextField();
      textField.width = stage.stageWidth - 40;
      textField.height = stage.stageHeight - 40;
      textField.x = 20;
      textField.y = 20;
      textField.border = true;
      textField.multiline = true;
      addChild( textField );
      
      textField.appendText( "Capabilities.screenResolutionX : " + Capabilities.screenResolutionX + "\n" );
      textField.appendText( "Capabilities.screenResolutionY : " + Capabilities.screenResolutionY + "\n" );
      textField.appendText( "Capabilities.screenDPI : " + Capabilities.screenDPI + "\n" );
      textField.appendText( "stage.stageWidth : " + stage.stageWidth + "\n" );
      textField.appendText( "stage.stageHeight : " + stage.stageHeight + "\n" );
      textField.appendText( "stage.fullScreenWidth : " + stage.fullScreenWidth + "\n" );
      textField.appendText( "stage.fullScreenHeight : " + stage.fullScreenHeight + "\n" );    }
  }
}

I didn’t use Flash Builder for my tests because I’m an FDT user, so the apps were built from Ant scripts. First I built the swf in the standard way.

<exec executable="${sdk.home}/bin/amxmlc" failonerror="true" dir="../package">
  <arg line='-source-path ../src'/>
  <arg line='-default-size=960,640'/>
  <arg line='-default-background-color 0xFFFFFF'/>
  <arg line='-default-frame-rate 60'/>
  <arg line='-debug=false'/>
  <arg line='-optimize=true'/>
  <arg line='-swf-version=13'/>
  <arg line='-output RetinaTest.swf'/>
  <arg line='../src/com/sticksports/test/RetinaTest.as'/>
</exec>

I gave the swf a default size to match the iPhone, just to see what Air gave me as the stage size as a result.

The application descriptor file requests the high resolution display, as for the iPhone retina screen.

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<application xmlns="http://ns.adobe.com/air/application/3.0">

  <id>com.sticksports.RetinaTest</id>
  <filename>RetinaTest</filename>
  <name>Retina Test</name>
  <versionNumber>0.0.1</versionNumber>
  <versionLabel>v0.0.1</versionLabel>
  <copyright>Stick Sports Ltd.</copyright>

  <initialWindow>
    <content>RetinaTest.swf</content>
    <aspectRatio>portrait</aspectRatio>
    <autoOrients>true</autoOrients>
    <fullScreen>true</fullScreen>
    <renderMode>cpu</renderMode>
    <softKeyboardBehavior>none</softKeyboardBehavior>
    </initialWindow>

  <icon>
    <image29x29>icons/icon_29.png</image29x29>
    <image57x57>icons/icon_57.png</image57x57> 
    <image72x72>icons/icon_72.png</image72x72> 
    <image114x114>icons/icon_114.png</image114x114> 
  </icon>
  
  <iPhone>
    <InfoAdditions>
      <![CDATA[
        <key>UIDeviceFamily</key>
        <array>
          <string>1</string>
          <string>2</string>
        </array>
        <key>UIStatusBarStyle</key>
        <string>UIStatusBarStyleBlackOpaque</string>
      ]]>
    </InfoAdditions>
    <requestedDisplayResolution>high</requestedDisplayResolution>
  </iPhone>

</application>

I built the ipa twice, using the Air 3.2 release candidate from Adobe Labs. I built it once using the default version of the iPhone SDK (version 4.0) that is bundled with Air.

<exec executable="${sdk.home}/bin/adt" failonerror="true" dir="../package">
  <arg value="-package"/>
  <arg value="-target"/>
  <arg value="ipa-ad-hoc"/>
  <arg value="-provisioning-profile"/>
  <arg value="${ios.provisioning.profile}"/>
  <arg value="-storetype"/>
  <arg value="pkcs12"/>
  <arg value="-keystore"/>
  <arg value="${ios.keystore.file}"/>
  <arg value="-storepass"/>
  <arg value="${ios.keystore.password}"/>
  <arg value="../publish/default/RetinaTest.ipa"/>
  <arg value="../build/RetinaTest-app.xml"/>
  <arg value="RetinaTest.swf"/>
  <arg value="Default.png"/>
  <arg value="icons"/>
</exec>

And once with the iOS 5.1 SDK

<exec executable="${sdk.home}/bin/adt" failonerror="true" dir="../package">
  <arg value="-package"/>
  <arg value="-target"/>
  <arg value="ipa-ad-hoc"/>
  <arg value="-provisioning-profile"/>
  <arg value="${ios.provisioning.profile}"/>
  <arg value="-storetype"/>
  <arg value="pkcs12"/>
  <arg value="-keystore"/>
  <arg value="${ios.keystore.file}"/>
  <arg value="-storepass"/>
  <arg value="${ios.keystore.password}"/>
  <arg value="../publish/5.1/RetinaTest.ipa"/>
  <arg value="../build/RetinaTest-app.xml"/>
  <arg value="RetinaTest.swf"/>
  <arg value="Default.png"/>
  <arg value="icons"/>
  <arg line="-platformsdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/"/>
</exec>

The equivalent command-line script is

adt -package -target ipa-ad-hoc -provisioning-profile YOUR_PROVISIONING_PROFILE -storetype pkcs12 -keystore YOUR_KEYSTORE_FILE -storepass YOUR_KEYSTORE_PASSWORD RetinaTest.ipa RetinaTest-app.xml RetinaTest.swf Default.png icons -platformsdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/

The results

With the default SDK the results are

Capabilities.screenResolutionX : 768
Capabilities.screenResolutionY : 1024
Capabilities.screenDPI : 132
stage.stageWidth : 960
stage.stageHeight : 640
stage.fullScreenWidth : 768
stage.fullScreenHeight : 1024

I was surprised the stageWidth and stageHeight don’t match the screenResolutionX and screenResolutionY, which is why I use the latter in my projects. As Florian mentioned in the comments, you can also use fullScreenWidth and fullScreenHeight, which I added after reading his comment. Aside from that, there’s no surprises here. The results are the same as on the iPad2.

With iOS 5.1 SDK, the results are

Capabilities.screenResolutionX : 1536
Capabilities.screenResolutionY : 2048
Capabilities.screenDPI : 132
stage.stageWidth : 1536
stage.stageHeight : 2048
stage.fullScreenWidth : 1536
stage.fullScreenHeight : 2048

This version uses the full resolution of the retina screen. The text is half the size on screen because the pixel resolution is doubled and the screenResolutionX and screenResolutionY and fullScreenWidth and fullScreenHeight are the correct size for the retina display. This time, surprisingly, the stageWidth and stageHeight did match the screen resolution – all the more reason not to trust them. Also, the screenDPI is incorrect, showing the same value as the iPad 2.

But, most importantly, the project has access to the full retina screen resolution. Hurrah!

Building with Air 3.1

As I said above, I initially used the public beta of Air 3.2 for this test. I reran the test using Air 3.1 and the results were the same, except building with Air 3.1 and iOS 5.1 gave the stageWidth as 1920px and stageHeight as 1280px. All other results were the same as for Air 3.2.

This entry was tagged , .

48 thoughts on “Using the iPad retina display with Adobe Air

  1. hi richard,

    great article! thank you very much.

    when using fullscreenapps on ios like you do here (true in app-descriptor) stage.stageWidth and stage.stageHeight return strange values. better use stage.fullScreenWIdth and stage.fullScreenHeight.

    do you need osx 10.7 to use the latest ios sdk 5.1?

  2. I thought it was just me regarding stageWidth not being reportedly correctly. I found that in a pure AS3 AIR project it would take several frames to report the correct value in my case only *after* setting Stage.scaleMode/align – even in the constructor. A little temporary enterFrame loop for 3 frames would see the correct value being reported and I could carry on with initialisation.

  3. Hi Florian. I hadn’t thought to use the fullScreenWidth and fullScreenHeight. I’ve added them to the article. Thanks.

    You need OSX 10.7 to run XCode 4.3.1, which includes the iOS 5.1 SDK. However, you don’t actually need to run XCode, you just need the SDK. So if you’re not on 10.7 you could try downloading XCode 4.3.1 from here, then copying the 5.1 SDK out of the bundle and using it directly.

  4. “I don’t know what’s special about iOS 4.0 that Adobe can distribute this version with Air but not later versions, but that’s the way it is” – so do you think Apple will accept any Air originated apps submitted with this workaround? Great article, thanks.

  5. Yes, they do accept apps built this way – I’ve previously used this technique to build with the iOS 5.0 SDK and have released the apps, as have many other developers. It’s not a workaround, it’s the documented way of working. Because Adobe are not allowed to distribute Apple’s iOS 5.1 SDK, you have to get this from Apple. That’s one of the many reasons to register as an iOS developer.

  6. Nice Work Richard.

    To help with folks wanting to use the extra compiler -platformsdk argument from the IDE, take a look at what I put together a while back to leverage interpreter mode in AIR from the Flash IDE:

    http://www.impossibilities.com/v4/2011/06/24/leverage-air-2-7-ipa-test-interpreter-target-mode-for-ios-in-flash-cs-5-5/

    Its basically a small java app I made that acts as a replacement for ADT, accepts arguments and passes them on to the real ADT – I originally made it to decouple ADT from the IDE and add support for the new interpreter mode in AIR 2.7, but it could very easily be modified to also add support for -platformsdk or any other variations on AIR command line arguments.

    I’ve actually made a # of improvements since I posted that version, will try and update the site when I get a chance, but what is posted is a good base for handling this.

  7. I was surprised the stageWidth and stageHeight don’t match the screenResolutionX and screenResolutionY, which is why I use the latter in my projects.

    This may be fine on iOS, but other platforms can have OS chrome, even in full screen mode. The Kindle Fire, for instance. I believe that other Android devices without hardware keys may be like that too. In those cases, stageWidth and stageHeight must be used to display your app at the correct size (although, I didn’t try fullScreenWidth and fullScreenHeight, I don’t think).

    This time, surprisingly, the stageWidth and stageHeight did match the screen resolution – all the more reason not to trust them.

    As another commenter noted, the stage size corrects itself after a moment. It may be wrong on startup, but you’ll get the right value after a few frames. Rather than choosing an arbitrary number of frames to wait, I would simply listen for the resize event on the stage.

  8. Josh – I wasn’t aware of the fullScreenWidth/fullScreenHeight option until Florian mentioned it. That looks like the best choice to me.

  9. I think it’s worth noting that running a regular iPad2 app (say, published using Adobe’s tools) does not “double the pixels”. 1024×768 is not 1/2 as much as 2048×1536. The result is that when they stretch the image on iPad3 is can look WORSE than the same app on iPad2. It’s especially inconsistent when you look at fonts.

    In any event, thanks a lot Richard for this post. And… please Adobe comment on solutions moving forward. I guess I’ll have to go buy a Mac–but I’m far from dropping windows entirely.

  10. Hey Richard, great article and great found, i was getting crazy trying to figure out why… but now there is one main concern… when will this be doable on windows? I wonder if there is a workaround.

  11. Pingback: Adobe AIR??iPad?Retina??? | Flash?????

  12. Hello Richard,
    Thank you very much for this great article.

    Do you know a way for adding retina default images (Default.png)?

    Thanks in advance,
    Marvin

  13. For those working in Flash Builder 4.6, when you do the ‘Export Release Build’ for iOS you can paste the fullpath to the iOS 5.1 SDK in the ‘Native Extensions’ tab section to pick up this iOS 5.1 SDK choice and get retina iPad support.

  14. @Marvin
    I would think you can follow the existing docs for placing launch images in the root of your app sources and use the same established naming conventions.
    Ie, for retina iPad it is:
    Default-Portrait@2x~ipad.png
    Default-Landscape@2x~ipad.png

  15. Hello Jeff,
    Thank you for your answer :)

    I found very detailed information about those launch (default) images here:
    http://tinyurl.com/c5ajjqf

    However I have a very specific problem with the launch images. During the starting process the landscape default image jumps shortly to right and top just before the actual application appears.
    Do you have any idea why this may happen?

  16. Hi, you’re article is simply great!
    I developed a test App and the resolution is awesome!
    There’s only a very big problem: the App seems very slow…

    In my “-app.xml” file I add this code line:
    <renderMode>gpu</renderMode>

    But when I compile it with the terminal using ADT the result is so bad…any suggestions?

    Thanks!

  17. Sara – I find, on the new iPad, that gpu renderMode is much faster than cpu. Unfortunately, on the original iPad it’s much slower, so finding the right compromise is a challenge (it’s a shame we can’t set it at run-time). gpu does render vectors a little differently, which can produce poor results on detailed graphics in particular, but I find it’s usually pretty good. If it’s not good enough on your content, you could try cpu mode and dropping the quality to low – with so many pixels you may not need anti-aliasing. It’s really a lot of trial and error at the moment and trying everything you can think of – tedious but necessary. Probably the best solution is to use Starling or ND2D to render with stage3d, but that may require a lot of reworking of your code.

  18. There is any chance to rebuild/create a new AIR 3.2 with iOS 5.1, so we could use Flash Builder to deploy to iOS without all this stuff and a Mac ?

  19. Quick follow up on my earlier post – with a link to a JSFL tool I am working on:

    https://github.com/rmhall/AIR-Pump

    That JSFL command allows you to quickly pass in the -platformsdk argument and options, compile your swf and compile the AIR file with ADT – all without leaving the IDE. :) Plan to continue working on it and make it into a custom Panel, but wanted to share what I had so far in case it might be useful for anyone.

  20. Thanks for the info. Would you know of any simulators available to test retina display resolution of the iPad3 w/o actually having one.

  21. @Jeff I put the Apple iOS SDK location in the native extension tab and got an error that didn’t couldn’t find the “framework not found UIKit
    Compilation failed while executing : Id64

    I am on lion, with 4.6, and with air 3.2

  22. Air 3.3 solves some issues:

    ipad3 reports 264dpi
    144×144 icon(ipad3) is now acceptable

    I tested the beta2 and confirmed the information above.

    But, I’m having some issues with air 3.3. On ipad3 the size of the objects is ok, but in a horizontal group for example the elements overlap.

  23. Update on my previous comment about AIR 3.3. Maybe this helps somebody ;)

    I missed the fact that I should have used the property applicationDPI in order to Flex handle the dpi stuff for me.

    Before (not using the property at all), the background image in my app was fullscreen on ipad2 and 1/4 screen on ipad3. After setting this property to 160 (base value), on ipad2 it continued to be fullscreen and on the ipad3 it became larger than 1/4 but still not fullscreen :( So, the framework didn’t figure out everything for me.

    This happens because Flex groups the different densities in 3 categories: 160, 240, 320. In my ipad2 x ipad3 case, the original values are 132 and 264. So, Flex rounds the 132 to 160 and the 264 to 240. This means that internally for Flex, the ipad3 has only 1.5x more density than the ipad2, that’s wrong (ipad3 has double the density) and that’s the root cause of the problem.

    So, the solution is to cheat/override this density, and in ipad3 case se it to 320. I’ll try that tomorrow and post the results ;)

  24. I am confused about -platformsdk.

    I am trying to compile my App for the iPad 1&2 and for the New iPad (3).

    I have downloaded the iOS5.1 SDK, and I am using Flash Builder 4.6.

    I don’t think the argument -platformsdk {sdk source} should be added to the Flex Compiler (as it’s giving me an error)…

    Where should this argument be placed?

  25. air 3.3 beta 3 release note :
    Platform SDK support for iOS on Windows Now, a developer can copy
    the iOS SDK folder on a Windows machine and use the platformsdk option of
    adt on Windows too.

    How exactly are we suppose to copy the IOS SDK folder ?
    Where can we get it using windows ?
    Thanks for helping !

  26. Hi Joe

    In Flash Builder, there is an option in the native extensions settings to add the path to the sdk. This path is applied internally via the -platformsdk compile setting. Unfiortunately, the path is only used if you include a native extension in your project, so you’ll have to include an extension too. Maybe something small like this.

  27. Hi Jeremie

    To develop for iOS you will need an Apple developer license. That will enable you to download XCode from the developer tools site. Although you can’t run XCode on windows, you can rifle through it’s resources (you’ll need one of the many windows apps for opening Apple disk image files). Amongst the many files included with XCode is the SDK.

  28. Supperb! Thanks for the tip :)

    I also noticed, as mentioned in your post, that the DPI it’s retrieving is still 132 (AIR 3.1), though its clearly using the retina display as its showing all as tiny. I guess I would have to verify its it’s installed on a retina by its Capabilities.screenResolutionX == 1536 and arrange the font sizes, images etc accordingly. Awaiting AIR 3.3 to be released :)

    Thanks again.

  29. Regarding using air 3.3 for platformsdk on windows. how exactly does that work? it says on the air 3.3 beta pdf that you must replace symbolic links with actual files on windows. what does this mean?

  30. Marvin – Symbolic links in Linux/Unix are a reference to an original file, similar to a shortcut in Windows. Unfortunately they don’t translate across platforms, so if you place the iOS SDK on a Windows machine the symbolic links in the SDK will stop working and you have to replace these links with the original files to get the SDK working again. I don’t know which the specific links are.

  31. Thanks, Richard! I’ll see if I can find any more info about this.

  32. Thanks Richard for your help.
    So far, I didn’t succeed to get the retina with adt command line on Windows. I get some error in the console when I target to the extracted Xcode dmg with IOS 5.1 folder.

    I’m able to get it on mac, it recognizes the last xcode sdk , but I really don’t like coding on mac, I can’t use flashdevelop there…

  33. Jeremie, did you get Premature end of file error as well? That’s what I’ve been getting. I’ve received a response from adobe regarding this question:

    1) Zip the iOS SDK iPhoneOSx.y.sdk present on your Mac machine.

    2) Copy the zipped file to a Windows machine.

    3) Unzip it.

    4) At the end of the ADT commandline, add -platformsdk

    In cases where the SDK is not properly copied, symbolic links may dissapear, which may require replacing them manually, else packaging would fail.

    To avoid that, I recommend using zip and unzip rather than directly copying the SDK folder from Mac to Win.

  34. Marvin, I had Premature end as well before.
    Now I tried with adobe’s process, I zipped the platformsdk folder, still no luck it gives me this message :

    ld: warning: -ios_version_min not specificed, assuming 4.0
    ld: warning: ignoring file C:\\iPhoneOS5.1.sdk/usr/lib/libstdc++.6.dylib, file w
    as built for unsupported file format which is not the architecture being linked
    (armv7)
    ld: in C:\\iPhoneOS5.1.sdk/usr/lib/libz.dylib, file too small for architecture a
    rmv7
    Compilation failed while executing : ld64

    Well I know it’s a problem with symbolic links/ unsupported file format but I couldn’t figure out how to replace them manually with the correct architecture…

  35. Problems solved. Air SDK 3.3 is now live. Air 3.3 SDK now supports iOS SDK 5.1. That means that there is no need to use platformsdk. The simple option (set resolution to “high”) works OK

  36. Hi,
    I just followed the procedure .I set the applicationDPI as 160 and it shows all the UI elements perfectly in both ipad2 and 3.
    But there is an issue in localToGlobal() . This method returns different values for ipad 2 and 3 and makes so many issues on screen.
    Did any one else experienced the same behavior..?Please can some one verify it..

    I am using AIR 3.3 Release Version
    Any implementation of localToGlobal or globalToLocal will replicate the issue.(tried localToGlobalContent as well with the same result)

    Thanks

  37. Hi guys,
    How do I install the new AIR SDK 3.3 to work with FlashBuilder 4.6?

    Not sure where to put the SDK, and how to use it when deploying for iOS (on windows machine).

    Thanks,

  38. hey.. does anyone know if it’s possible to specify standard res for ipad but high res for iphone with out spcifying a < 5.1 ios sdk? i am developing an app that is designed to run on iphone 4 and ipad 2. cheers

  39. Richard do you know if it is possible to point to ios5.1 sdk via Flash Builder Native Extensions preference on Mac 10.6.8 Snow Leopard?

    I would have to download the sdk on a 10.7 Lion mac and transfer the zipped sdk to my Snow Leopard machine and then not really sure if that will work?

  40. Right now I have FB 4.7 Flex Mobile project on mac 10.6.8 with ios5 and have extended the runtimeDPI class to set application DPI to 320 if its an iPad3. Looks fine in the AIR simulator but do you think it will work on an iPad 3? I dont have one to test as yet.

  41. Mark Black, that works just as well on the emulator. Very good solution, thanks for the hint!

  42. Using an iPad mini (2nd generation) with Retina display and building with any SDK > 5.01 (tried 7.0, 6.0 and 5.01), I’m not getting the correct values. Here is what I’m getting when running the app (device iOS is 7.0)

    Capabilities screenresolution: 768, 1024
    Capabilities.screenDPI: 132
    stage: 768, 1024
    fullscreen: 768, 1024

    I’m using a Mac, AIR4.0 (released version – Apple is rejecting any versions of AIR less than 4.0), iOS sdk set correctly in native extensions tab. Also tried command line, no errors or warnings with the same results.

    Any ideas or suggestions? I’m updating an app that works well on an iPad 2 and others but I need to get it to display correctly on iPad mini (2g)

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>