#FFK11


Contact me if you’re there: @derRaab

Posted in Conference, Flash | Leave a comment

iOS development with AIR 2.6 using FDT and my new friend ANT

Adobe recently released AIR 2.6 with improved iOS support, so I finally had to get into using ADT with ANT. My editor of choice is FDT so I wanted to do as less extra work as possible. Mainly because I’m no terminal-guy. I need a clean GUI holding my hand while setting up workspaces, linking libraries and stuff like that. In other words, command line and compiler arguments are freaking me out. ;)

I read a lot of blogposts and articles (see link list on the bottom of this post) but most of them compile SWFs using ANT, which means setting source path and stuff like that as command line arguments. But hey, FDT does this already during my daily workflow, so to me it seems natural reusing this within the iOS packaging process.

So I won’t comment a lot what I came up with because all of this can be read on one of the sites below, but show you simply a screenshot of my “IOSAIRTest” workspace structure and of course the ANT files. Notice that I’m not into having different directories for debug, publish, testing and so. I like to have all source files clean and separated by file type (would have an mxml folder too):

You will find the most interesting files in src/ant. Let’s start with local.properties which just defines the SDK path:

FLEX_HOME=/Users/{USERNAME}/Path/To/FlexSDKs/4.5.0.17689_AIR_2.6
MXMLC=${FLEX_HOME}/bin/mxmlc
ADT=${FLEX_HOME}/bin/adt

Within build.properties you setup all params regarding your project:

app.rootdir=./../..
app.descriptor=${app.rootdir}/bin/IOSAIRTest-app.xml
app.rootfile=IOSAIRTest.swf
app.sourcedir=${app.rootdir}/src/as
app.bindir=${app.rootdir}/bin
app.source=${app.sourcedir}/de/superclass/IOSAIRTest.as
app.includes=assets icons Default.png Default-Portrait.png
 
build.storetype=pkcs12
build.keystore=${app.rootdir}/resources/ios/iPhoneDevCert.p12
build.storepass={PASSWORD;)}
build.mobileprofile=${app.rootdir}/resources/ios/AIR_TEST.mobileprovision
build.name=IOSAIRTest.ipa
 
fdt.projectname=AIRTest
fdt.mainclass=${app.source}
fdt.target=${app.bindir}/${app.rootfile}

And build.xml contains four ways to create the IPA package and the according FDT tasks:

<?xml version="1.0" encoding="UTF-8"?>
<project name="AIR export" basedir=".">
 
    <property file="local.properties" />
    <property file="build.properties" />
 
    <!-- FDT tasks
 
        see http://fdt.powerflasher.com/docs/FDT_Ant_Tasks#fdt.launch.application - for documentation
        see http://fdt.powerflasher.com/docs/FDT_and_Ant_Tutorial#Your_First_Task:_Compiling_.26_JRE_Error - if you run into errors!
    -->
 
    <target name="FDT create SWF">
        <fdt.launch.resetFlexCompiler/>
        <fdt.launch.application
            projectname="${fdt.projectname}"
            mainclass="${fdt.mainclass}"
            profile="false"
            debug="false"
            target="${fdt.target}"
            startswf="false"/>
      </target>
 
    <target name="FDT create SWF debug">
        <fdt.launch.resetFlexCompiler/>
        <fdt.launch.application
            projectname="${fdt.projectname}"
            mainclass="${fdt.mainclass}"
            profile="false"
            debug="true"
            target="${fdt.target}"
            startswf="false"/>
      </target>
 
    <!-- ADT tasks -->
 
    <target name="iOS create IPA debug" depends="FDT create SWF debug">
        <exec executable="${ADT}">
            <arg line="-package
                        -target ipa-debug
                        -storetype ${build.storetype}
                        -keystore ${build.keystore}
                        -storepass ${build.storepass}
                        -provisioning-profile ${build.mobileprofile}
                        ${app.bindir}/${build.name}
                        ${app.descriptor}
                        -C ${app.bindir} ${app.rootfile} ${app.includes}
            "/>
        </exec>
    </target>
 
    <target name="iOS create IPA test" depends="FDT create SWF">
        <exec executable="${ADT}">
            <arg line="-package
                        -target ipa-test
                        -storetype ${build.storetype}
                        -keystore ${build.keystore}
                        -storepass ${build.storepass}
                        -provisioning-profile ${build.mobileprofile}
                        ${app.bindir}/${build.name}
                        ${app.descriptor}
                        -C ${app.bindir} ${app.rootfile} ${app.includes}
            "/>
        </exec>
    </target>
 
    <target name="iOS create IPA ad-hoc" depends="FDT create SWF">
        <exec executable="${ADT}">
            <arg line="-package
                        -target ipa-ad-hoc
                        -storetype ${build.storetype}
                        -keystore ${build.keystore}
                        -storepass ${build.storepass}
                        -provisioning-profile ${build.mobileprofile}
                        ${app.bindir}/${build.name}
                        ${app.descriptor}
                        -C ${app.bindir} ${app.rootfile} ${app.includes}
            "/>
        </exec>
    </target>
 
    <target name="iOS create IPA app-store" depends="FDT create SWF">
        <exec executable="${ADT}">
            <arg line="-package
                        -target ipa-app-store
                        -storetype ${build.storetype}
                        -keystore ${build.keystore}
                        -storepass ${build.storepass}
                        -provisioning-profile ${build.mobileprofile}
                        ${app.bindir}/${build.name}
                        ${app.descriptor}
                        -C ${app.bindir} ${app.rootfile} ${app.includes}
            "/>
        </exec>
    </target>
 
