Esempio di API esterna: comunicazione tra ActionScript e JavaScript in un browser WebFlash Player 9 e versioni successive, Adobe AIR 1.0 e versioni successive Questo esempio di applicazione mostra le tecniche appropriate per abilitare la comunicazione tra ActionScript e JavaScript in un browser Web, nel contesto di un'applicazione di Instant Messaging che consente a un utente di inviare messaggi chat a se stesso (da cui il nome dell'applicazione: Introvert IM). I messaggi vengono scambiati tra un form HTML nella pagina Web e un'interfaccia SWF che utilizza l'API esterna. La tecnica dimostrata nell'esempio consente di:
Per ottenere i file dell'applicazione per questo esempio, visitate la pagina www.adobe.com/go/learn_programmingAS3samples_flash_it. I file dell'applicazione Introvert IM sono disponibili nella cartella Samples/IntrovertIM_HTML. L'applicazione è composta dai seguenti file:
Preparazione di una comunicazione ActionScript-browserL'API esterna viene molto spesso utilizzata per consentire alle applicazioni ActionScript di comunicare con un browser Web. Grazie all'API esterna, i metodi ActionScript possono chiamare il codice scritto in JavaScript e viceversa. In virtù della complessità dei browser e del modo in cui effettuano il rendering interno delle pagine, non è possibile garantire che un documento SWF registri le proprie funzioni di callback prima che venga eseguito il primo codice JavaScript della pagina HTML. Per tale motivo, prima di chiamare le funzioni nel documento SWF da JavaScript, il documento SWF deve sempre chiamare la pagina HTML per notificarle che il documento SWF è pronto per accettare le connessioni. Attraverso una serie di operazioni eseguite, ad esempio, dalla classe IMManager, l'applicazione Introvert IM determina se il browser è pronto per la comunicazione e prepara il documento SWF di conseguenza. La prima operazione, ovvero determinare quando il browser è pronto per la comunicazione, si svolge nella funzione di costruzione IMManager, come indicato di seguito: 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.");
}
}
Innanzitutto, il codice verifica se l'API esterna è almeno disponibile nel contenitore corrente utilizzando la proprietà ExternalInterface.available. In caso affermativo, inizia il processo di impostazione della comunicazione. Poiché quando si tenta la comunicazione con un'applicazione esterna possono verificarsi delle eccezioni di sicurezza e altri errori, il codice viene racchiuso in un blocco try (i blocchi catch corrispondenti sono stati omessi dall'elenco per ragioni di spazio). Il codice successivo chiama il metodo isContainerReady(), rappresentato qui: private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call("isReady");
return result;
}
Il metodo isContainerReady() utilizza a propria volta il metodo ExternalInterface.call() per chiamare la funzione JavaScript isReady(), come indicato di seguito: <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>
La funzione isReady() restituisce semplicemente il valore della variabile jsReady. Tale variabile inizialmente è false; quando l'evento onload della pagina Web è stato attivato, il valore della variabile diventa true. In altre parole, se ActionScript chiama la funzione isReady() prima che la pagina sia stata caricata, JavaScript restituisce false a ExternalInterface.call("isReady"), e di conseguenza il metodo ActionScript isContainerReady() restituisce false. Una volta caricata la pagina, la funzione JavaScript isReady() restituisce true, pertanto anche il metodo ActionScript isContainerReady() restituisce true. Tornando alla funzione di costruzione IMManager, a seconda della prontezza del contenitore può verificarsi una delle due condizioni seguenti. Se isContainerReady() restituisce true, il codice chiama semplicemente il metodo setupCallbacks(), che completa il processo di impostazione della comunicazione con JavaScript. Se invece isContainerReady() restituisce false, il processo viene essenzialmente sospeso. Viene creato un oggetto Timer a cui viene ordinato di chiamare il metodo timerHandler() ogni 100 millisecondi, come indicato di seguito: 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();
}
}
Ogni volta che il metodo timerHandler() viene chiamato, verifica ancora una volta il risultato del metodo isContainerReady(). Una volta inizializzato il contenitore, tale metodo restituisce il valore true. A quel punto, il codice arresta il timer e chiama il metodo setupCallbacks() per completare il processo di impostazione della comunicazione con il browser. Esposizione dei metodi ActionScript a JavaScriptCome illustrato nell'esempio precedente, quando il codice determina che il browser è pronto, viene chiamato il metodo setupCallbacks(). Questo metodo prepara ActionScript alla ricezione delle chiamate da JavaScript, come illustrato di seguito: 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");
}
Il metodo setCallBacks() conclude la preparazione alla comunicazione chiamando ExternalInterface.addCallback() per registrare i due metodi che saranno disponibili per le chiamate da JavaScript. In questo codice, il primo parametro (il nome con cui il metodo è conosciuto da JavaScript, ovvero "newMessage" e "getStatus") è uguale al nome del metodo in ActionScript (nel caso dell'esempio, poiché sarebbe stato ininfluente indicare nomi diversi, per semplicità è stato utilizzato lo stesso nome). Infine, viene utilizzato il metodo ExternalInterface.call() per chiamare la funzione JavaScript setSWFIsReady(), che notifica al contenitore che le funzioni ActionScript sono state registrate. Comunicazione da ActionScript al browserL'applicazione Introvert IM dimostra una serie di esempi di chiamate a funzioni JavaScript nella pagina contenitore. Nel caso più semplice (un esempio tratto dal metodo setupCallbacks()), la funzione JavaScript setSWFIsReady() viene chiamata senza passare alcun parametro o ricevere alcun valore: ExternalInterface.call("setSWFIsReady");
In un altro esempio tratto dal metodo isContainerReady(), ActionScript chiama la funzione isReady() e riceve come risposta un valore booleano: var result:Boolean = ExternalInterface.call("isReady");
Potete passare parametri alle funzioni JavaScript anche utilizzando l'API esterna. Considerate, ad esempio, il metodo sendMessage() della classe IMManager, che viene chiamato quando l'utente sta inviando un nuovo messaggio al proprio interlocutore: public function sendMessage(message:String):void
{
ExternalInterface.call("newMessage", message);
}
Anche in questo caso, si utilizza ExternalInterface.call() per chiamare la funzione JavaScript designata, notificando al browser il nuovo messaggio. Inoltre, il messaggio stesso viene passato come parametro aggiuntivo a ExternalInterface.call(), e di conseguenza viene passato come parametro alla funzione JavaScript newMessage(). Chiamate al codice ActionScript da JavaScriptUna comunicazione dovrebbe essere sempre bidirezionale, e l'applicazione Introvert IM non fa eccezione. Non solo il client IM di Flash Player chiama JavaScript per inviare i messaggi, ma il form HTML chiama il codice JavaScript anche per inviare messaggi e chiedere informazioni al file SWF. Quando, ad esempio, il file SWF notifica al contenitore che il contatto è stato stabilito ed è pronto per comunicare, come prima cosa il browser chiama il metodo getStatus() della classe IMManager per recuperare lo stato di disponibilità iniziale dell'utente dal client IM SWF. Questo avviene in una pagina Web, nella funzione updateStatus(), nel modo indicato di seguito: <script language="JavaScript">
...
function updateStatus()
{
if (swfReady)
{
var currentStatus = getSWF("IntrovertIMApp").getStatus();
document.forms["imForm"].status.value = currentStatus;
}
}
...
</script>
Il codice verifica il valore della variabile swfReady, che rileva se il file SWF ha notificato il browser che ne ha registrato i metodi con la classe ExternalInterface. Se il file SWF è pronto per ricevere la comunicazione, la riga successiva (var currentStatus = ...) chiama di fatto il metodo getStatus() nella classe IMManager. In questa riga di codice vengono eseguite tre operazioni:
Nota: se state seguendo il codice, avrete notato che nel codice sorgente della funzione updateStatus(), la riga di codice che chiama la funzione getSWF() è scritta nel seguente modo: var currentStatus = getSWF("${application}").getStatus(); il testo ${application} è un segnaposto all'interno della pagina template HTML; quando Adobe Flash Builder genera la pagina HTML effettiva per l'applicazione, questo segnaposto viene sostituito dallo stesso testo utilizzato come attributo id del tag object e dall'attributo nome del tag embed (nell'esempio IntrovertIMApp). Questo è il valore previsto dalla funzione getSWF().
La funzione JavaScript sendMessage() dimostra il passaggio di un parametro a una funzione ActionScript (sendMessage() è la funzione che viene chiamata quando l'utente preme il pulsante Invia presente nella pagina HTML). <script language="JavaScript">
...
function sendMessage(message)
{
if (swfReady)
{
...
getSWF("IntrovertIMApp").newMessage(message);
}
}
...
</script>
Il metodo ActionScript newMessage() prevede un solo parametro, pertanto la variabile JavaScript message viene passata ad ActionScript utilizzandola come parametro nella chiamata al metodo newMessage() nel codice JavaScript. Rilevamento del tipo di browserA causa delle differenze nel modo in cui i browser accedono ai contenuti, è importante utilizzare sempre JavaScript per rilevare quale browser è utilizzato dall'utente e per accedere al filmato in base alla sintassi specifica del browser, utilizzando l'oggetto window o document, come mostrato nella funzione JavaScript getSWF() dell'esempio seguente: <script language="JavaScript">
...
function getSWF(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
return window[movieName];
}
else
{
return document[movieName];
}
}
...
</script>
Se lo script non rileva il tipo di browser dell'utente, quest'ultimo potrebbe sperimentare un comportamento imprevisto durante la riproduzione dei file SWF in un contenitore HTML. |
|