flex

flash_catalystAfter installing the latest Flash Catalyst beta 1 on my Macbook, the application didn’t want to start because this problem:

License Expired
Licensing for this product has been expired.

I had the MAX Preview version installed, so this was probably causing the problem. If you are installing the Windows version or haven’t installed the MAX Preview before, you won’t have the problem.

To solve it I tried a lot of uninstalling and re-installing, but in the end these five steps did the trick:

  1. Run the Adobe Licensing Repair Tool
  2. Uninstall Flash Catalyst
  3. Reboot the computer
  4. Running Repair Tool again but with 0 option
  5. Reinstall Flash Catalyst

It worked for me, so let’s hope it will work for you.

fbbuilderToday the beta’s of Flash Catalyst and Flash Builder became available for download on Adobe Labs. This means that we can now start to play with the new Flex 4 SDK. There has been some controversy lateley about the pro’s and cons of Flex namespaces. I was in the pro camp as you can see in this post I made some time ago. But enough about this discussion ;)

If you want to have more information about the new Flex 4 SDK and what has changed you can go to the following articles:

For my first blog post about Flex 4 I want to show you one of the new components, and that’s the spark.components.DataGroup component. Why? Because I have been using the old mx.core.Repeater a lot and there is no repeater in the new spark components.

In the old days of Flex 3 you could use the Repeater class when you needed a very specific view for customizing a list of data. It would look something like this:

<mx:VBox>
    <mx:Repeater id="myRepeater">
        <mx:dataProvider>
            <local:Person firstName="Alain" lastName="Hufkens"/>
            <local:Person firstName="Hugh" lastName="Hefner"/>
            <local:Person firstName="Jimi" lastName="Hendrix"/>
        </mx:dataProvider>
        <mx:HBox>
            <mx:Label text="{myRepeater.currentItem.firstName}"/>
            <mx:Label text="{myRepeater.currentItem.lastName}"/>
        </mx:HBox>
    </mx:Repeater>
</mx:VBox>

This example here is pretty simple, but it gives you a list that displays the persons showing the first and last name. You could extend this with the person’s photo or address.

With the new DataGroup component you need a different approach and you need to work with ItemRenderers, something that already existed in the Flex 3 SDK. The next code snippets show you how to do this:

The first example uses the spark.skins.default.DefaultItemRenderer that can be used for very simple lists. By default the list outputs the toString() of an Object or in this example shows the String from the DataProvider.

<s:DataGroup itemRenderer="spark.skins.default.DefaultItemRenderer">
    <s:layout>
        <s:VerticalLayout gap="1" />
    </s:layout>
    <s:dataProvider>
        <s:ArrayCollection>
            <fx:String>Frog</fx:String>
            <fx:String>Cat</fx:String>
            <fx:String>Mouse</fx:String>
        </s:ArrayCollection>
    </s:dataProvider>
</s:DataGroup>

The next example uses the spark.skins.default.DefaultComplexItemRenderer. This ItemRenderer renders different Graphical and complex components. You can have a Component like a Button, DropDownList, … next to a graphical object like a Rect, Ellipse, … next to each other.

<fx:Declarations>
    <s:SolidColor id="fillColor" color="#fff000"/>
</fx:Declarations>

<s:DataGroup itemRenderer="spark.skins.default.DefaultComplexItemRenderer">
    <s:layout>
        <s:HorizontalLayout/>
    </s:layout>
    <s:dataProvider>
        <s:ArrayCollection>
            <s:Button label="Button" />
            <s:Rect fill="{fillColor}" width="20" height="20"/>
            <s:Ellipse fill="{fillColor}" width="20" height="20"/>
            <s:DropDownList />
        </s:ArrayCollection>
    </s:dataProvider>
</s:DataGroup>

That’s all pretty cool but it’s not what I needed. I just needed something that can present my Person object. So in this case we need to create a Custom ItemRenderer. This is a very easy thing to do and the end result is a lot better then the Repeater solution.

<s:DataGroup itemRenderer="PersonItemRenderer">
    <s:layout>
        <s:VerticalLayout/>
    </s:layout>
    <s:dataProvider>
        <s:ArrayCollection>
            <local:Person firstName="Alain" lastName="Hufkens"/>
            <local:Person firstName="Hugh" lastName="Hefner"/>
            <local:Person firstName="Jimi" lastName="Hendrix"/>
        </s:ArrayCollection>
    </s:dataProvider>
</s:DataGroup>

And this is the code for the PersonItemRenderer:

<s:ItemRenderer
 xmlns:fx="http://ns.adobe.com/mxml/2009"
 xmlns:s="library://ns.adobe.com/flex/spark"
 xmlns:mx="library://ns.adobe.com/flex/halo">
 
  <fx:Declarations>
  <s:SolidColor id="normalColor" color="#000000"/>
  <s:SolidColor id="hoveredColor" color="#FF0000"/>
  </fx:Declarations>
 
  <s:states>
    <s:State name="normal"/>
    <s:State name="hovered"/>
  </s:states>
 
  <s:layout>
    <s:HorizontalLayout/>
  </s:layout>
 
  <s:Ellipse fill="{normalColor}" fill.hovered="{hoveredColor}"
      width="10" height="10" />
  <s:SimpleText text="{data.firstName} {data.lastName}"
      color.hovered="#FF0000"/>
 