</project>

If you’re not sure how to get started with all this AIR 2.6 stuff because it’s currently not integrated in the Flex SDKs – follow this steps:

Loads of linked informations:

http://blogs.adobe.com/cantrell/archives/2011/03/how-to-use-air-2-6-with-flash-builder-4.html
http://www.mobilerevamp.org/2010/07/30/how-to-build-your-first-air4android-application-using-fdt-and-eclipse/
https://code.google.com/p/air-on-android-with-fdt/
http://www.beautifycode.com/flex-hero-mobile-project-template-for-fdt-4-2
http://www.beautifycode.com/publish-package-an-air-file-with-fdt4
http://labs.almerblank.com/2011/03/using-ant-to-compile-a-flex-mobile-project-for-ios/
http://va.lent.in/blog/2011/03/25/air2-6-app-for-ios/ (Thanks for ANT files!)
http://developerartofwar.com/2011/03/24/air-2-6-on-ipad-2-in-15-mins/
http://karoshiethos.com/2010/04/06/use-fdt-folder-path-variables-in-ant/
http://fdt.powerflasher.com/docs/FDT_Ant_Tasks#fdt.launch.application
http://labs.almerblank.com/2011/03/using-ant-to-compile-a-flex-mobile-project-for-ios/

Update:
http://www.blackcj.com/blog/2011/04/04/ios-android-and-blackberry-in-a-single-click-with-ant/

Posted in AIR, ANT, FDT, Flash, Flash on iOS, iPhone / iPad, Terminal | 4 Comments

SWF meta tag

I’m always searching for it so here is a useful blogpost.

As the latest FDT version ( Beta 4 ) does not set compiler arguments concerning SWF-size, framerate etc. by default I started using SWF-Metatags to specify these settings.

I’m talking of these things:

[SWF(width="910", height="610", backgroundColor="#FFFFFF", frameRate="40")]

Just set this tag above your class opening in the one you’re going to compile. Here is a complete list of (useful) arguments you can pass in:

width
widthPercent
height
heightPercent
scriptTimeLimit
frameRate
backgroundColor

So basically this is the fastest way to set up common compile-arguments to your project. By the way there is no Flex-Framework required – these tags also work in pure AS3 projects.

Posted in ActionScript, Flash | Leave a comment

Date.time vs. Date.setTime() getTime() performance

Using Date.setTime() and Date.getTime() is faster than Date.time.

My quick speed test to determine the fastest way to get and set time values on Date objects:

var date : Date = new Date();
var max : Number = date.time;
 
var start : int;
var end : int;
var time : Number;
var times : Vector.<Number> = new Vector.<Number>(); 
 
var c : int = 1000000;
for ( var i : int = 0; i < c; i++ ) { times.push( Math.round( max * Math.random() ) ); }
 
start = getTimer();
for ( i = 0; i < c; i++ ) { date.time = times[ i ]; };
end = getTimer();
trace( "date.time = times[ i ];", end - start );
 
start = getTimer();
for ( i = 0; i < c; i++ ) { date.setTime( times[ i ] ); };
end = getTimer();
trace( "date.setTime( times[ i ] );", end - start );
 
start = getTimer();
for ( i = 0; i < c; i++ ) { time = date.time; };
end = getTimer();
trace( "time = date.time;", end - start );
 
