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. |
![]() |