"adobe" Posts

Flex SDK 4.5 doesn’t keep Embed Metadata

Hey everyone,

I’ve run into a bug with the released version of the Adobe Flex 4.5 SDK. The 4.5 version of the SDK does not respect keeping [Embed] metadata in your SWF. This is problematic because we use this metadata extensively in PushButton Engine.

Take the following example into account:

TestMetadata.as

package
{
    import flash.display.Sprite;
    import flash.utils.describeType;
 
    public class TestMetadata extends Sprite
    {
        public function TestMetadata()
        {
            var typeInfo:XML = describeType(TestClassWithEmbed);
            trace(typeInfo);
        }
    }
}

TestClassWithEmbed.as

package
{
    public class TestClassWithEmbed
    {
        [Embed(source="assets/flip.png", mimeType="image/png" )]
        public var Flip:Class;
 
        [SomeMeta(source="assets/flip.png", mimeType="image/png")]
        public var Test:Class;
    }
}

In version 4.1 of the Adobe Flex SDK, we get the following back from describeType.

<variable name="Test" type="Class">
  <metadata name="SomeMeta">
    <arg key="source" value="assets/flip.png"/>
    <arg key="mimeType" value="image/png"/>
  </metadata>
  <metadata name="__go_to_definition_help">
    <arg key="file" value="/projects/zaalabs/workspace/TestMetadata/src/TestClassWithEmbed.as"/>
    <arg key="pos" value="243"/>
  </metadata>
</variable>
<variable name="Flip" type="Class">
  <metadata name="Embed">
    <arg key="source" value="assets/flip.png"/>
    <arg key="mimeType" value="image/png"/>
  </metadata>
  <metadata name="__go_to_definition_help">
    <arg key="file" value="/projects/zaalabs/workspace/TestMetadata/src/TestClassWithEmbed.as"/>
    <arg key="pos" value="136"/>
  </metadata>
</variable>

However, in version 4.5 of the Adobe Flex SDK, you can see the Embed metadata is being omitted. Same exact code, same compiler arguments, nothing has changed except the SDK.

<variable name="Test" type="Class">
  <metadata name="SomeMeta">
    <arg key="source" value="assets/flip.png"/>
    <arg key="mimeType" value="image/png"/>
  </metadata>
  <metadata name="__go_to_definition_help">
    <arg key="pos" value="243"/>
  </metadata>
</variable>
<variable name="Flip" type="Class">
  <metadata name="__go_to_definition_help">
    <arg key="pos" value="136"/>
  </metadata>
</variable>

As you can see, the Embed metadata is being stripped out, even though I explicitly set “–keep-as3-metadata+=Embed,SomeMeta” in the compiler. Since I don’t believe that the Adobe Flash Player team would break describeType in a minor release, I’m led to believe that this is a bug that was introduced in the 4.5 version of mxmlc in the Flex SDK.

Rant

:: UPDATE ::

This seems to have been an isolated incident on this specific day, bugs.adobe.com has worked well for me many times since then.

————————————————————————–

So I tried to do the “correct” thing and file this as a bug on bugs.adobe.com. And would happily do so if the site worked. In fact, in the time I’ve been waiting for bug.adobe.com to load and let me login… not only did I write the test case, but I wrote this entire blog post as well.




[UPDATE]
I was finally able to file the bug, I think… it won’t pull it up. SDK-30485.

10 minutes to diagnose the issue…
15 minutes to blog about it…
45 minutes… and counting to file a bug through the proper channels.

Adobe Flex to JavaScript… why Conversion is Hard

I recently had a conversation with Simeon Bateman regarding the woes of mobile web development. We realized one of the reasons why Flex developers as in general have a hard time embracing JavaScript development.

The Problem

The particular JavaScript quirk we were discussing was window.innerHeight functions on mobile devices.  During our development on mobile devices, we ran into two frustrating issues.

Simeon’s issue was with the way window dimensions get messed up when an Android device is re-oriented.

My issue was with the way that window.innerHeight tells you how much space you have with the url bar on the screen, until the url bar is scrolled off the screen, then it reports the actual space that you can work with (since this is my post we’ll talk about my problem). This issue if frustrating because I’m trying to get a webpage to take up the whole screen on the mobile device, with the url bar scrolled out of view.

To illustrate what I’m discussing, I’ll show side by side screenshots.  The screenshot is of a page that reports the screen height and width and the window innerHeight and width and updates them on an interval.  On the left you have the URL bar, on the right the URL bar has been scrolled off the screen.  Notice how the screen size has remained the same, but the window.innerHeight has changed.

Window Size with URL barWindow Inner Height without URL bar

We both understood the problems we faced, but both believed there had to be a good and right way to solve the problem, a “best practice” if you will.  Having spent time working in the Flex community, we had come to expect an elegant way of solving the issues we faced.

Neither of us are foreign to forging our own paths through new territory, but we’re generally used to coming to a solution that feels right.  When things start getting hacky we feel like we’re in the wrong place and try to research the problem looking for a more elegant solution.

Finding A Solution

In our scenario with window.innerHeight we were trying to think how we could go about getting the height of the space we can use in an elegant fashion, and couldn’t come up with anything.  We knew how to accomplish our tasks in an inelegant fashion, but thought it was a common enough task that there would be a “right” or elegant solution.

