ExternalInterface to Make your flex methods Callable via HTML/Javascript

Its greate Experience working with addCallBack method and finally I got it working. I tried various ways. First I simply register the method in flex using addCallBack function but I didnt succeeded. After looking through live docs and reading more about it I come know swf initiates the and talks with browser that swf is ready to accept the call from HTML pages. How did I achieve this?

Here is my Mxml code

MXML Application:

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; layout=”absolute” creationComplete=”initApp();”>
<mx:Script>
<![CDATA[

import flash.external.*;
import mx.controls.Alert;
public var readyTimer:Timer;
public var javascriptMethodCounter:int = 0;

public function initApp():void
{
if (isContainerReady())
{
// If the container is ready, register the SWF’s functions.
setUpCall();
}
else
{
/* If the container is not ready, set up a Timer to call the
container at 100ms intervals. Once the container responds that
it’s ready, the timer will be stopped. */
readyTimer = new Timer(100);
readyTimer.addEventListener(TimerEvent.TIMER, timerHandler);
readyTimer.start();
}
}

public function showAlert(message:String):void
{
javascriptMethodCounter++;
javascriptCounterText.text = javascriptMethodCounter + ” times javascript function called “;
javascriptMessageLogger.text = message;
}

public function timerHandler():void
{
if (isContainerReady())
{
// If the container is ready, register the SWF’s functions.
setUpCall();
readyTimer.stop();
}
}

//setup the callback function so that HTML can call flex methods
public function setUpCall():void
{
ExternalInterface.addCallback(“showAlert”,showAlert);
}

//Checks wheather HTML page is loaded or not.
private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call(“isReady”);
Alert.show(“Result :”+result)
return result;
}
]]>
</mx:Script>
<mx:Panel x=”10″ y=”10″ width=”386″ height=”200″ layout=”absolute”>
<mx:TextArea x=”10″ y=”36″ width=”346″ height=”114″ id=”javascriptMessageLogger”/>
<mx:Label x=”10″ y=”10″ text=”times javascript function called” width=”260″

id=”javascriptCounterText”/>
</mx:Panel>

</mx:Application>

Above code comprises of following method :

initApp : This methods will get call on the creationComplete of an event. This checks wheather swf is ready for

to accept call from HTML/javascript or not.

isContainerReady: this simply call one javascript function which returns boolean value.

timerHandler: after calling isContainerReady function if result if false, we register a timer which gets call

every 100ms to register the swf communication. When successful timer get stoped and call setUpCall method.

setUpCall: Simply registers the Flex method with ExternalInterface addCallBack method.

showAlert: This is the method which we are registered to be callable via HTML

Controls :

javascriptMessageLogger : Displays the message passed via javascript method

javascriptCounterText: Shows the number of times methods get called from javascript.

HTML code:

<script language=”javascript”>
var interfaceObj;

function callFlexMethod()
{

if(navigator.appName.indexOf(“microsoft”)!=-1)
{
alert(“Microsoft”);
interfaceObj = window[“ExternalInterface1”];
}
else
{
interfaceObj = document[“ExternalInterface1”];
}
}

// ——- Private vars ——-
var jsReady = false;

// ——- functions called by ActionScript ——-
// called to check if the page has initialized and JavaScript is available
function isReady() {
return jsReady;
}

// called by the onload event of the <body> tag
function pageInit() {
// Record that JavaScript is ready to go.
jsReady = true;
callFlexMethod();
}

</script>

isReady : Simply returns the state of jsReady variable

pageInit: this method get called on onload event of page. This function makes jsReady true and get the copy of swf object into interfaceObj variable

callFlexMethod: Determines the browser type and get the proper object out of it

Form Element:

Enter Text : <input type=”text” id=”myText”><input type=”button” value=”Send to Flex” onclick=”interfaceObj.showAlert(document.getElementById(‘myText’).value);”>

myText: This is where we enter the message we want to passed to flex method.

Button : Onclick of button showAlert method of flex application get call with value from textInput.

I was able to successfully makes flex methods available to javascript and call it from javascript. One more thing it should be run from webserver.

Screenshot for the javascript flex communication for the above application