</s:ItemRenderer>

You can see the demo (including source) here.

One of the projects I am currently working on is an open source Actionscript library that wraps the Basecamp REST API in an easy to use AS3 classes. The project is called BasecampAS3Lib an can be found on Google Code. The project is still in development and I did some serious refactoring yesterday.

At this point the services can only retrieve data from Basecamp and you can already experiment with the ProjectService, CategoryService and TodoListService classes. The other services still need to be implemented. But this post will give you a sneak peak on how simple it can be to retrieve data (in this case project data) from Basecamp with this lib.

NOTE: This code only works in an Adobe AIR application (see below for more details why).

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
  xmlns:mx="http://www.adobe.com/2006/mxml"
  xmlns:basecamp="net.hufkens.basecamp.*"
  xmlns:services="net.hufkens.basecamp.services.*"
  layout="absolute"  viewSourceURL="srcview/index.html">
 
  <mx:VBox width="100%" height="100%">
    <mx:HBox width="100%">
      <mx:Label text="url:"/>
      <mx:TextInput id="apiurl" width="100"/>
      <mx:Label text="username:"/>
      <mx:TextInput id="username" width="100"/>
      <mx:Label text="password:"/>
      <mx:TextInput id="password" width="100"/>
      <mx:Button label="get projects"
        click="getProjects()"/>
    </mx:HBox>
    <mx:DataGrid dataProvider="{projects}"
      width="100%" height="100%"/> 
  </mx:VBox>
 
  <basecamp:BasecampAPI id="api"
    url="{apiurl.text}"
    username="{username.text}"
    password="{password.text}"/>
 
  <mx:ArrayCollection id="projects"/>
 
  <mx:Script>
    <![CDATA[
      import net.hufkens.basecamp.events.BasecampEvent;
     
      private function getProjects():void {
        api.projectService.addEventListener(
          BasecampEvent.GET_LIST, handleGetList);

        api.projectService.addEventListener(
          BasecampEvent.FAIL, handleFail);

        api.projectService.getList();
      }
     
      private function handleGetList(event:BasecampEvent):void {
        projects = new ArrayCollection(event.data as Array);
      }
     
      private function handleFail(event:BasecampEvent):void {
        Alert.show(event.data as String);
      }
     
    ]]>
  </mx:Script>
 
</mx:WindowedApplication>

However there is still an issue with the authentication. Apparently using basic authentication from a Flash/Flex application is not that trivial as it would sound. A while ago I wrote a blog post about this (read it here), but this approach only works when you run it from an AIR application. The same code doesn’t work when running from a url on a web site.

So, if you have any suggestions or a solution for the basic authentication issue please let me know.

Logo-templateI don’t have a lot of experience yet with tracking AIR applications developed with Flash or Flex. Adhese has a service called pubblegum that can be used directly from Flash without calling an external Javascript (which is the case with Google Analytics). So we decided to give it a try.

What exactly is pubblegum?

Whether it is Adobe® Flash®, Adobe® Air®, Microsoft® Silverlight®, Javascript or something as basic as an image. Pubblegum tracks your content in real-time from within the file and reports all available info, from custom interactions to URLs where your content was published.

Cool is that they have a specific API for AIR applications built in Actionscript 3 and the API also takes care of the fact that your application can be disconnected. If you want to use it, you can send them a mail to get a free trial. In our case we used the specific API for tracking user actions in the AIR application. And it is fairly easy to use. You only need to include the com.adhese.pubblegum.PubblegumAir class in your source code (a .swc file for Flex projects would also be nice guys) and write these two lines of code:

var api:PubblegumAir =
    new PubblegumAir("companyID", "campaignID", "creativeID", true);
api.action("action");

The first variable is provided by Adhese and should be your company name/identifier, the second and third parameter can be chosen freely. The last parameter specifies whether you are tracking an application. So true tells the API, that the client is an application.

That isn’t all that bad is it, and on top of that you get a nice dashboard where you can analyze your results.

Mar
31
Posted by Alain at 3:48 pm

air_appiconAt my company I developed an Adobe AIR application created in Flex for internal use. The application uses custom chrome because it has a specific designed interface. At the time we also decided to enable the transparency. To achieve this, you only need to change some settings in the AIR configuration file. This file is located in the root of your Flex project and ends with “-app.xml”. The first setting turns off the default OS specific chrome and the second one make the application transparent.

<systemChrome>none</systemChrome>
<transparent>true</transparent>

