HomeBlogFlash's ExternalInterface and IE

Flash's ExternalInterface and dynamic loading

Grr, I lost the whole day yesterday fighting this up.  Flash (starting from version 8 I think?) has this magic ExternalInterface API, which is quite useful.  With it, you can define an API for your SWF that external JavaScript will be able to access (almost) as if your flash object was a JS object.  Also, using ExternalInterface you can call JavaScript functions from Flash.

Going quickly through how useful this is: basically I was playing with XMLSocket and wanted to be able to call it from JavaScript.  In fact I don't like Flash at all, but it has this amazing XMLSocket functionality, you know, something that JS should have provided, like, 12 years ago.  So because browsers' JS engines don't provide this utterly basic interface that any other client-side environment on the Planet has, I had to resort to Flash to play with it.

So I coded my very simple and invisible SWF, which only exports an interface to XMLSocket that I can use from JS.  I learned a few things and thought I'd write about my experiences here (before you flame my genuine lack of Flash knowledge, please understand that it's the second time in my life when I touch Flash and all I wanted was to get out of that IDE ASAP :D  I hate it.).

  1. External interface doesn't work if your applet is really invisible.

    Or at least, that's my conclusion.  If I put width="0" and height="0" on the <embed> and <object> tags, bye bye ExternalInterface.  In fact, bye bye Flash—nothing seemed to work.

    So I had to resort on adding width="1" and height="1".  After this hack, everything worked fine in all but the most problematic browser of All Time (InternetExplorer).

  2. External interface doesn't work in Internet Explorer unless you're loading the SWF during page load.

    It's pretty simple: my code uses a JavaScript widget library (that I'll eventually release).  In it I added a Socket communication object that relies on Flash's ExternalInterface + XMLSocket.  Because this object might or might not be used, it makes no sense to load the SWF during page load.  So I add the SWF later in a DIV, using innerHTML.

    I spent all day debugging this in Internet Explorer (while Firefox and Safari were doing just fine; I'm not sure about Opera yet).

    In order to make it work in IE while still not loading the SWF from the start, I had to create an IFRAME where I loaded the SWF—this time it registers the ExternalInterface alright.  I also couldn't play with making the IFRAME invisible (i.e. width=0, or display: none) — that won't work, you have to hide it differently (by i.e. positioning it outside the viewable area).

Back to basics

Isn't “old school” great?  I don't want to use Flash, but I have to because by default, browsers don't have anything that would allow me to open an arbitrary TCP connection.  Why?  The things you can do with XMLSocket are amazing—like, being connected to the server.

Some folks have imagined ingenious ways (Comet) to do this with existing infrastructure: because HTTP is a request/response-based protocol, it means that the server can't tell something to the browser unless the browser has requested that something.  So the nifty idea was to make an XMLHttpRequest (yay, AJAX!) from the browser, request that the server would not respond until it has something to say.  Like “incoming move from your opponent” in a multiplayer game.  That is called a “long lived” request, since the socket is open and the client waits for information, which the server will eventually send.  This looks pretty much the same as the good old select() to me, but hey—this time it's AJAX.

There are multiple problems with this approach, however—such as the fact that on some server platforms, such a request will uselessly block a server process.  Of course, then they invented “non-blocking IO”, which alleviates the problem.  Java has this (but I can't describe how much I don't like Java).

Then, the HTTP standard enforces a limit on the concurrent requests from a client to a server: the client can open at most 2 simultaneous requests.  This means that while your AJAX request waits for some answer, you can only do at most one other request to the server.  As you can guess—there are ways to work around this too.

Then, there's also an overhead for every request—such as a DNS lookup, a client-server handshake, etc.  This could never match the performance that an already open socket provides.

So what I don't understand is: why the heck don't we have plain old sockets?  So simple, so powerful, so old and proven—and yet we invent buzzwords to work around this limitation!...

Comments

  • By: David HigginsApr 04 (01:31) 2008RE: Flash's ExternalInterface and IE §

    Mihai, I'm stuck with the same problem that you appear to have been struck with ... which is trying to load SWF's after the 'page load' dynamically using the SWFObject library ...

    Is this a verifiable 'issue' with IE and Flash, as relates to the ExternalInterface failing to wireup the events?

    Do you know of any better way to do this ... perhaps maybe have a SWF that is always loaded onto the pages and uses LocalConnection to listen for late-loaded SWF's to say "Hey, wire up some events on behalf of me, please" ... perhaps?

    • By: mishooApr 04 (20:47) 2008RE[2]: Flash's ExternalInterface and IE §

      Yes, this issue happens always with IE.  I don't think you can trick it with an additional Flash applet, but the IFRAME-based solution works fine and it isn't too much overhead.

      • By: meconfAug 10 (17:13) 2009RE[3]: Flash's ExternalInterface and IE §

        Hi, I've been having this problem, and I haven't been able to fix it.
        I am trying to use this IFRAME-based solution, however it doesn't work for me.
        Can anyone provide me snippet of the source code?
        Thank a lot for the help in advance.

        <iframe width="1" height="1" src=""></iframe>
                            <object id="XXXRow${rownum}Col${col}IE" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%">
                            <param name="movie" value="XXX.swf">
        <param name="wmode" value="transparent">            <param name="allowScriptAccess" value="always"/>
                            
                            <!--[if !IE]>-->
                            <object id="XXXRow${rownum}Col${col}" type="application/x-shockwave-flash" data="XXX.swf" width="100%" height="100%" style="outline:none;">            <param name="wmode" value="opaque">                    <param name="allowScriptAccess" value="always"/>
        </object>
                            <!--<![endif]-->

                            </object>

  • By: Vivek LakhanpalJun 09 (10:29) 2008RE[3]: Flash's ExternalInterface and IE §

    Try putting id in Object tag and it will work in IE as well, without using Iframe etc. It work for me at least.

    • By: nac spaniardMar 10 (19:41) 2010RE[4]: Flash's ExternalInterface and IE §

      Thank you so so so much! After having wasted two days trying to find out what the hell was wrong, this finally worked for me. I hate IE, I hate Flash, damn it! ;)

  • By: offirOct 15 (00:27) 2008RE: Flash's ExternalInterface and IE §

    Here is an alternative to using an iframe. With this you should be able to invoke a method on a flash object that was constructed in a DIV in runtime:

    function invokeFlashMethod(methodName, arg1, arg2, arg3)
    {
        var flsh;
        var userAgent = window.navigator.userAgent.toLowerCase();
        var isIE = (userAgent.indexOf('msie') >= 0);
        var isSafari = (userAgent.indexOf('webkit') >= 0) || (userAgent.indexOf('safari') >= 0);
        if (isIE || isSafari) {
            flsh = $(MyFlashObjectId);
        }
        else {
            flsh = document[MyFlashEmbedId];
        }
        
        
        var res = null;
        if (isIE) {
            var args = [];
            if (arg1) {
                args.enqueue(arg1);
            }
            if (arg2) {
                args.enqueue(arg2);
            }
            if (arg3) {
                args.enqueue(arg3);
            }
            var xmlArgs = window.self.__flash__argumentsToXML(args, 0);
            var xml = '<invoke name=\"';
            xml = xml + methodName;
            xml = xml + '\" returntype=\"javascript\">';
            xml = xml + xmlArgs;
            xml = xml + '</invoke>';
            var funcRes = flsh.callFunction(xml);
            if (!isNullOrUndefined(funcRes)) {
                res = eval(funcRes);
            }
        }
        else {
            if (!arg1) {
                res = flsh[methodName]();
            }
            else if (arg1 && !arg2) {
                res = flsh[methodName](arg1);
            }
            else if (arg1 && arg2 && !arg3) {
                res = flsh[methodName](arg1, arg2);
            }
            else {
                res = flsh[methodName](arg1, arg2, arg3);
            }
        }
        return res;
    }

  • By: EricJan 17 (23:55) 2009RE[4]: Flash's ExternalInterface and IE §

    Adding an id to the object tag worked a treat for me. Thanks!

  • By: vfleurimaMar 27 (01:56) 2009RE[2]: Flash's ExternalInterface and IE §

    I ran into similar issues usingdynamically-generated elements with Externalnterface + Flash 10 + IE 7 + SWFObject 1.5. The fix for me was to ensure that whatever element I ended up calling SWFObject.write() on was previously appended to the DOM using appendChild() or somesuch.

  • By: M.RahmanOct 20 (12:55) 2009RE[2]: Flash's ExternalInterface and IE §

    though not the one asking, that was so inspiring, Offir

  • By: Marco SchlenderOct 20 (20:38) 2009RE[4]: Flash's ExternalInterface and IE §

    this is the best fixing. one id and the problem is killed :o)

  • By: Andre MarbeckNov 26 (15:45) 2009RE: Flash's ExternalInterface and IE §

    Thanks for this great Blog.
    I thought, I'll never get this *§$% SWC running in IE... :-)
    Just a little id...

  • By: OlehOct 08 (18:24) 2010Object doesn't support this ptoperty or method §

    Hi, I have a problem with calling swf from javascript when move my swf application from one to another html element by appendChild.

  • By: uyafsb xijuNov 22 (12:47) 2011RE[2]: Flash's ExternalInterface and IE §

    Zdsav aes d cxz

Page info
Created:
2007/11/07 18:59
Modified:
2007/11/07 23:50
Author:
Mihai Bazon
Comments:
16
Tags:
flash, javascript, programming
See also