Finally we realized that we knew of people out there who were doing what we wanted, and this is JavaScript after all, so we went and looked at the source. We checked in a few places, and discovered that most of the places we checked handled this problem in a similar way.  The great guys over at Sencha had this in their code for handling this problem and making sure the application is the correct size.

init: function (c, b) {
    var d = this,
        e = Math.max(window.innerHeight, window.innerWidth) * 2,
        a = Ext.getBody();
    d.updateOrientation();
    this.initialHeight = window.innerHeight;
    this.initialOrientation = this.orientation;
    a.setHeight(e);
    Ext.gesture.Manager.freeze();
    this.scrollToTop();
    setTimeout(function () {
        d.scrollToTop();
        setTimeout(function () {
            d.scrollToTop();
            d.initialHeight = Math.max(d.initialHeight, window.innerHeight);
            if (c) {
                c.apply(b || window)
            }
            d.updateBodySize();
            Ext.gesture.Manager.thaw()
        }, 500)
    }, 500)
}

The variable names are not great as its beautified code that was minified, but if you follow it you can see what they’re doing.

In order to size the app to the proper height and be able to have the url bar scrolled off the top, they have to double the size of the container, to ensure that they can scroll past the url bar. Then they scroll… twice on 500ms timeouts, and then they can fix the size of the app to bring the size down to what it really is without the url bar, since window.innerHeight will now report they value they want.

The Difference

This is where JavaScript development diverges from Adobe Flex development.  The fractured landscape of so many browsers and the impossibility of getting users to upgrade in a timely manner has left JavaScript developers with no choice but to hack their way through.

This is not to say that JavaScript lacks elegance… but that there are some areas where the hack is just what you need to do.

In Flex there are times where you need to implement a hack, but you generally implement it as a patch to the Flex SDK and your application code is spared the hack. This example underscores one of the big issues that Flex developers face as they move from the world of the Flash Player to the fractured world of browsers. To a Flex developer this feels like an inelegant hack, but to a JavaScript developer this is a great solution, because it works across all the different platforms we need to support.

Conclusion

I don’t present this information as a way of excusing Flex Developers from exploring HTML/JS development, but wanted to help developers understand this difference that can help on both platforms.

With this new found understanding if you feel like hopping into some HTML/JS development, may I suggest another article, by Simeon Bateman.

Adobe Flash ExternalInterface issues with Internet Explorer

On a recent project, I was asked to build a simple Flash mp3 player that could be controlled with JavaScript by using ExternalInterface.  I built and tested the whole application in under an hour and was feeling pretty good about myself.  QA filed a bug saying that JavaScript was throwing an error, and it only occurred when my mp3 player was present.

The error only happened in IE8, so I was stuck with IE’s debugger and error messages.  The error was being thrown when the loaded SWF attempted to add callbacks to ExternalInterface using ExternalInterface.addCallback  As soon as this function was called my script threw an error:

Object doesn’t support this property or method

IE 8 Error Screen

The stack trace showed an anonymous JScript block with a function named __flash__addCallback which was throwing the error when trying to append a property to a JScript object. The debugger for this particular error looked like this.

I scoured the internet searching for solutions to this problem as I was sure it had to be something that was well documented.  I came across some solutions that appeared to work for people such as: ensure your object tag has an id, ensuring you set the type or class id on the object tag. These solutions worked for some people, but didn’t solve the problem I was having.

After a little more investigation I realized that some of my ExternalInterface calls were successful, while others were not.  I then realized that play and stop were probably reserved names for IE8 and might be the root of my problem.  I adjusted the names of the callback functions to playSong and stopSong and things started working.

This Doesn’t Work:

ExternalInterface.addCallback("play", play);
ExternalInterface.addCallback("stop", stop);

This Works:

ExternalInterface.addCallback("playSong", play);
ExternalInterface.addCallback("stopSong", stop);

The moral of the story is to avoid common names when using ExternalInterface. Play and Stop I know are reserved, and I’m sure there’s a host of others out there.

Tip of the Day – Updating to Flash Builder 4.0.1

I recently posted about Building AIR 2 applications with Flash Builder 4.

There is now an update for Flash Builder 4 which downloads and installs the Adobe Flex 4.1 SDK. According to Renaun Erickson’s post, Flex 4.1 includes Flash Player 10.1 and AIR 2.0.

Now, if you’re like me and loathe the Adobe Updater… then you probably turned off the Adobe Updater notifications.

So here’s how to update Flash Builder to version 4.0.1 which includes the 4.1 SDK.

Go to Help > Search for Flash Builder Updates…

Help - Search for Flash Builder Updates...

This will launch the Adobe Application Manager and then proceed to update your software, including Flash Builder 4.

== UPDATE ==

If you don’t see a Flash Builder update available in Adobe Application Manager, you can download the standalone updater from Adobe.

Update Progress

Update Complete

Once the update is completed you can see Flash Builder is now at version 4.0.1.

Flash Builder 4.0.1 about screen

And you now have the option for Flex 4.1 as an installed Flex SDK. You can use Flex 4.1 to develop against Flash Player 10.1 and Adobe AIR 2.0.

4.1 is now avaliable