This is all very cool, and it worked out great for me. Sure, the application used a bit more CPU then expected, but that’s a known issue for AIR applications. But some of my colleagues complained that their CPU went through the roof (more than 50% while doing nothing) and the application became unstable. Wouter Martens (currently doing his internship) stumbled upon this blog post because he also had the CPU issue on his machine. It turns out that the problem is depended on hardware, and that explains why some people have issues and others don’t. We tested the same application without the transparency and the CPU issue was gone.

Luckily it turns out that we don’t really need the transparency, and that we can easily change the design without a lot of impact. Changing the transparent setting in the xml file to “false” did the trick.

<systemChrome>none</systemChrome>
<transparent>false</transparent>

This demonstrates that it’s not that trivial to create a cross-platform run-time, that also behaves consistent over all platforms and all hardware.

For an internal project I created an Adobe AIR application that connects to the Basecamp API. We have been using the application since the launch of Adobe AIR. Back then I had a problem connecting to the API using the HTTPService, because the combination of Basic Authentication and the https protocol was not supported. After several unsuccessful experiments I decided to go for an approach that uses a PHP Proxy on the server that delegates the calls to the Basecamp API. However the downside of this approach is that this setup needs extra configuration and a server-side deployment.

This week I got the chance to pick it up again and I stumbled upon this forum post on the Basecamp Forum. I found this piece of code posted on Verveguy’s blog. And it actually did the trick.

private function addAuthHeader(service:HTTPService,
                     username:String, password:String):void
{
    //add the header to request
    var enc:Base64Encoder = new Base64Encoder();
    enc.encode(username + ":" + password);
    service.headers["Authorization"] = "Basic " + enc.toString();
}

For everybody who needs to connect a Flex application to an API that uses https in combination with Basic Authentication, here is the solution. All credits to the original blog post.

Mar
14

lita_iconI have been working on a couple of AIR applications, one of them being Airbob an open source Cruise Control monitor tool. This was the first AIR application I wrote way back when Adobe AIR 1.0 was released. For local data I also used SQLite which is very useful for saving state and preferences of your application.

There are several administration tools available, but none of them were really that good. David Deraedt wrote a complete SQLite Administration Tool using Flex and Adobe AIR called Lita, and it is very good and pretty useful when you need to dive into thise .db files.

Check out the list of features:

  • A free, multiplatform administration tool for your SQLite Databases
  • Open, create, compact databases
  • Create, rename, delete, and empty tables
  • Create, rename and delete columns
  • Create, modify and delete records
  • Encrypt or reencrypt your databases
  • Easily run your custom SQL statements
  • Create and delete indices

Screenshot:

lita

So great work David, and for more information about this tool and the install link, got to his blog.

Mar
10

I am currently working on an AIR application developed using the Flex 3 SDK. The problem I am facing now, is that I need to restart my application from code. This sounds very easy, you would think. My first guess would be that there should be a method on the NativeApplication object like:

NativeApplication.nativeApplication.restart();

But this method does not exist. There is an exit method, but no restart method. So I “googled” around and came to some interesting articles describing how to do this.

The Joy of Flex blog wrote an article “Can an AIR application restart itself?” I tried it out, but this did not work for my project. The code actually steps through the methods but the application never restarts. The article also says that there are serious problems with this approach. So probably I am in the case where the exit beats the launch.

So my next approach was this article by David Tucker: “AIR Tip 11 – Launching an AIR Application from an AIR Application“. It actually described how to launch an AIR application from another application. This is what has been used in the first article, so back to start.

Then I found this interesting peace of code on Flex Internals:

package
{
  import mx.core.Application;
  import mx.core.WindowedApplication;
  import adobe.utils.ProductManager;

  public function reboot():void
  {
    var app:WindowedApplication =
        WindowedApplication(Application.application);
   
    var mgr:ProductManager =
        new ProductManager("airappinstaller");
   
    mgr.launch("-launch " +
        app.nativeApplication.applicationID + " " +
        app.nativeApplication.publisherID);
   
    app.close();
  }
}

Also make sure that the “allowBrowserInvocation” option is turned on in the AIR application descriptor template:

<allowBrowserInvocation>true</allowBrowserInvocation>

So this was actually what I needed, and it worked!
Any feedback is appreciated :)

Feb
14
Posted by Alain at 10:41 am

fx-gumboYesterday Adobe decided to remove the Fx prefix from the new Flex 4 (aka Gumbo) components. The debate was whether components in the next version of Flex should all start with the letters “Fx” or use namespaces to resolve possible conflicts with legacy components like Button, Panel and ScrollBar. After playing around with the new Flex components, it felt a little strange to use for example a FxButton for the new stuff because in the end it just a button. In other language has been be solved using namespaces so why not keep it clean and use a specific namespace for one architecture and another one for the new.

The Flex SDK team has decided and is going for the multiple namespace solution. Read more about this in this topic: “Kittens saved, Fx prefix will go away“. The cool thing is that when the topic came up for debate Adobe asked the community for input in this forum post. So now that’s out of the way I can’t wait using Flex 4.