start = getTimer();
for ( i = 0; i < c; i++ ) { time = date.getTime(); };
end = getTimer();
trace( "time = date.getTime();", end - start );
 
// Result:
//
// date.time = times[ i ];        381
// date.setTime( times[ i ] );    270
// time = date.time;            184
// time = date.getTime();        65

Posted in ActionScript, Flash | 4 Comments

Flash iOS packager update released!

Everything New in Adobe AIR 2.6 (read all on Christian Cantrells blog):

  • Asynchronous Bitmap Decoding
  • Owned Windows
  • Bitmap Capture in StageWebView
  • Microphone support on iOS
  • StageWebView on iOS
  • Multitasking on iOS
  • Retina Support on iOS
  • iOS Camera, CameraUI, and CameraRoll Support
  • Improved hardware acceleration on iOS
  • PFI is now ADT
  • Configurable panning with soft keyboard activation
  • Programmatic control of the display of the on-screen keyboard
  • Support for the Amazon Android Market (more info)
  • Vector printing on Linux
  • Native cursor support
  • On-device debugging over USB (Android only)
  • Native Menu event refinement
  • Enhanced text support on Android
  • NetConnection.httpIdleTimeout
  • Bundled Android USB drivers on Windows
  • Support for the vipaccess:// URI
  • -version flag for ADT

Get runtime and get SDK.

Video – developing for iOS with AIR for mobile 2.6/

Posted in AIR, Flash on iOS | 1 Comment

The Hitchhiker’s Guide to a Flash Player update

I really hate Flash Player updates just because it always takes me some time to figure out again how to update all of them on my Mac. Why isn’t there some kind of centralized Flash Player Manager?

Well, as normal user it’s really easy. Just visit Adobe and you’re almost done. But for me as developer I need to update all players used by Flash CS 5, Flash Builder 4 and the Flex SDKs as well. Note to myself: Just remember these steps (in this case for 10.2):

Visit the Flash Player Download Heaven.

Update Browser Debug Player:

  • “Download the Macintosh Flash Player X.X Plugin content debugger (Intel-based Macs)”
  • Run “Install Adobe Flash Player Debugger.app”.
  • Do nothing with Google Chrome! It updates automatically and will be your performance weapon of choice. It’s still running a release version of Flash Player. Really great if you use apps like http://audiotool.com/.

Update Adobe Flash CS 5 Release Projector for Mac OS X:

  • “Download the Macintosh Flash Player 10.2 Projector”
  • Save file as Applications/Adobe Flash CS 5/Players/Flash Player.app

Update Adobe Flash CS 5 Debug Projector for Mac OS X:

  • “Download the Macintosh Flash Player 10.2 Projector content debugger”
  • Save file as Applications/Adobe Flash CS 5/Players/Debug/Flash Player Debugger.app

Update Adobe Flash CS 5 Release Projector for Windows:

  • “Download the Windows Flash Player 10.2 Projector”
  • Save file as Applications/Adobe Flash CS 5/Players/FlashPlayer.exe

Update Adobe Flash CS 5 Debug Projector for Windows:

  • “Download the Windows Flash Player 10.2 Projector content debugger”
  • Save file as Applications/Adobe Flash CS 5/Players/Debug/FlashPlayerDebugger.exe

Well, there is one issue I don’t understand, but I think everything is working properly. I created a little file running this script:

import flash.system.Capabilities;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
 
var textField : TextField = new TextField();
    textField.autoSize = TextFieldAutoSize.LEFT;
    textField.text = Capabilities.version;
 
addChild( textField );

But when I’m just “testing” in Flash CS 5 it still says “MAC 10,1,52,14″. When I’m “debugging” it says “MAC 10,2,152,26″. I removed all Flash Player.app and Flash Player Debugger.app except the latest. If you have a clue – let me know.

Just for me – Flash Player Updates I manually installed lately:

  • 15.06.2011 – MAC 10,3,181,26

Posted in Flash Player | 3 Comments

Set WP-Syntax tab width

Since I’m using the WP-Syntax plug-in on my blog I tried to optimize font size and the tab width. Like a lot of developers I heavily use tabs in my source code. These tabs are really wide within the browser so I was looking for a way to minimize the used space.

I’m not a CSS guy but it seems like there is no way to set a specific tab width. So why not replace the tab with white space?

My change to wp-syntax/wp-syntax.php:

