A 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, consequentemente, 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 para o objeto Timer e chama o método
setupCallbacks()
para finalizar o processo de configuração da comunicação com o navegador.