Using ANT to Compile a Flex Mobile Project for iOS

It’s 3am. You have a sexy Flex mobile project that takes full advantage of the Hero SDK and its Spark mobile components. You’re dying to deploy to iPhone and iPad but unfortunately, you either have to build your app using Adobe’s iPhone packager via the command line interface (CLI), wait until Flash Builder includes a GUI that supports this scenario, switch to another IDE (FDT, etc) or re-factor the app from Flex to Flash for compilation via Flash CS5. Nothing’s particularly appealing.

Enter: ANT to the rescue!

By creating an ANT build script, you can alleviate all of the above concerns and stay super-flexible at the same time. Here’s a template that I’ve been using lately with great success:

<?xml version="1.0" encoding="UTF-8"?> 
<project default="4. Package Application" name="[Your Flex Project Name]"> 
	<!-- Framework properties -->
	<property name="FLEX_HOME" value="[/path/to/your/flex/4.5/sdk]" /> 
	<property name="AIR_GLOBAL" value="${FLEX_HOME}/frameworks/libs/air/airglobal.swc" /> 
	<property name="ADL" value="${FLEX_HOME}/bin/adl" /> 
	<property name="ADT" value="${FLEX_HOME}/lib/adt.jar" /> 
	<property name="PFI" value="${FLEX_HOME}/lib/pfi.jar" /> 
	<property name="FLEX_TASKS" value="${FLEX_HOME}/ant/lib/flexTasks.jar" /> 
	<property name="LOCALE" value="en_US" /> 
 
	<!-- Project properties --> 
	<property name="project_root" value="[/path/to/your/flex/mobile/project]" /> 
	<property name="class_path" value="${project_root}/src" /> 
	<property name="lib_path" value="${project_root}/libs" />
	<property name="splash_path" value="${class_path}/Default.png" /> 
	<property name="app_name" value="[YourApp]" /> 
	<property name="app_root_dir" value="." /> 
	<property name="app_type" value="mxml" /> 
	<property name="assets_dir_name" value="[name_of_your_assets_dir]" />
	<property name="debug_mode" value="false" />
 
	<!-- Certificate properties --> 
	<property name="cert_loc" value="${app_root_dir}/[path/to/your/certs]" />
	<property name="ios_keystore" value="${cert_loc}/[your_cert_name].p12" /> 
	<property name="ios_pass" value="[your_cert_password]" />
	<property name="ios_provisioning" value="${cert_loc}/[your_provisioning_profile].mobileprovision" />
 
	<!-- Application properties -->
	<property name="swf_file" value="${app_name}.swf" /> 
	<property name="air_file" value="${app_name}.air" /> 
	<property name="ipa_file" value="${app_name}.ipa" /> 
	<property name="app_descriptor" value="${class_path}/${app_name}-app.xml" /> 
	<property name="main_class" value="${class_path}/${app_name}.${app_type}" />
	<property name="build_dir" location="${app_root_dir}/build" /> 
	<property name="debug_dir" location="${app_root_dir}/build/debug" /> 
	<property name="publish_dir" location="${app_root_dir}/build/deploy" /> 
	<property name="assets_dir" location="${class_path}/${assets_dir_name}" />
	<property name="output_loc" location="${publish_dir}/${swf_file}" />
 
	<!-- Use the Flex ANT tasks for easier compilation -->
	<taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_TASKS}"/>
 
	<!-- Clean existing directories --> 
	<target name="1. Cleanup Directories" description="clean up"> 
		<delete dir="${debug_dir}" /> 
		<delete dir="${publish_dir}" /> 
		<delete dir="${build_dir}" /> 
	</target> 
 
	<!-- Create required directories --> 
	<target name="2. Build New Directories" depends="1. Cleanup Directories"> 
		<mkdir dir="${build_dir}" /> 
		<mkdir dir="${debug_dir}" /> 
		<mkdir dir="${publish_dir}" /> 
	</target>
 
	<!-- Compile SWF to build-directory for packaging --> 
	<target name="3. Compile SWF" depends="2. Build New Directories"> 
		<mxmlc 
			file="${main_class}" 
			output="${output_loc}" 
			locale="${LOCALE}" 
			static-rsls="false" 
			accessible="false" 
			configname="airmobile" 
			debug="${debug_mode}" 
			failonerror="true" 
			fork="true" 
			maxmemory="512m">
			<source-path path-element="${class_path}"/>
			<compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
				<include name="libs/*" />
			</compiler.library-path>
			<library-path file="${FLEX_HOME}/frameworks/locale/${LOCALE}" append="true"/>
			<library-path dir="${lib_path}" includes="*.swc" append="true"/>
			<external-library-path file="${AIR_GLOBAL}" append="true"/>
		</mxmlc>
	</target>
 
	<!-- Package the application to an ipa file & save it in the publish directory --> 
	<target name="4. Package Application" depends="3. Compile SWF"> 
		<java jar="${ADT}" fork="true" failonerror="true"> 
			<arg value="-package"/>
			<arg value="-target"/>
			<arg value="ipa-test"/>
			<arg value="-provisioning-profile"/>
			<arg value="${ios_provisioning}"/>
 
      			<arg value="-storetype"/>
			<arg value="pkcs12"/>
			<arg value="-keystore"/>
			<arg value="${ios_keystore}"/>
			<arg value="-storepass"/>
			<arg value="${ios_pass}"/>
 
			<arg value="${ipa_file}"/>
			<arg value="${app_descriptor}"/>
			<arg value="${output_loc}"/>
 
			<arg value="-C" /> 
			<arg value="${class_path}"/>
			<arg value="${splash_path}"/>
 
			<arg value="-C" /> 
			<arg value="${class_path}"/>
			<arg value="${assets_dir}/icons/." /> 
		</java> 
	</target>
