Przykład użycia zewnętrznego interfejsu API: komunikacja między kodem ActionScript a kodem JavaScript w przeglądarce WWWFlash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje Ta aplikacja przykładowa prezentuje odpowiednie techniki komunikacji między kodami ActionScript i JavaScript w przeglądarce sieci Web, w kontekście aplikacji Instant Messaging, która umożliwia użytkownikowi czatowanie z samym sobą (stąd nazwa aplikacji: Introvert IM). Komunikaty są wysyłane między HTML na stronie sieci Web, a interfejsem SWF za pomocą zewnętrznego interfejsu API. Technika przedstawiona na tym przykładzie obejmuje:
Aby pobrać pliki tej przykładowej aplikacji, należy przejść na stronę www.adobe.com/go/learn_programmingAS3samples_flash_pl. Pliki aplikacji Introvert IM są dostępne w folderze Samples/IntrovertIM_HTML. Aplikacja składa się z następujących plików:
Przygotowanie do komunikacji kodu ActionScript z przeglądarkąJednym z najczęstszych zastosowań zewnętrznego interfejsu API jest umożliwianie komunikacji aplikacji ActionScript z przeglądarką sieci Web. Dzięki zewnętrznemu interfejsowi API metody ActionScript mogą wywoływać kod zapisany w języku JavaScript i vice versa. Z powodu złożoności przeglądarek i sposobu, w jaki renderują wewnętrznie strony nie ma możliwości zagwarantowania, że dokument SWF zarejestruje swoje wywołania przed uruchomieniem pierwszego kodu JavaScript na stronie HTML. Z tego powodu przed wywołaniem funkcji w dokumencie SWF (z kodu JavaScript) dokument SWF zawsze powinien wywołać stronę HTML, aby powiadomić ją o tym, że dokument SWF jest gotowy do zaakceptowania połączeń. Na przykład: w serii kroków wykonanych przez klasę IMManager aplikacja Introvert IM określa, czy przeglądarka jest gotowa na komunikację, a następnie przygotowuje plik SWF dla komunikacji. Pierwszy krok — określenie, czy przeglądarka jest gotowa do komunikacji — odbywa się w konstruktorze IMManager: 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.");
}
}
Najpierw kod sprawdza, czy zewnętrzny interfejs API jest dostępny w bieżącym kontenerze — w tym celu korzysta z właściwości ExternalInterface.available. Jeśli jest dostępny, kod rozpoczyna konfigurowanie komunikacji. Podczas próby nawiązania połączenia z aplikacją zewnętrzną mogą wystąpić wyjątki zabezpieczeń i inne błędy, dlatego kod jest opakowany blokiem try (odpowiadające bloki catch zostały usunięte z przykładu w celu jego skrócenia). Następnie kod wywołuje metodę isContainerReady(), co przedstawiono poniżej: private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call("isReady");
return result;
}
Z kolei metoda isContainerReady() wykorzystuje metodę ExternalInterface.call() w celu wywołania funkcji isReady() JavaScript w następujący sposób: <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>
Funkcja isReady() po prostu zwraca wartość zmiennej jsReady. Ta zmienna na początkowo wartość false; po wywołaniu zdarzenia onload strony sieci Web wartość zmiennej zostaje zmieniona na true. Innymi słowy: gdy kod ActionScript wywoła funkcję isReady() przed załadowaniem strony, kod JavaScript zwraca wartość false do ExternalInterface.call("isReady"), a w konsekwencji metoda ActionScript isContainerReady() również zwraca wartość false. Po załadowaniu strony funkcja JavaScript isReady() zwraca wartość true, dlatego metoda ActionScript isContainerReady() również zwraca true. W konstruktorze IMManager dochodzi do jednej z dwóch operacji w zależności od gotowości konstruktora. Jeśli metoda isContainerReady() zwróci wartość true, kod po prostu wywołuje metodę setupCallbacks(), która kończy proces konfigurowania komunikacji z JavaScript. Z drugiej strony: jeśli isContainerReady() zwraca false, proces jest wstrzymywany. Następuje utworzenie obiektu Timer, który wywołuje metodę timerHandler() co 100 milisekund: 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();
}
}
Przy każdym wywołaniu metoda timerHandler() ponownie sprawdza wynik metody isContainerReady(). Po zainicjowaniu kontenera metoda zwraca wartość true. Następnie kod zatrzymuje obiekt Timer i wywołuje metodę setupCallbacks() w celu zakończenia konfigurowania komunikacji z przeglądarką. Aktywacja metod ActionScript w JavaScriptZgodnie z poprzednim przykładem — gdy kod ustali, że przeglądarka jest gotowa, następuje wywołane metody setupCallbacks(). Ta metoda przygotowuje kod ActionScript w celu odbierania wywołań z JavaScript: 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");
}
Metoda setCallBacks() kończy zadanie przygotowania komunikacji z kontenerem — w tym celu wywołuje metodę ExternalInterface.addCallback() w celu zarejestrowania dwóch metod, które będą mogły być wywoływane z JavaScript. W tym kodzie pierwszy parametr — nazwa, pod którą metoda jest znana w kodzie JavaScript ("newMessage" oraz "getStatus") — jest taki sam jak nazwa metody w ActionScript. (W tym przypadku używanie różnych nazw nie przyniosło żadnych korzyści, dlatego w celu uproszczenia ponownie użyto tej samej nazwy). Na koniec metoda ExternalInterface.call() wywołuje funkcję setSWFIsReady() JavaScript, która powiadamia kontener o tym, że funkcje ActionScript zostały zarejestrowane. Komunikacja kodu ActionScript z przeglądarkąAplikacja Introvert IM prezentuje gamę przykładowych wywołań funkcji JavaScript na stronie kontenera. W najprostszym przypadku (przykład z metody setupCallbacks()), funkcja setSWFIsReady() JavaScript zostaje wywołana bez użycia żadnych parametrów i bez odbierania wartości zwracanych: ExternalInterface.call("setSWFIsReady");
W innym przykładzie z metodą isContainerReady() kod ActionScript wywołuje funkcję isReady() i odbiera wartość logiczną w odpowiedzi: var result:Boolean = ExternalInterface.call("isReady");
Za pomocą zewnętrznego interfejsu API można również przekazywać parametry do kodu JavaScript. Na przykład: rozważmy metodę sendMessage() klasy IMManager, która zostaje wywołana, gdy użytkownik wysyła nowy komunikat do „partnera konwersacji”: public function sendMessage(message:String):void
{
ExternalInterface.call("newMessage", message);
}
Ponownie metoda ExternalInterface.call() służy do wywołania wyznaczonej funkcji JavaScript, powiadamiając przeglądarkę o nowym komunikacie. Ponadto komunikat jest przekazywany jako dodatkowy parametr do metody ExternalInterface.call() i w konsekwencji jest przekazywany do funkcji newMessage() JavaScript. Wywołanie kodu ActionScript z kodu JavaScriptKomunikacja powinna odbywać się w dwóch kierunkach, a aplikacja Introvert IM nie jest wyjątkiem od tej zasady. Klient IM Flash Player nie tylko wywołuje JavaScript w celu wysyłania komunikatów, ale ponadto HTML wywołuje kod JavaScript w celu wysyłania komunikatów do pliku SWF i żądania informacji z pliku SWF. Na przykład: gdy plik SWF powiadomi kontener o tym, że ukończył nawiązywanie połączenia i jest gotowy do komunikacji, wówczas przeglądarka najpierw wywołuje metodę getStatus() klasy IMManager w celu uzyskania wstępnego statusu dostępności użytkownika od klienta IM SWF. Odbywa się to na stronie sieci Web, w funkcji updateStatus(): <script language="JavaScript">
...
function updateStatus()
{
if (swfReady)
{
var currentStatus = getSWF("IntrovertIMApp").getStatus();
document.forms["imForm"].status.value = currentStatus;
}
}
...
</script>
Kod sprawdza wartość zmiennej swfReady, która śledzi, czy plik SWF powiadomił przeglądarkę o tym, że jej metody zostały zarejestrowane w klasie ExternalInterface. Jeśli plik SWF jest gotowy na odbieranie komunikacji, następna linia (var currentStatus = ...) wywołuje metodę getStatus() w klasie IMManager. Ta linia kodu wykonuje trzy operacje:
Uwaga: Osoby, które śledzą kod, zauważyły zapewne, że w kodzie źródłowym funkcji updateStatus() linia kodu, która wywołuje funkcję getSWF() jest zapisana w następujący sposób: var currentStatus = getSWF("${application}").getStatus(); Tekst ${application} jest obiektem zastępczym w szablonie strony HTML; gdy program Adobe Flash Builder wygeneruje rzeczywistą stronę HTML dla aplikacji, ten tekst zastępczy zostanie zastąpiony przez tekst używany jako atrybut id znacznika object oraz atrybut name znacznika embed (w tym przykładzie IntrovertIMApp). Jest to wartość oczekiwana przez funkcję getSWF().
Funkcja sendMessage() JavaScript prezentuje przekazanie parametru do funkcji ActionScript. (sendMessage() to funkcja wywoływana, gdy użytkownik naciśnie przycisk Wyślij na stronie HTML). <script language="JavaScript">
...
function sendMessage(message)
{
if (swfReady)
{
...
getSWF("IntrovertIMApp").newMessage(message);
}
}
...
</script>
Metoda newMessage() ActionScript oczekuje jednego parametru, dlatego zmienna message JavaScript zostaje przekazana do ActionScript, ponieważ została wykorzystana jako parametr w wywołaniu metody newMessage() w kodzie JavaScript. Wykrywanie typu przeglądarkiZ powodu różnic w sposobach, w jakie przeglądarki uzyskują dostęp do treści, bardzo ważne jest zawsze użycie kodu JavaScript w celu wykrywania używanej przeglądarki oraz w celu uzyskania dostępu do filmu zgodnie ze składnią właściwą dla przeglądarki — za pomocą obiektu okna lub dokumentu, co przedstawiono w funkcji getSWF() JavaScript w poniższym przykładzie: <script language="JavaScript">
...
function getSWF(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
return window[movieName];
}
else
{
return document[movieName];
}
}
...
</script>
Jeśli skrypt nie wykrywa typu przeglądarki użytkownika, działanie plików SWF w kontenerze HTML może być niezgodne z oczekiwaniami. |
|