Exempel på extern API: kommunicera mellan ActionScript och JavaScript i en webbläsareFlash Player 9 och senare, Adobe AIR 1.0 och senare I det här exempelprogrammet demonstreras lämpliga tekniker för kommunikation mellan ActionScript och JavaScript i en webbläsare, i det här fallet i ett snabbmeddelandeprogram som gör att en person kan chatta med sig själv (därav programnamnet: Introvert IM). Meddelanden skickas mellan ett HTML-formulär på webbsidan och ett SWF-gränssnitt med det externa API:t. Teknikerna som demonstreras i det här exemplet innehåller följande:
Programfilerna för det här exemplet finns på www.adobe.com/go/learn_programmingAS3samples_flash_se. Programfilerna för Introvert IM finns i mappen Samples/IntrovertIM_HTML. Programmet består av följande filer:
Förberedelser för kommunikation mellan ActionScript och webbläsarenEtt av de vanligaste sätten att använda det externa API:t är för att låta ActionScript-program kommunicera med en webbläsare. Med det externa API:t kan ActionScript-metoder anropa kod som skrivits i JavaScript och vice versa. Eftersom webbläsare är så komplicerade och eftersom de renderar sidor internt går det inte att garantera att ett SWF-dokument kan registrera sina callback-funktioner innan den första JavaScripten på HTML-sidan körs. Därför bör alltid SWF-dokumentet anropa HTML-sidan för att meddela den att SWF-dokumentet är klart att ta emot anslutningar innan funktionerna i SWF-dokumentet anropas från JavaScript. Introvert IM avgör till exempel genom en serie steg som utförs av klassen IMManager om webbläsaren är klar för kommunikation och förbereder SWF-filen för kommunikation. Det första steget, som avgör när webbläsaren är klar för kommunikation, utförs i IMManager-konstruktorn på följande sätt: public function IMManager(initialStatus:IMStatus) { _status = initialStatus; // Check if the container is able to use the external API. if (ExternalInterface.available) { try { // This calls the isContainerReady() method, which in turn calls // the container to see if Flash Player has loaded and the container // is ready to receive calls from the SWF. var containerReady:Boolean = isContainerReady(); if (containerReady) { // If the container is ready, register the SWF's functions. setupCallbacks(); } 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. var readyTimer:Timer = new Timer(100); readyTimer.addEventListener(TimerEvent.TIMER, timerHandler); readyTimer.start(); } } ... } else { trace("External interface is not available for this container."); } } Först kontrolleras om det externa API:t överhuvudtaget är tillgängligt i den aktuella behållaren med hjälp av egenskapen ExternalInterface.available. I så fall börjar kommunikationen upprättas. På grund av att säkerhetsundantag och andra fel kan uppstå när du försöker kommunicera med ett externt program är koden placerad i ett try-block (motsvarande catch-block har utelämnats i exemplet av utrymmesskäl). Sedan anropas metoden isContainerReady() som listas här: private function isContainerReady():Boolean { var result:Boolean = ExternalInterface.call("isReady"); return result; } Metoden isContainerReady() använder i sin tur metoden ExternalInterface.call() för att anropa JavaScript-funktionen isReady() på följande sätt: <script language="JavaScript"> <!-- // ------- 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; } ... //--> </script> Funktionen isReady() returnerar helt enkelt värdet för variabeln jsReady. Den variabeln är från början false. När webbsidans onload-händelse aktiveras ändras variabelns värde till true. Med andra ord svarar JavaScript false på anropet ExternalInterface.call("isReady") om ActionScript anropar funktionen isReady() innan sidan har lästs in. Det gör i sin tur att ActionScript-metoden isContainerReady() returnerar false. När sidan har lästs in returnerar JavaScript-funktionen isReady()true så att även ActionScript-metoden isContainerReady() returnerar true. I IMManager-konstruktorn händer en av två saker beroende på om behållaren är klar eller inte. Om isContainerReady() returnerar true anropar koden helt enkelt metoden setupCallbacks() som slutför processen att upprätta kommunikation med JavaScript. Om isContainerReady() å andra sidan returnerar false pausas i stället processen. Ett Timer-objekt skapas och instrueras att anropa metoden timerHandler() var hundrade millisekund på följande sätt: private function timerHandler(event:TimerEvent):void { // Check if the container is now ready. var isReady:Boolean = isContainerReady(); if (isReady) { // If the container has become ready, we don't need to check anymore, // so stop the timer. Timer(event.target).stop(); // Set up the ActionScript methods that will be available to be // called by the container. setupCallbacks(); } } Varje gång metoden timerHandler() anropas kontrollerar den resultatet av metoden isContainerReady(). När behållaren har initierats returnerar metoden true. Sedan stoppar koden Timer-objektet och anropar metoden setupCallbacks() som slutför processen att upprätta kommunikation med webbläsaren. Exponera ActionScript-metoder för JavaScriptFöregående exempel visade, att när koden avgör att webbläsaren är klar, anropas metoden setupCallbacks(). Denna metod förbereder ActionScript för att ta emot anrop från JavaScript, vilket visas nedan: private function setupCallbacks():void { // Register the SWF client functions with the container ExternalInterface.addCallback("newMessage", newMessage); ExternalInterface.addCallback("getStatus", getStatus); // Notify the container that the SWF is ready to be called. ExternalInterface.call("setSWFIsReady"); } Metoden setCallBacks() avslutar förberedelserna för kommunikation med behållaren genom att anropa ExternalInterface.addCallback() för att registrera de två metoder som ska vara tillgängliga för anrop från JavaScript. I den här koden är den första parametern – det namn som metoden är känd under i JavaScript ("newMessage" och "getStatus") – samma som metodens namn i ActionScript. (I det här fallet fanns det ingen fördel med att använda olika namn. Därför användes samma namn för enkelhetens skull.) Slutligen används metoden ExternalInterface.call() för att anropa JavaScript-funktionen setSWFIsReady(), som meddelar behållaren att ActionScript-funktionerna har registrerats. Kommunikation från ActionScript till webbläsarenProgrammet Introvert IM demonstrerar ett antal exempel på hur JavaScript-funktioner anropas i behållarsidan. I det enklaste fallet (ett exempel från metoden setupCallbacks()) anropas JavaScript-funktionen setSWFIsReady() utan att några parametrar skickas och utan att något returvärde tas emot: ExternalInterface.call("setSWFIsReady"); I ett annat exempel från metoden isContainerReady() anropar ActionScript funktionen isReady() och tar emot ett booleskt värde som svar: var result:Boolean = ExternalInterface.call("isReady"); Du kan också skicka parametrar till JavaScript-funktioner med det externa API:t. Ta till exempel metoden sendMessage() i klassen IMManager. Den anropas när användaren skickar ett nytt meddelande till sin ”konversationspartner”: public function sendMessage(message:String):void { ExternalInterface.call("newMessage", message); } Återigen är det ExternalInterface.call() som används för att anropa den angivna JavaScript-funktionen och meddela webbläsaren om det nya meddelandet. Dessutom skickas själva meddelandet som en extra parameter till ExternalInterface.call(). Därmed skickas det även som en parameter till JavaScript-funktionen newMessage(). Anropa ActionScript-kod från JavaScriptKommunikation ska ske åt två håll. Programmet Introvert IM är inget undantag. Det är inte bara Flash Players IM-klient som anropar JavaScript för att skicka meddelanden, HTML-formuläret anropar också JavaScript-koden för att skicka meddelanden till och få information från SWF-filen. När SWF-filen till exempel meddelar behållaren att den har upprättat kontakt och är klar att kommunicera, är det första webbläsaren gör att anropa metoden getStatus() i klassen IMManager för att hämta den ursprungliga statusen för användartillgänglighet från SWF-filens IM-klient. Detta görs i webbsidan med funktionen updateStatus() på följande sätt: <script language="JavaScript"> ... function updateStatus() { if (swfReady) { var currentStatus = getSWF("IntrovertIMApp").getStatus(); document.forms["imForm"].status.value = currentStatus; } } ... </script> Koden kontrollerar värdet för variabeln swfReady, som håller reda på om SWF-filen har meddelat webbläsaren att den har registrerat sina metoder med klassen ExternalInterface. Om SWF-filen är klar att ta emot kommunikation anropar nästa rad (var currentStatus = ...) metoden getStatus() i klassen IMManager. Tre saker händer på den här kodraden:
Obs! Om du följer koden märker du förmodligen att i källkoden för funktionen updateStatus() har kodraden som anropar funktionen getSWF() skrivits så här: var currentStatus = getSWF("${application}").getStatus(); Texten ${application} är en platshållare i HTML-sidmallen. När Adobe Flash Builder genererar den faktiska HTML-sidan för programmet, ersätts den här platshållaren med samma text som används som object-taggens id-attribut och embed-taggens name-attribut (IntrovertIMApp i exemplet). Det är värdet som förväntas av funktionen getSWF().
JavaScript-funktionen sendMessage() demonstrerar hur en parameter skickas till en ActionScript-funktion. (sendMessage() är den funktion som anropas när användaren trycker på knappen Send på HTML-sidan.) <script language="JavaScript"> ... function sendMessage(message) { if (swfReady) { ... getSWF("IntrovertIMApp").newMessage(message); } } ... </script> ActionScript-metoden newMessage() förväntar sig en parameter, så JavaScript-variabeln message skickas till ActionScript genom att användas som parameter i anropet till metoden newMessage() i JavaScript-koden. Identifiera webbläsartypenEftersom webbläsare öppnar innehåll på olika sätt är det viktigt att alltid använda JavaScript för att identifiera vilken webbläsare användaren har och att öppna filmen i enlighet med den webbläsarspecifika syntaxen, med objektet window eller document, vilket visas i JavaScript-funktionen getSWF() i det här exemplet: <script language="JavaScript"> ... function getSWF(movieName) { if (navigator.appName.indexOf("Microsoft") != -1) { return window[movieName]; } else { return document[movieName]; } } ... </script> Om skriptet inte kan identifiera användarens webbläsartyp kan användaren se oväntade effekter när SWF-filer spelas upp i en HTML-behållare. |
|