15 Responses to ExternalInterface to Make your flex methods Callable via HTML/Javascript

  1. Pedro says:

    Hi Vijay,

    Your solution for the JS to AS works great. I’ve also understood what I was doing wrong.
    Thanks for all your help and quick response.

  2. Janaki says:

    hi,
    i am a newbee for Flex. i have created an Action Script (2) application which has multiple frames suing Flash 8. now i thought of transofrming it in Flex. so how should i simulate those frames in flex UI. basically i am looking for linking pages or Mxml files in Flex. will u pls help me.

    Thanks,
    ~J~

  3. I am not sure how you can import your flash app into flex, as flex has different approches of design as well as components and controls which makes application development very easy. You can take a look into the documentation part of flex. After reading you will get the good idea of how to it.

    if you face any problem in particular area/section let me know. I will try to solve your doubts

    Thank You

  4. Georges says:

    Marvelous !!!!!!!!!!!!!!!

    You’re a King !!!!
    and bla bla blabla bla blabla bla blabla bla blabla bla blabla bla bla for the eternity ….

    Thanks a lot !

    GeO

  5. ani says:

    Hi,
    I am new to flex and i m trying above code. All things are executing properly only the call is not reaching ‘showAlert’ function. Can u please help me in this.

  6. I have forwared both the sample of externalInterface on your email sample included example of flex to javascript and vice versa. Hope this helps

  7. ani says:

    Thanks for such a quick response.I had found the problem and solved it.

  8. Zeeshan Malik says:

    Hi,
    Thanks for the code. I made a project in Flex builder 2 and executed your code. I only made changes to the html file which flex builder created in bin folder. But when I open the html code in the browser I get following error as soon as page loads.

    ArgumentError: Error #1063: Argument count mismatch on JavaScriptAndActionScriptComm/timerHandler(). Expected 0, got 1.
    at flash.utils::Timer/flash.utils:Timer::_timerDispatch()
    at flash.utils::Timer/flash.utils:Timer::tick()

    My html file code is as following:

    body { margin: 0px; overflow:hidden }

    var interfaceObj;

    function callFlexMethod()
    {

    if(navigator.appName.indexOf(“microsoft”)!=-1)
    {
    alert(“Microsoft”);
    interfaceObj = window[“ExternalInterface1”];
    }
    else
    {
    interfaceObj = document[“ExternalInterface1”];
    }
    }

    // ——- Private vars ——-
    var jsReady = false;

    // ——- functions called by ActionScript ——-
    // called to check if the page has initialized and JavaScript is available
    function isReady() {
    return jsReady;
    }

    // called by the onload event of the tag
    function pageInit() {
    // Record that JavaScript is ready to go.
    jsReady = true;
    callFlexMethod();
    }

    <!–
    // Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)
    var hasProductInstall = DetectFlashVer(6, 0, 65);

    // Version check based upon the values defined in globals
    var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);

    // Check to see if a player with Flash Product Install is available and the version does not meet the requirements for playback
    if ( hasProductInstall && !hasRequestedVersion ) {
    // MMdoctitle is the stored document.title value used by the installation process to close the window that started the process
    // This is necessary in order to close browser windows that are still utilizing the older version of the player after installation has completed
    // DO NOT MODIFY THE FOLLOWING FOUR LINES
    // Location visited after installation is complete if installation is required
    var MMPlayerType = (isIE == true) ? “ActiveX” : “PlugIn”;
    var MMredirectURL = window.location;
    document.title = document.title.slice(0, 47) + ” – Flash Player Installation”;
    var MMdoctitle = document.title;

    AC_FL_RunContent(
    “src”, “playerProductInstall”,
    “FlashVars”, “MMredirectURL=”+MMredirectURL+’&MMplayerType=’+MMPlayerType+’&MMdoctitle=’+MMdoctitle+””,
    “width”, “100%”,
    “height”, “100%”,
    “align”, “middle”,
    “id”, “JavaScriptAndActionScriptComm”,
    “quality”, “high”,
    “bgcolor”, “#869ca7”,
    “name”, “JavaScriptAndActionScriptComm”,
    “allowScriptAccess”,”sameDomain”,
    “type”, “application/x-shockwave-flash”,
    “pluginspage”, “http://www.adobe.com/go/getflashplayer”
    );
    } else if (hasRequestedVersion) {
    // if we’ve detected an acceptable version
    // embed the Flash Content SWF when all tests are passed
    AC_FL_RunContent(
    “src”, “JavaScriptAndActionScriptComm”,
    “width”, “100%”,
    “height”, “100%”,
    “align”, “middle”,
    “id”, “JavaScriptAndActionScriptComm”,
    “quality”, “high”,
    “bgcolor”, “#869ca7”,
    “name”, “JavaScriptAndActionScriptComm”,
    “flashvars”,’historyUrl=history.htm%3F&lconid=’ + lc_id + ”,
    “allowScriptAccess”,”sameDomain”,
    “type”, “application/x-shockwave-flash”,
    “pluginspage”, “http://www.adobe.com/go/getflashplayer”
    );
    } else { // flash is too old or we can’t detect the plugin
    var alternateContent = ‘Alternate HTML content should be placed here. ‘
    + ‘This content requires the Adobe Flash Player. ‘
    + ‘Get Flash‘;
    document.write(alternateContent); // insert non-flash content
    }
    // –>

    Thank you for your help.

  9. if you are using addEventListener methods to catch an event, every events passes the event object as a parameter to the function. In this case you need to have a correct signature for the method.

    Your error shows that one argument is passed to the function, but the called function did not have the correct parameter. Just change your function to accept the correct parameter

    eg. function timeHandler(event:Event){}

  10. Zeeshan Malik says:

    Yeah i changed that and it’s working now. But I’m unable to fill out the html file properly. So could you please send me the html file.

    Thanks
    Zeeshan

  11. Rodrigo says:

    I did exactly as in your example, but the following call always return false:

    var result:Boolean = ExternalInterface.call(“isReady”);

    I put an alert in the javascript function to show the value of the jsReady variable and it shows true, but this value is not being returned to the action script.

    Any ideas??

  12. Satyajit says:

    hi vijay,
    thanks for the code.
    i tried ur code it works perfectly but, it worked for first time and as soon as i closed my project and reopened it. the code in html file in bin dir was overwritten and all the javascript functions vanised away. so please can help me to overcome this problem.

  13. hi,

    you can have the javascript code in different file. This javascript code you can always embed in the HTML file after the project build. Or else you can create different HTML page so that its not overwritten everytime you build the project.

  14. rahul says:

    hello ,
    i m new user of flex..
    i have flex application but it is not run without html file so how i can solve this problem?

  15. Alex says:

    Hi Vijay,

    I tried the code you post it here, but always get the error about “interfaceObj is undifined”.

    I found that for this line : “interfaceObj = document[“ExternalInterface1″];” interfaceObj never assigned anything.

    Do you know why is that? I’m running with flex3+ff rc2

    Thank you,
    Alex.

Leave a reply to Alex Cancel reply