</project>

UPDATED 3/23/11: changed the Package Application target to use ADT vs PFI now that AIR 2.6 is official.

You should only have to modify the values wrapped in brackets [ ] to match your system setup. Once that’s done, you’ll need to tweak your application’s descriptor file (ie, myapp-app.xml) as follows:

#1 Modify the initialWindow’s content value to match the output path from your ANT script:

<content>[This value will be overwritten by Flash Builder in the output app.xml]</content>

becomes:

<content>/path/to/your/application.swf</content>

#2 Add the following iOS-required data, either before or after the Android data section:

<iPhone>
    <InfoAdditions><![CDATA[
<key>UIDeviceFamily</key>
<array>
<string>1</string>
<string>2</string>
</array>
]]></InfoAdditions>
    <requestedDisplayResolution>high</requestedDisplayResolution>
</iPhone>

After that, you should be able to compile your app using the ANT script without problem from any IDE that supports ANT or even from the CLI. This certainly isn’t the only way to accomplish this, it’s just my take on it. Feel free to hack away at it and share what you come up with.

If you should decide to bypass the template and build a script from scratch, here are a few caveats to remember:

  • update your application descriptor to use the output SWF path from your ANT script instead of the default placeholder text provided by Adobe
  • add the appropriate iOS tags to your descriptor
  • modify the ANT template to point to your system specific config (SDK, project, certs)
  • don’t forget to add your certificate’s password
  • remember to load the airmobile-config.xml (configname=airmobile vs air)
  • change ipa-test to ipa-app-store before publishing to the App Store.

Checkout some of the related resources for alternatives to tackling the same problem and just general information on developing AIR applications for iOS devices.

RELATED RESOURCES
http://www.ivanalvarez.com/2010/10/flex-4-in-ios-3/
http://www.terrenceryan.com/blog/post.cfm/compiling-flex-hero-apps-with-mxmlc-in-ant
http://blogs.adobe.com/cantrell/archives/2010/09/packager-for-iphone-refresher.html
http://help.adobe.com/en_US/air/build/WS901d38e593cd1bac1e63e3d128fc240122-7ff2.html
http://help.adobe.com/en_US/air/build/WSBE9908A0-8E3A-4329-8ABD-12F2A19AB5E9.html
http://help.adobe.com/en_US/as3/iphone/air_deviphoneapps.pdf

3 thoughts on “Using ANT to Compile a Flex Mobile Project for iOS”

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>