function wp_syntax_highlight($match)
{
    global $wp_syntax_matches;
 
    $i = intval($match[1]);
    $match = $wp_syntax_matches[$i];
 
    $language = strtolower(trim($match[1]));
    $line = trim($match[2]);
    $escaped = trim($match[3]);
    $code = wp_syntax_code_trim($match[4]);
 
    // INSERT JUST THIS LINE OF CODE
    $code = str_replace ( '    ' , '   ' , $code );
    .
    .
    .

Posted in How To..., PHP | 2 Comments

Flex 4 DragManager.doDrag() with .acceptDragDrop() error

While diving into the Flex 4 spark framework I ran into a problem using

mx.managers.DragManager.doDrag() with
mx.managers.DragManager.acceptDragDrop():

If you just drag, accept on dragDrop and then drop without moving the mouse you’ll get this error:

TypeError: Error #1009:
at mx.managers.dragClasses::DragProxy/mouseUpHandler()
[E:\dev\4...\mx\managers\dragClasses\DragProxy.as:591]

This is, because DragProxy didn’t receive a MouseEvent yet. So what you can do is manually send one. See this little use case and test for yourself:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx"
 
            applicationComplete="construct()"
            height="100%"
            width="100%">
    <fx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.core.DragSource;
            import mx.core.UIComponent;
            import mx.managers.DragManager;
 
            private function construct() : void
            {
                // Get notified whan a global error occurs
                loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, errorHandler );
            }
 
            private function onButtonMouseDown( event : MouseEvent ) : void
            {
                var button : UIComponent = UIComponent( event.target );
                var dragSource:DragSource = new DragSource();
 
                DragManager.doDrag( button, dragSource, event );
 
                // Accept dragDrop
                if ( acceptDragDropCheckBox.selected )
                {
                    DragManager.acceptDragDrop( this );
                }
 
                // Avoid error
                if ( avoidErrorCheckBox.selected )
                {
                    button.dispatchEvent( new MouseEvent( MouseEvent.MOUSE_MOVE, true,false, button.mouseX, button.mouseY ) );
                }
            }
 
            protected function errorHandler( e : UncaughtErrorEvent ) : void
            {
                Alert.show("An error has occurred and been caught by the global error handler: " + String( e.error ), "My Global Error Handler");
                e.preventDefault();
            }
        ]]>
    </fx:Script>
    <s:Label x="20" y="10" text="If you accept dragDrop you need to avoid the error!"/>
    <s:CheckBox id="acceptDragDropCheckBox" x="20" y="30" label="Accept DragDrop"/>
    <s:CheckBox id="avoidErrorCheckBox" x="20" y="50" label="Avoid error"/>
    <mx:Button id="dragButton" x="20" y="110" mouseDown="onButtonMouseDown(event)" label="Drag me. Or click me for error!"/>  
</s:Application>

UPDATE:

A much better way to avoid this error is listening to a DragEvent.DRAG_ENTER before calling DragManager.acceptDragDrop():

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx"
 
            dragEnter="dragEnterDataRenderer(event)"
 
            height="100%"
            width="100%">
    <fx:Script>
        <![CDATA[
            import mx.core.DragSource;
            import mx.core.UIComponent;
            import mx.events.DragEvent;
            import mx.managers.DragManager;
 
            private function onButtonMouseDown( event : MouseEvent ) : void
            {
                var button : UIComponent = UIComponent( event.target );
                var dragSource:DragSource = new DragSource();
 
                DragManager.doDrag( button, dragSource, event );
            }
 
            private function dragEnterDataRenderer( event : DragEvent ) : void
            {
                DragManager.acceptDragDrop( this );
            }
        ]]>
    </fx:Script>
    <mx:Button id="dragButton" x="20" y="20" mouseDown="onButtonMouseDown(event)" label="Click me. Drag me. No Error."/>  
</s:Application>

Posted in Flex | Leave a comment

Amazing Math Tutorial Video Site

I really need to quote this bit-101 blog post.
It’s the first time I heard about that great website:

http://www.khanacademy.org/

I don’t have much more to say about this. Do you need to learn or brush up on any subject related to math? You will find a wealth of data here in a massive number of videos, each 10 minutes or under. Seriously, anything you want to learn is here, from the basics to advanced calculus. Where does this guy find the time?

I got the link from Brook Andrus’ site, where she gives a bit more info on the author. Pretty amazing guy.

http://www.brooksandrus.com/blog/2010/10/01/the-wrath-of-khan-the-genesis-of-21st-century-education

UPDATE: There’s another one: http://patrickjmt.com/

