Przykład użycia zewnętrznego interfejsu API: komunikacja między kodem ActionScript a kodem JavaScript w przeglądarce WWW

Flash 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:

  • Poprawne zainicjowanie komunikacji poprzez sprawdzenie, czy przeglądarka jest gotowa do komunikacji, następnie skonfigurowanie komunikacji

  • Sprawdzenie, czy kontener obsługuje zewnętrzny interfejs API

  • Wywołanie funkcji JavaScript z kodu ActionScript, przekazanie parametrów i odebranie wartości w odpowiedzi

  • Udostępnienie ActionScript metod do wywołania przez kod JavaScript, a następnie wykonanie wywołań

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:

File

Opis

IntrovertIMApp.fla

lub

IntrovertIMApp.mxml

Główny plik aplikacji w formacie Flash (FLA) lub Flex (MXML).

com/example/programmingas3/introvertIM/IMManager.as

Klasa, która nawiązuje i utrzymuje połączenie między ActionScript a kontenerem.

com/example/programmingas3/introvertIM/IMMessageEvent.as

Niestandardowe zdarzenie wywoływane przez klasę IMManager po odebraniu komunikatu z kontenera.

com/example/programmingas3/introvertIM/IMStatus.as

Uporządkowanie, którego wartości reprezentują różne wartości statusu „dostępność”, jakie mogą być wybierane w aplikacji.

html-flash/IntrovertIMApp.html

lub

html-template/index.template.html

Strona HTML dla aplikacji Flash (html-flash/IntrovertIMApp.html) lub szablonu, który służy do tworzenia strony HTML kontenera dla aplikacji dla Adobe Flex (html-template/index.template.html). Ten plik zawiera wszystkie funkcje JavaScript, które tworzą część kontenera aplikacji.

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 JavaScript

Zgodnie 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 JavaScript

Komunikacja 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:

  • Wywołuje funkcję getSWF() JavaScript, zwracając odwołanie do obiektu JavaScript reprezentującego plik SWF. Parametr przekazany do getSWF() określa obiekt przeglądarki, który jest zwracany w przypadku, gdy strona HTML zawiera więcej niż jeden plik SWF. Wartość przekazana do tego parametru musi być zgodna z atrybutem id znacznika object i atrybutem name znacznika embed , dzięki któremu możliwe jest dołączenie pliku SWF.

  • Odwołanie do pliku SWF powoduje wywołanie metody getStatus() w taki sposób, jakby była to metoda obiektu SWF. W tym przypadku używana jest nazwa funkcji „ getStatus ”, ponieważ jest to nazwa, pod jaką funkcja ActionScript została zarejestrowana za pomocą metody ExternalInterface.addCallback() .

  • Metoda getStatus() ActionScript zwraca wartość, a ta wartość zostaje przypisana do zmiennej currentStatus , która następnie zostaje przypisana jako treść (właściwość value ) pola tekstowego status .

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ądarki

Z 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.