At MAX2010 (Awesome BTW) Adobe introduced Flex SDK Hero and Flash Builder Burrito which enables you to build and deploy Flex mobile applications on Android by default. In addition, using the revitalized Packager for iPhone, you can postprocess the swf into an ipa that you can deploy on an iPhone using iTunes.
In this post, I will share with you the steps that I took to use the Flex API for ArcGIS to build a mobile mapping application.
First and foremost - RTFM - here are some links that u _need_ to read specially for iPhone provisioning:
http://opensource.adobe.com/wiki/display/flexsdk/Hero
http://labs.adobe.com/technologies/flashbuilder_burrito/
http://labs.adobe.com/technologies/packagerforiphone/
The cool part of this whole process is now you have one code base to build upon and deploy on Android and iPhone and in the future whatever mobile platform Adobe decides to support.
You can download the source code of the sample application from here.
This simple application queries the states demographic layer in arcgis.com and displays the result as a list. By taking advantage of the new state syntax in Flex 4, if the user rotates the phone to view the info in landscape mode, the list is replaced with a map showing the selected states. Cool ?
There is no new Flex API for ArcGIS to learn. I'm using the same old Query, QueryTask, Map, ArcGISTiledLayer, GraphicLayer and SimpleFillSymbol classes from the released Flex API.
Now, to compile the application using Flash Builder Burrito, make sure to include in the libs project folder the flexapi swc and make sure to copy from the Flex sdks folder (under the burrito application folder) the mx.swc and the sparkskins.swc files. For the next release of our swc will not require the last two swc, just add them for now. Your package explorer in Flash Builder should look like this:
Now you can compile, deploy and run your swf on the USB attached Android. Make sure that you have the latest AIR runtime on your phone. If not, then delete AIR using the Settings view and redeploy the application, the latest runtime engine will be automagically installed.
Now to the iPhone. Currently, Burrito does not have a built-in wizard to postprocess the swf into and an ipa. This must be done via command line tools. So, download and install the latest iphone packager for your platform (windows or mac). In my case, I had to re-compile the source code to reproduce the swf. Here is the content of my bash shell script:
FLEX_HOME="/Applications/Adobe Flash Builder Burrito/sdks/4.5.0"
"${FLEX_HOME}/bin/mxmlc"\
-load-config "${FLEX_HOME}/frameworks/airmobile-config.xml"\
-compiler.include-libraries+=libs\
-sp src\
-o bin-debug/MyMobileApp.swf src/MyMobileApp.mxml
Next is to convert the swf to an ipa. Here is the content of my shell script:
~/packagerforiphone_v2_mac_101110/bin/pfi\
-package\
-target ipa-test\
-provisioning-profile ~/YourProfile.mobileprovision\
-storetype pkcs12\
-keystore ~/YourFile.p12\
-storepass YourPassword\
MyMobileApp.ipa\
bin-debug/MyMobileApp-ios.xml\
bin-debug/MyMobileApp.swf\
bin-debug/assets/Default.png\
bin-debug/assets/Icon29.png\
bin-debug/assets/Icon57.png\
bin-debug/assets/Icon512.png
Here is the content of MyMobileApp-ios.xml:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/2.0">
<id>ThunderHead</id>
<filename>MyMobileApp</filename>
<name>MyMobileApp</name>
<version>v1</version>
<initialWindow>
<renderMode>gpu</renderMode>
<content>bin-debug/MyMobileApp.swf</content>
<fullScreen>true</fullScreen>
<aspectRatio>portrait</aspectRatio>
<autoOrients>true</autoOrients>
</initialWindow>
<supportedProfiles>mobileDevice</supportedProfiles>
<icon>
<image29x29>bin-debug/assets/Icon29.png</image29x29>
<image57x57>bin-debug/assets/Icon57.png</image57x57>
<image512x512>bin-debug/assets/Icon512.png</image512x512>
</icon>
<iPhone>
<InfoAdditions><![CDATA[
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleBlackOpaque</string>
<key>UIRequiresPersistentWiFi</key>
<string>NO</string>
]]></InfoAdditions>
</iPhone>
</application>
Again - if you want to know what all the above options mean - you _must_ read the packager documentation. The pfi command will run for a long time - do not worry - it will eventually finish - again, this is still in its early stages, and I hope that Adobe will make this easier and faster in the future.
Now drag the ipa file onto iTunes and sync your iPhone. you should in theory have the app on your iPhone.
I hope this works for you and tell me what you think.
33 comments:
Dude, u r one crazy mo-fo! Love it!
So cool... they need the iphone export wizard - i RTFM'd the iphone packager, and seems like a major pain. Was it very difficult? Looks quite involved... This could be huge!!
Any chance you can post more detail on the process of porting to ipa? All the doc assumes using Flash CS5, but i am using Flash Builder "Burrito" - assume that is OK?
Also, i could not import the sample code zip into Burrito, said was not a valid project. Tried both pointing to the zip and to the folder of the unzipped contents. Any thoughts?
you are my hero
Can you use the phone's GPS to get the current location? That would provide a better opportunity for smarter apps.
Sure u can - there is a full GeoLocation API in flex
Fantastic! I was able to get it work on my development iPhone2G. Had some problems with Hero not running exactly as it should...and, of course, no hardware "back" button.
Other then that, it does run, albeit slow.
GREAT Job and I do see what is possible, and I believe Adobe will definitely improve this one.
hi...
i'm getting this error when packing...
Exception in thread "main" java.lang.Error: Unable to find named traits: mx.collections.errors::SortError
at adobe.abc.Domain.resolveTypeName(Domain.java:195)
at adobe.abc.Domain.resolveTypeName(Domain.java:112)
at adobe.abc.GlobalOptimizer$InputAbc.resolveTypeName(GlobalOptimizer.java:274)
at adobe.abc.GlobalOptimizer$InputAbc.readCode(GlobalOptimizer.java:983)
at adobe.abc.GlobalOptimizer$InputAbc.readBody(GlobalOptimizer.java:531)
at adobe.abc.GlobalOptimizer$InputAbc.readAbc(GlobalOptimizer.java:404)
at adobe.abc.GlobalOptimizer$InputAbc.readAbc(GlobalOptimizer.java:280)
at adobe.abc.LLVMEmitter.generateBitcode(LLVMEmitter.java:160)
at com.adobe.air.ipa.AOTCompiler.convertAbcToLlvmBitcode(AOTCompiler.java:329)
at com.adobe.air.ipa.AOTCompiler.GenerateMacBinary(AOTCompiler.java:600)
at com.adobe.air.ipa.IPAOutputStream.compileRootSwf(IPAOutputStream.java:196)
at com.adobe.air.ipa.IPAOutputStream.finalizeSig(IPAOutputStream.java:366)
at com.adobe.air.ADTPackager.createPackage(ADTPackager.java:65)
at com.adobe.air.ipa.IPAPackager.createPackage(IPAPackager.java:165)
at com.adobe.air.ADTEntrypoint.parseArgsAndGo(ADTEntrypoint.java:132)
at com.adobe.air.ipa.PFI.parseArgsAndGo(PFI.java:152)
at com.adobe.air.ADTEntrypoint.run(ADTEntrypoint.java:68)
at com.adobe.air.ipa.PFI.main(PFI.java:112)
any hints?
Another cool blog. Right On!
can you post some images?
Thanks for the great tutorial. However, i am having an issue compiling with mxmlc. This is my build swf cmd:
"c:\Program Files\Adobe\Adobe Flash Builder Burrito\sdks\4.5.0\bin\mxmlc" -load-config "c:\Program Files\Adobe\Adobe Flash Builder Burrito\sdks\4.5.0\frameworks\airmobile-config.xml" -library-path -sp -o MyMobileApp.swf "c:\Users\Morgan\Adobe Flash Builder Burrito Preview\MyMobileApp\src\MyMobileApp.mxml"
I get an error saying "Error: Could not resolve to a component implement" or an error regarding compile time constants. This sounds like my libraries are not being included in the build. I would greatly appreciate any feedback anyone may have regarding this issue. And yes, i am new to mxmlc compiling, so please forgive me if the answer is obvious. Thanks again,
Morgan
GeoSurf, Inc
Sorry for the delay - Looks like your library path is missing the swcs.
So I tried your code today with 2.3 and got this error, any thoughts?
VerifyError: Error #1014: Class mx.controls.sliderClasses::Slider could not be found.
at com.esri.ags::Map()[C:\checkout\flex_api2\api\src\com\esri\ags\Map.as:526]
at views::FeatureList/_FeatureList_Map1_i()
at mx.core::DeferredInstanceFromFunction/getInstance()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\core\DeferredInstanceFromFunction.as:105]
at mx.states::AddItems/createInstance()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\states\AddItems.as:487]
at mx.states::AddItems/initialize()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\states\AddItems.as:502]
at mx.states::State/http://www.adobe.com/2006/flex/mx/internal::initialize()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\states\State.as:257]
at mx.core::UIComponent/initializeState()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\core\UIComponent.as:10608]
at mx.core::UIComponent/commitCurrentState()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\core\UIComponent.as:10306]
at mx.core::UIComponent/commitProperties()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\core\UIComponent.as:8180]
at spark.components.supportClasses::GroupBase/commitProperties()[E:\dev\hero_private_beta\frameworks\projects\spark\src\spark\components\supportClasses\GroupBase.as:1089]
at spark.components::Group/commitProperties()[E:\dev\hero_private_beta\frameworks\projects\spark\src\spark\components\Group.as:826]
at mx.core::UIComponent/validateProperties()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\core\UIComponent.as:8095]
at spark.components::ViewNavigator/createViewInstance()[E:\dev\hero_private_beta\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1738]
at spark.components::ViewNavigator/commitViewChange()[E:\dev\hero_private_beta\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1661]
at spark.components::ViewNavigator/commitProperties()[E:\dev\hero_private_beta\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1063]
at mx.core::UIComponent/validateProperties()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\core\UIComponent.as:8095]
at mx.managers::LayoutManager/validateClient()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\managers\LayoutManager.as:934]
at mx.core::UIComponent/validateNow()[E:\dev\hero_private_beta\frameworks\projects\framework\src\mx\core\UIComponent.as:7953]
at spark.components::ViewNavigator/executeDelayedActions()[E:\dev\hero_private_beta\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1170]
You have to add references in your flex project to adobe's mx.core libraries. In Flash Burrito, it only loads the spark stuff, and the ESRI API still uses mx stuff.
Are you saying that I need to add a source path to the 3.5 sdk so that it can find the missing components code. or do you have a different method in mind.
No - just add the mx.swc and sparkskin.swc to ur libs folder.
I had this code working on flex builder burrito, updated to the new version flash builder 4.5 and am getting no errors when compiling. But when running the app and executing a query I get this error
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at views::FeatureList/set data()[C:\Users\anash\Adobe Flash Builder 4.5\VernonGIS_Mobile\VernonGIS\src\views\FeatureList.mxml:17]
at spark.components::ViewNavigator/createViewInstance()[E:\dev\hero_private\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1928]
at spark.components::ViewNavigator/commitNavigatorAction()[E:\dev\hero_private\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1849]
at spark.components::ViewNavigator/commitProperties()[E:\dev\hero_private\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1220]
at mx.core::UIComponent/validateProperties()[E:\dev\hero_private\frameworks\projects\framework\src\mx\core\UIComponent.as:8209]
at mx.managers::LayoutManager/validateProperties()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:597]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:813]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1180]
I added in the two swc files that are missing. Any help would be appreciated. I have been trying to resolve this for a week now
try this project - http://dl.dropbox.com/u/2193160/MobileApp.fxp
Save the link as a file - do not open it directly specially with IE.
thanks for your help your solution worked
Hey all,
Trying to implement this using the 4.5 release and keep getting this error. I have sorted out that it fails when trying to bind dataprovider to the list in this line of code:
list.dataProvider = new ArrayList(featureSet.attributes);
I can see the objects in debug mode, but it doesn't want to bind the attributes for some reason.
Any ideas?
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at views::FeatureList/set data()[/Users/-----/Documents/Adobe Flash Builder 4.5/TestMobile/src/views/FeatureList.mxml:30]
at spark.components::ViewNavigator/createViewInstance()[E:\dev\hero_private\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1928]
at spark.components::ViewNavigator/commitNavigatorAction()[E:\dev\hero_private\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1849]
at spark.components::ViewNavigator/commitProperties()[E:\dev\hero_private\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1220]
at mx.core::UIComponent/validateProperties()[E:\dev\hero_private\frameworks\projects\framework\src\mx\core\UIComponent.as:8209]
at mx.managers::LayoutManager/validateProperties()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:597]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:813]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1180]
Download latest src from http://dl.dropbox.com/u/2193160/MobileApp.fxp
Hi, is there anyway to get my map offline with using esri flex api. As far as i know, esri ios api support something like that with using map caching?? Thankss...
There is an update to this post - http://www.adobe.com/devnet/flash-builder/articles/mobile-mapping-app-arcgis.html
There is not yet an COTS offline caching solution
Thanks for the ideas!!
Do you find that performance is shot by the adobe framework?
Why does my 4mb (200 lines of code) swf turn into a 23 mb app? (with esri flex, mx and sparkskins swc's)
Getting better with each release of AIR - tested up tp 2.6 - not 2.7 yet - and yes, in the version that I posted, it is because of the mx dependency - which we fixed in the soon to be released 2.4 API.
Thanks, again! Any thoughts on persisting the whereInput's text property? It always gets reset to the default, but I want it to show the last search string. I tried removing the intermediate QueryExecuteView to try using popView() (instead of popToFirstView()) on the QueryResultView's Home button, but no luck. I thought each view's data property was supposed to be maintained in the stack. Well, if it is, how do I use it? Thanks!
Found it!
from here
Although I did *not* have to set my destructionPolicy='never'.
FWIW... I just had to manually set:
data.text = whereInput.text;
right before pushing the QueryResultView. Then when I use navigator.popView() to go back, my last search string is there. I also moved the BusyIndicator into the QueryView and toggle it's visibility with executing/handling the query/response.
is it possible to test your sample application over an emulator? or we need a device for that?
FlashBuilder 4.6 comes with Emulator !
Hi Mansour,
thanks for the hack! I have a question though.
Esri docs at http://resources.arcgis.com/en/help/flex-viewer/concepts/index.html#/FAQs/01m300000004000000/ state that:
===================
Is it possible to run the ArcGIS Viewer for Flex application on my iPhone or iPad?
No. There are two specific issues related to this.
The ArcGIS Viewer for Flex is a standard Flex project, it would need to be re-written as a Flex Mobile Project.
The ArcGIS Viewer for Flex uses Flex modules. These are not supported in Flex mobile projects.
===================
What's up with that, is it true that to use Esri Flex on iOS, one needs to ditch the viewer?
Actually this has nothing to do flex - iOS does not allow any application to be modular - that means extra executable code cannot be downloaded after the fact - so yes - you will have to rewrite the app - some people have done this as they will have to rewrite it to create a better mobile experience.
Post a Comment