Using the iPad retina display with Adobe Air

Using the iPad retina display with Adobe Air

19th March 2012

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/ Now use the playformsdk setting to build against iOS 5.1.

via Using the iPad retina display with Adobe Air.

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.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/'/>

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="">

  <name>Retina Test</name>
  <copyright>Stick Sports Ltd.</copyright>





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"/>

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/"/>

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/

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.


Gesture Recognizers

UIKit includes a UIGestureRecognizer class that defines the basic behavior for all gesture recognizers. You can define your own custom gesture recognizer subclasses or use one of the UIKit-supplied subclasses to handle any of the following standard gestures:

  • Tapping (any number of taps)
  • Pinching in and out (for zooming)
  • Panning or dragging
  • Swiping (in any direction)
  • Rotating (fingers moving in opposite directions)
  • Long presses


4,字体上是关键,最好选择设备有的字体,不要嵌入字体。嵌入的字体会出现问题,而且效率很低很低,特别是在ipad3和低清设备上面。如果你不知道有什么字体,可以在”越 狱”的ios机子上,用91软件,可以把上面的字体全部弄下来。
6,我们用AIR3.2打包后,会出现设备crash。用AIR3.1和3.3没有问题。但是3.1有个小问题,ipad3 loading那儿图片会斜一下,不过问题不大。
10,不需要鼠标操作的,要把mouseEnabled设置成false ,如果它的子对象也不需要鼠标事件,要把mouseChildren设置为false。
16,现在flash builder4.6及以上版本都能方便地打包ipa,完全可以不用adt命令行。

Adobe AIR 应用程序图标





320 x 480



640 x 960



768 x 1004



768 x 1004



1024 x 748



1024 x 748



320 x 480

标准 iPhone 上的 example://URL


640 x 960

高分辨率 iPhone 上的 example:// URL


768 x 1004

纵向 iPad 上的 example:// URL


1024 x 748

横向 iPad 上的 example:// URL

via Adobe AIR 应用程序图标.

iOS Data Storage Guidelines 和 “do not back up”文件属性

iOS 5有了iCloud后,Apple更新了数据存储指导方针,以适应于iCloud存储,同时增加了“不要备份”文件属性,可以指定文件不备份和上传到iCloud


iOS 数据存储指导方针

iCloud包括了备份,会通过Wi-Fi每天自动备份用户iOS设备。app的home目录下的所有东西都会被备份,除了应用Bundle本身、缓存目录和temp目录。已购买的音乐、应用、书籍、Camera Roll、设备设置、主屏幕、App组织、消息、铃声也都会被备份。由于备份通过无线进行,并且为每个用户存储在iCloud中,应用需最小化自己存储的数据数量。大文件会延长备份时间,并且消耗用户的可用iCloud空间。


1. 只有那些用户生成的文档或其它数据,或者应用不能重新创建的数据,才应该存储在<Application_Home>/Documents目录下,并且会被自动备份到iCloud。

2. 可以重新下载或生成的数据,应该存储在<Application_Home>/Library/Caches目录。例如数据库缓存文件、可下载文件(杂志、报纸、地图应用使用的数据)等都属于这一类。

3. 临时使用的数据应该存放在<Application_Home>/tmp目录。尽管这些文件不会被iCloud备份,应用在使用完之后需要记得删除这些文件,这样才不会继续占用用户设备的空间。

4. 使用”不要备份”属性来指定那些需要保留在设备中的文件(即使是低存储空间情况下)。那些能够重新生成,但在低存储空间时仍需保留,对应用正常运行有影响,或者用户希望文件在离线时可用的文件,需要使用这个属性。无论哪个目录下的文件(包括Documents目录),都可以使用这个属性。这些文件不会被删除,也不会包含在用户的iCloud或iTunes备份中。由于这些文件一直占用着用户设备的存储空间,应用有责任定期监控和删除这些文件。

iOS 5.0.1开始支持”do not back up”文件属性,允许开发者明确地指定哪些文件应该被备份,哪些是本地缓存可以自动删除,哪些文件不需要备份但不能删除。此外,对目录设置这个属性,会阻止备份该目录和目录中的所有内容。

注意”do not back up”属性只能用于iOS 5.0.1以后版本。之前版本的应用需要存储数据到<Application_Home>/Library/Caches目录才能避免被备份。由于老的系统忽略这个属性,你需要确保应用在所有iOS版本中,都遵循上面的iOS Data Storage Guidelines。

数据处理分类文件属性就是iOS 5.0.1引入的”do not back up”特性,用于指定文件或目录不需要备份(不管在文件系统的什么位置)。通过使用这个新的文件属性,并且将文件存放在指定的目录下,文件可以分为以下四种数据类型:s.

这些是用户创建的数据,或其它不能重新生成的数据。应该存放在<Application_Home>/Documents目录下,并且不应该标记为”do not backup”属性。关键数据在低存储空间时也会保留,而且会被iCloud或iTunes备份。



可以下载,或重新创建,但用户希望在离线时也能访问这些数据。离线数据应该存放在<Application_Home>/Documents目录或<Application_Home>/Library/Private Documents目录,并标记为”do not backup”属性。这两个位置的数据在低存储空间时都会保留,而”do not backup”属性会阻止iTunes或iCloud备份。应用不再需要离线数据文件时,应该尽快删除,以避免浪费用户的存储空间。ce.