Posted in How To..., Links, Video | Leave a comment

Linked List Performance Test

I was thinking about not creating linked lists for every data type I use but using one abstract data structure containing my specific data types.

So I wrote this short performance check:

package de.superclass 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.utils.Timer;
    import flash.utils.getTimer;
 
    public final class LinkedListTest extends Sprite 
    {
        private var _abstractItemLinkedList : AbstractItem;
        private var _dataItemLinkedList : DataItem;
        private var _vector : Vector.<DataItem>;
 
        public function LinkedListTest()
        {
            loaderInfo.addEventListener( Event.COMPLETE, onLoaderInfoComplete );
        }
 
        private function onLoaderInfoComplete( event : Event ) : void 
        {
            createData( );
 
            var timer : Timer = new Timer( 3000, 1 );
                timer.addEventListener( TimerEvent.TIMER_COMPLETE, onTimerComplete );
                timer.start();
        }
 
        private function onTimerComplete(event : TimerEvent) : void 
        {
            runTest( );
        }
 
        private function createData() : void 
        {
            var vector : Vector.<DataItem> = _vector = new Vector.<DataItem>();
            for ( var i : int = 0; i < 5000000; i++ )
            {
                var dataItem : DataItem = new DataItem();
                    dataItem.index = i;
 
                vector.push( dataItem );
 
                var abstractItem : AbstractItem = new AbstractItem();
                    abstractItem.data = dataItem;
 
                if ( i == 0 )
                {
                    _dataItemLinkedList = dataItem;
                    _abstractItemLinkedList = abstractItem;
                }
                else
                {
                    previousDataItem.next = dataItem;
                    previousAbstractItem.next = abstractItem;
                }
 
                var previousDataItem : DataItem = dataItem;
                var previousAbstractItem : AbstractItem = abstractItem;
            }
        }
 
        private function runTest() : void 
        {
            var dataItem : DataItem;
            var startTime : int;
 
            var vector : Vector.<DataItem> = _vector;
            var c : int = vector.length;
 
            startTime = getTimer();
            for ( var i : int = 0; i < c; i++ )
            {
                dataItem = vector[ i ];
                dataItem.index = dataItem.index;
            }
 
            var durationVector : int = getTimer() - startTime;
 
            startTime = getTimer();
            dataItem = _dataItemLinkedList;
            while ( dataItem )
            {
                dataItem.index = dataItem.index;
                dataItem = dataItem.next;
            }
 
            var durationDataItemLinkedList : int = getTimer() - startTime;
 
            startTime = getTimer( );
            var abstractItem : AbstractItem = _abstractItemLinkedList;
            while ( abstractItem )
            {
                dataItem = abstractItem.data;
                dataItem.index = dataItem.index;
                abstractItem = abstractItem.next;
            }
 
            var durationAbstractItemLinkedList : int = getTimer() - startTime;
 
            startTime = getTimer( );
            abstractItem = _abstractItemLinkedList;
            while ( abstractItem )
            {
                dataItem = DataItem( abstractItem.data );
                dataItem.index = dataItem.index;
                abstractItem = abstractItem.next;
            }
 
            var durationAbstractItemLinkedListWithCast : int = getTimer() - startTime;
 
            startTime = getTimer( );
            abstractItem = _abstractItemLinkedList;
            while ( abstractItem )
            {
                dataItem = abstractItem.data as DataItem;
                dataItem.index = dataItem.index;
                abstractItem = abstractItem.next;
            }
 
            var durationAbstractItemLinkedListWithAs : int = getTimer() - startTime;
 
            trace( "Durations:" );
            trace( "Vector", durationVector );
            trace( "DataItem LinkedList", durationDataItemLinkedList );
            trace( "AbstractItem LinkedList", durationAbstractItemLinkedList );
            trace( "AbstractItemLinkedList Using Cast", durationAbstractItemLinkedListWithCast );
            trace( "AbstractItemLinkedList Using As", durationAbstractItemLinkedListWithAs );
        }
    }
 
}
 
class AbstractItem
{
    public var data : *;
    public var next : AbstractItem;
}
 
class DataItem
{
    public var index : int;
    public var next : DataItem;
}

Results on my MacBook Pro i7:

Durations:
Vector 91
DataItem LinkedList 53
AbstractItem LinkedList 76
AbstractItemLinkedList Using Cast 108
AbstractItemLinkedList Using As 121

Alsways use explicit implemented linked lists!

Posted in ActionScript | Leave a comment