Exemplo de API externa: comunicaçaõ entre ActionScript e JavaScript em um navegador da WebFlash Player 9 e posterior, Adobe AIR 1.0 e posterior Este aplicativo de amostra demonstra técnicas adequadas de comunicação entre o ActionScript e o JavaScript em um navegador da Web, no âmbito de um aplicativo de mensagem instantânea que permite que uma pessoa converse consigo mesma (daí o nome do aplicativo: Introvert IM). As mensagens são enviadas entre um formulário HTML na página da Web e uma interface SWF usando a API externa. As técnicas demonstradas neste exemplo incluem as seguintes:
Para obter os arquivos do aplicativo para este exemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_br. Os arquivos do aplicativo Introvert IM estão localizados na pasta Amostras/IntrovertIM_HTML. O aplicativo consiste nos seguintes arquivos:
Preparação da comunicação entre o ActionScript e o navegadorA API externa normalmente é usada para permitir a comunicação dos aplicativos do ActionScript com um navegador da Web. Usando a API externa, os métodos do ActionScript podem chamar o código gravado em JavaScript e vice-versa. Devido à complexidade dos navegadores e ao modo de renderização interna das páginas, não é possível garantir que um documento SWF registrará seus retornos de chamada antes da execução do primeiro JavaScript na página HTML. Por esse motivo, antes de chamar funções no documento SWF a partir do JavaScript, o documento SWF sempre deve chamar a página HTML para notificar se o documento SWF está pronto para aceitar conexões. Por exemplo, por meio de uma série de etapas realizadas pela classe IMManager, o Introvert IM determina se o navegador está pronto para comunicação e prepara o arquivo SWF para comunicação. A primeira etapa, determinar quando o navegador está pronto para comunicação, acontece no construtor IMManager do seguinte modo: 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.");
}
}
Primeiro, o código verifica se a API externa está realmente disponível no contêiner atual usando a propriedade ExternalInterface.available. Se estiver, o processo de configuração da comunicação é iniciado. Como exceções de segurança e outros erros podem ocorrer ao tentar se comunicar com um aplicativo externo, o código fica entre um bloco try (os blocos catch correspondentes foram omitidos da listagem para facilitar). O código a seguir chama o método isContainerReady(), listado aqui: private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call("isReady");
return result;
}
O método isContainerReady(), por sua vez, usa o método ExternalInterface.call() para chamar a função isReady() do JavaScript do seguinte modo: <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>
A função isReady() simplesmente retorna o valor da variável jsReady. Essa variável é inicialmente false; assim que o evento onload da página da Web é acionado, o valor da variável muda para true. Em outras palavras, se o ActionScript chamar a função isReady() antes que a página seja carregada, o JavaScript retornará false para ExternalInterface.call("isReady") e, conseqüentemente, o método isContainerReady() do ActionScript retornará false. Assim que a página for carregada, a função isReady() do JavaScript retornará true, de modo que o método isContainerReady() do ActionScript também retornará true. De volta ao construtor IMManager, uma de duas coisas acontecem dependendo da disponibilidade do contêiner. Se isContainerReady() retornar true, o código simplesmente chamará o método setupCallbacks(), que concluirá o processo de configuração da comunicação com o JavaScript. Por outro lado, se isContainerReady() retornar false, o processo será basicamente suspenso. Um objeto Timer é criado e suspenso para chamar o método timerHandler() a cada 100 milissegundos do seguinte modo: 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();
}
}
Sempre que é chamado, o método timerHandler() verifica mais uma vez o resultado do método isContainerReady(). Assim que o contêiner é inicializado, esse método retorna true. Em seguida, o código pára o objeto Timer e chama o método setupCallbacks() para finalizar o processo de configuração da comunicação com o navegador. Exposição dos métodos do ActionScript ao JavaScriptConforme mostrou o exemplo anterior, assim que o código determina que o navegador está pronto, o método setupCallbacks() é chamado. Esse método prepara o ActionScript para receber chamadas do JavaScript, conforme mostrado a seguir: 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");
}
O método setCallBacks() termina a tarefa de preparação de comunicação com o contêiner chamando ExternalInterface.addCallback() para registrar os dois métodos que estarão disponíveis para serem chamados a partir do JavaScript. Neste código, o primeiro parâmetro - o nome pelo qual o método é conhecido pelo JavaScript ("newMessage" e "getStatus") - é igual ao nome do método no ActionScript. Neste caso, não seria útil usar nomes diferentes, de modo que o mesmo nome foi reutilizado para simplificar. Finalmente, o método ExternalInterface.call() é usado para chamar a função setSWFIsReady() do JavaScript, que avisa ao contêiner que as funções do ActionScript foram registradas. Comunicação do ActionScript com o navegadorO aplicativo Introvert IM demonstra diversos exemplos de chamada das funções do JavaScript na página do contêiner. No caso mais simples (um exemplo do método setupCallbacks()), a função setSWFIsReady() do JavaScript é chamada sem transmitir nenhum parâmetro nem receber um valor de retorno: ExternalInterface.call("setSWFIsReady");
Em outro exemplo do método isContainerReady(), o ActionScript chama a função isReady() e recebe um valor booleano em resposta: var result:Boolean = ExternalInterface.call("isReady");
Também é possível transmitir parâmetros para as funções do JavaScript usando a API externa. Por exemplo, considere o método sendMessage() da classe IMManager, que é chamado quando o usuário está enviando uma nova mensagem para seu "parceiro de conversa": public function sendMessage(message:String):void
{
ExternalInterface.call("newMessage", message);
}
Novamente, ExternalInterface.call() é usado para chamar a função designada do JavaScript, notificando o navegador sobre a nova mensagem. Além disso, a mensagem propriamente dita é transmitida como um parâmetro adicional para ExternalInterface.call() e, conseqüentemente, transmitida como parâmetro para a função newMessage() do JavaScript. Chamada do código do ActionScript a partir do JavaScriptA comunicação é uma rua de mão dupla e o aplicativo Introvert IM não foge à regra. O cliente IM do Flash Player não só chama o JavaScript para enviar mensagens, mas o formulário HTML chama o código do JavaScript para enviar mensagens e solicitar informações do arquivo SWF também. Por exemplo, quando o arquivo SWF avisa o contêiner que terminou de estabelecer o contato e está pronto para se comunicar, a primeira coisa que o navegador faz é chamar o método getStatus() da classe IMManager para recuperar o status de disponibilidade inicial do usuário a partir do cliente IM do SWF. Isso é feito na página da Web, na função updateStatus(), do seguinte modo: <script language="JavaScript">
...
function updateStatus()
{
if (swfReady)
{
var currentStatus = getSWF("IntrovertIMApp").getStatus();
document.forms["imForm"].status.value = currentStatus;
}
}
...
</script>
O código verifica o valor da variável swfReady, que controla se o arquivo SWF notificou o navegador sobre o registro dos métodos com a classe ExternalInterface. Se o arquivo SWF estiver pronto para receber comunicação, a próxima linha (var currentStatus = ...) realmente chamará o método getStatus() na classe IMManager. Três coisas acontecem nesta linha de código:
Nota: Se estiver seguindo o código, você provavelmente percebeu que, no código-fonte da função updateStatus(), a linha de código que chama a função getSWF() é realmente escrita do seguinte modo: var currentStatus = getSWF("${application}").getStatus(). O texto ${application} é um alocador de espaço contido no modelo da página HTML. Quando o Adobe Flash Builder gera a página HTML real para o aplicativo, esse alocador é substituído pelo mesmo texto usado como o atributo id da tag object e o atributo name da tag embed (que corresponde a IntrovertIMApp no exemplo). Este é o valor esperado pela função getSWF().
A função sendMessage() do JavaScript demonstra a transmissão de um parâmetro como uma função do ActionScript. (sendMessage() é afunção que foi chamada quando o usuário pressionou o botão Enviar na página HTML. <script language="JavaScript">
...
function sendMessage(message)
{
if (swfReady)
{
...
getSWF("IntrovertIMApp").newMessage(message);
}
}
...
</script>
O método newMessage() do ActionScript espera um parâmetro, de modo que a variável message do JavaScript é transmitida para o ActionScript como um parâmetro na chamada do método newMessage() no código do JavaScript. Detecção do tipo de navegadorDevido às diferenças de acesso ao conteúdo dos navegadores, é importante sempre usar o JavaScript para detectar qual navegados está sendo executado pelo usuário e para acessar o filme de acordo com a sintaxe específica do navegador, usando o objeto de janela ou documento, como mostra a função getSWF() do JavaScript neste exemplo: <script language="JavaScript">
...
function getSWF(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
return window[movieName];
}
else
{
return document[movieName];
}
}
...
</script>
Se o seu script não detectar o tipo de navegador do usuário, o usuário poderá observar um comportamento inesperado ao reproduzir arquivos SWF em um contêiner HTML. |
|