设置Do Not Backup扩展属性
注意:”do not backup”扩展属性可以添加到任何文件或目录,在旧版本的系统中也能够设置。但旧系统仍然会备份这些文件,一旦设备更新到iOS 5.0.1,这些文件会被重新正确地配置。

使用下面方法来设置”do not back up”扩展属性。当你创建不需要备份的文件或目录时,向文件写入数据,然后调用下面方法,并传递一个文件URL。

#include <sys/xattr.h>
– (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
    c*****t char* filePath = [[URL path] fileSystemRepresentation];

    c*****t char* attrName = “”;
    u_int8_t attrValue = 1;

    int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
    return result == 0;

Adobe AIR 各平台限制列表



类或功能 桌面 extended
tv extendedTV
Accelerometer (Accelerometer.isSupported) 检查
Accessibility (Capabilities.hasAccessibility)
回音消除 (Microphone.getEnhancedMicrophone())
ActionScript 2
CacheAsBitmap 矩阵
Camera (Camera.isSupported)
CameraUI (CameraUI.isSupported)
ContextMenu (ContextMenu.isSupported)
DatagramSocket (DatagramSocket.isSupported)
DockIcon (NativeApplication.supportsDockIcon) 检查 检查
拖放 (NativeDragManager.isSupported) 检查
EncyptedLocalStore (EncyptedLocalStore.isSupported)
Flash Access (DRMManager.isSupported)
GameInput (GameInput.isSupported)
Geolocation (Geolocation.isSupported) 检查
HTMLLoader (HTMLLoader.isSupported)
IME (IME.isSupported) 检查
LocalConnection (LocalConnection.isSupported)
Microphone (Microphone.isSupported) 检查
多频道音频 (Capabilities.hasMultiChannelAudio()) 检查 检查
NativeMenu (NativeMenu.isSupported)
NativeProcess (NativeProcess.isSupported)
NativeWindow (NativeWindow.isSupported)
NetworkInfo (NetworkInfo.isSupported) 检查
使用默认应用程序打开文件 有限制
PrintJob (PrintJob.isSupported)
SecureSocket (SecureSocket.isSupported) 检查 检查
ServerSocket (ServerSocket.isSupported)
Shader 有限制
Stage3D (Stage.stage3Ds.length)
舞台方向 (Stage.supportsOrientationChange)
StageVideo 检查
StageWebView (StageWebView.isSupported)
登录时启动应用程序 (NativeApplication.supportsStartAtLogin)
StorageVolumeInfo (StorageVolumeInfo.isSupported) 检查 检查
SystemTrayIcon (NativeApplication.supportsSystemTrayIcon) 检查 检查
Text Layout Framework 输入
Updater (Updater.isSupported)
XMLSignatureValidator (XMLSignatureValidator.isSupported)


  • 检查 — 在该配置文件中,某些设备支持该功能,但并非所有设备均支持该功能。在使用该功能之前,应在运行时检查是否支持该功能。
  • 有限制 — 支持该功能,但具有一些重要限制。有关更多信息,请参阅相关文档。
  •  — 该配置文件不支持该功能。
  •  — 该配置文件支持该功能。请注意,个别计算设备可能缺少某项功能所需的硬件。例如,并非所有手机均带有摄像头。



Source Code – 720p Video on iPad and Android Tablets with Adobe AIR


	import flash.desktop.NativeApplication;
	import flash.desktop.SystemIdleMode;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.geom.Rectangle;

	public dynamic class AIRMobileVideo_AS extends Sprite
		public function AIRMobileVideo_AS()
			NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
			NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true)

			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE ;
			stage.addEventListener( StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY , stageVideoState );
		protected var stream:NetStream ;

		protected function stageVideoState( e:StageVideoAvailabilityEvent ):void
			var available:Boolean = e.availability == StageVideoAvailability.AVAILABLE ;

			if ( available )
				var nc:NetConnection = new NetConnection() ;
				nc.connect(null) ;
				stream = new NetStream(nc) ;
				stream.client = this ;
				var video:StageVideo = stage.stageVideos[0] ;
				video.viewPort = new Rectangle( 0, 0, 1280 , 720 ) ;
				video.attachNetStream( stream ) ; "") ;


		public function onMetaData( info:Object ):void


		private function handleActivate(event:Event):void
			NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE;

		private function handleDeactivate(event:Event):void




  • Ensure videos are mobile optimized, since mobile HW decoders likely don’t support all levels or profiles of H.264. Follow the encoding cookbook, and the mobile encoding guidelines.
  • Make sure to use the StageVideo API if you use an AS only approach, or the latest OSMF version which has build-in StageVideo support. Define <renderMode>direct</renderMode> in the Adobe AIR application xml file to enable StageVideo.
  • Consider adaptive streaming to adjust to less consistent mobile networks, as example HTTP Dynamic Streaming on Android, or HLS streaming on iOS.

Update 01/27/12: If you use the captive runtime approach, please update Flash Builder/Flash to the latest AIR version for 720p Android playback (AIR or higher)

via Source Code – 720p Video on iPad and Android Tablets with Adobe AIR.