Comunicação com outras instâncias do Flash Player e AIR

Flash Player 9 e posterior, Adobe AIR 1.0 e posterior

A classe LocalConnection permite a comunicação entre aplicativos Adobe® AIR® e também com o conteúdo SWF executado no navegador. Você também pode usar a classe LocalConnection para se comunicar entre um aplicativo do AIR e o conteúdo SWF em execução no navegador. A classe LocalConnection permite construir aplicativos versáteis que podem compartilhar dados entre as instâncias do Flash Player e do AIR.

Sobre a classe Local

A classe LocalConnection permite desenvolver arquivos SWF que podem enviar instruções a outros arquivos SWF sem o uso do método fscommand() ou do JavaScript. Objetos LocalConnection podem se comunicar apenas entre arquivos SWF que estão em execução no mesmo computador cliente, mas podem ser executados em diferentes aplicativos. Por exemplo, um arquivo SWF em execução em um navegador e um arquivo SWF em execução em um projetor podem compartilhar informações, com o projetor mantendo informações locais e o arquivo SWF com base em navegador conectado remotamente. (Um projetor é um arquivo SWF salvo em um formato que pode ser executado como um aplicativo autônomo, isto é, o projetor não requer que o Flash Player seja instalado porque está incorporado dentro do executável.)

Objetos LocalConnection podem ser usados para comunicação entre SWFs usando diferentes versões do ActionScript:

  • Objetos LocalConnection do ActionScript 3.0 podem se comunicar com objetos LocalConnection criados no ActionScript 1.0 ou 2.0.

  • Objetos LocalConnection do ActionScript 1.0 ou 2.0 podem se comunicar com objetos LocalConnection criados no ActionScript 3.0.

O Flash Player manipula automaticamente essa comunicação entre objetos LocalConnection de diferentes versões.

O modo mais simples de usar um objeto LocalConnection é permitir a comunicação somente entre objetos LocalConnection localizados no mesmo domínio ou no mesmo aplicativo do AIR. Desse modo, não é necessário se preocupar com problemas de segurança. No entanto, se precisar permitir a comunicação entre domínios, há vários modos de implementar medidas de segurança. Para obter mais informações, consulte a discussão do parâmetro connectionName do método send() e das entradas allowDomain() e domain http://help.adobe.com/pt_BR/Flash/CS5/AS3LR/flash/net/LocalConnection.html na listagem da classe LocalConnection, na Referência do ActionScript® 3.0 para Adobe® Flash® Platform .

É possível usar objetos LocalConnection para enviar e receber dados dentro de um arquivo SWF único, mas a Adobe não recomenda esse procedimento. Em vez disso, use objetos compartilhados.

Há três maneiras de adicionar métodos de retorno de chamada aos objetos LocalConnection:

  • Criar subclasse da classe LocalConnection e adicionar métodos.

  • Definir a propriedade LocalConnection.client como um objeto que implementa os métodos.

  • Criar uma classe dinâmica que estende o LocalConnection e anexar métodos dinamicamente.

A primeira maneira de adicionar métodos de retorno de chamada é estender a classe LocalConnection. Você define os métodos dentro da classe personalizada em vez de adicioná-los dinamicamente à ocorrência de LocalConnection. Essa abordagem é demonstrada no código a seguir:

package 
{ 
    import flash.net.LocalConnection; 
    public class CustomLocalConnection extends LocalConnection 
    { 
        public function CustomLocalConnection(connectionName:String) 
        { 
            try 
            { 
                connect(connectionName); 
            } 
            catch (error:ArgumentError) 
            { 
                // server already created/connected 
            } 
        } 
        public function onMethod(timeString:String):void 
        { 
            trace("onMethod called at: " + timeString); 
        } 
    } 
}

É possível utilizar o código a seguir para criar uma nova instância da classe CustomLocalConnection:

var serverLC:CustomLocalConnection; 
serverLC = new CustomLocalConnection("serverName");

A segunda maneira de adicionar métodos de retorno de chamada é usar a propriedade LocalConnection.client . Isso envolve a criação de uma classe personalizada e a atribuição de uma nova ocorrência para a propriedade cliente , conforme mostrado no código a seguir:

var lc:LocalConnection = new LocalConnection(); 
lc.client = new CustomClient();

A propriedade LocalConnection.client indica os métodos de retorno de chamada do objeto que devem ser chamados. No código anterior, a propriedade client foi definida como uma nova ocorrência de uma classe personalizada, CustomClient. O valor padrão da propriedade client é a ocorrência LocalConnection atual. Você poderá usar a propriedade client , se tiver dois manipuladores de dados que tenham o mesmo conjunto de métodos, mas funcionam de modo diferente, por exemplo, em um aplicativo em que um botão em uma janela alterna a exibição em uma segunda janela.

Para criar a classe CustomClient, você pode usar o seguinte código:

package 
{ 
    public class CustomClient extends Object 
    { 
        public function onMethod(timeString:String):void 
        { 
            trace("onMethod called at: " + timeString); 
        } 
    } 
}

A terceira maneira de adicionar métodos de retorno de chamada criando uma classe dinâmica e anexando os métodos dinamicamente, é muito semelhante ao uso da classe LocalConnection em versões anteriores do ActionScript, conforme mostrado no código a seguir:

import flash.net.LocalConnection; 
dynamic class DynamicLocalConnection extends LocalConnection {}

Os métodos de retorno de chamada podem ser adicionados dinamicamente a essa classe usando o seguinte código:

var connection:DynamicLocalConnection = new DynamicLocalConnection(); 
connection.onMethod = this.onMethod; 
// Add your code here. 
public function onMethod(timeString:String):void 
{ 
    trace("onMethod called at: " + timeString); 
}

A maneira anterior de adicionar métodos de retorno de chamada não é recomendada porque o código não é muito portátil. Além disso, o uso desse método de criação de conexões locais pode criar problemas de desempenho, porque o acesso a propriedades dinâmicas é drasticamente mais lento do que o acesso a propriedades seladas.

Propriedade isPerUser

A propriedade isPerUser foi adicionada ao Flash Player (10.0.32) e AIR (1.5.2) para solucionar um conflito que ocorre quando mais de um usuário está conectado em um computador Mac. Em outros sistemas, a propriedade é ignorada, já que a conexão local sempre foi estendida aos usuários. A propriedade isPerUser deve ser definida para true no código novo. No entanto, o valor padrão é false para manter a compatibilidade com versões anteriores. O padrão pode ser mudado em versões futuras dos tempos de execução.

Envio de mensagens entre dois aplicativos

Use a classe LocalConnection para se comunicar entre aplicativos AIR diferentes e entre aplicativos AIR diferentes e aplicativos Adobe® Flash® Player (SWF) diferentes em execução em um navegador. Você também pode usar a classe LocalConnection para se comunicar entre um aplicativo do AIR e um aplicativo SWF em execução no navegador.

Por exemplo, você pode ter várias ocorrências do Flash Player em uma página da Web ou fazer com que uma ocorrência do Flash Player recupere dados de uma ocorrência do Flash Player em uma janela pop-up.

O código seguinte define um objeto LocalConnection que atua como um servidor e aceita chamadas LocalConnection recebidas de outros aplicativos:
package 
{ 
    import flash.net.LocalConnection; 
    import flash.display.Sprite; 
    public class ServerLC extends Sprite 
    { 
        public function ServerLC() 
        { 
            var lc:LocalConnection = new LocalConnection(); 
            lc.client = new CustomClient1(); 
            try 
            { 
                lc.connect("conn1"); 
            } 
            catch (error:Error) 
            { 
                trace("error:: already connected"); 
            } 
        } 
    } 
}

Esse código primeiro cria um objeto LocalConnection chamado lc e define a propriedade client como um objeto, clientObject . Quando outro aplicativo chama um método nessa instância LocalConnection, o tempo de execução pesquisa por esse método no objeto clientObject .

Caso possua uma conexão com o nome especificado, uma exceção de Argument Error é enviada, indicando que a tentativa de conexão falhou porque o objeto já está conectado.

Sempre que uma ocorrência do Flash Player se conecta a esse arquivo SWF e tenta chamar qualquer método para a conexão local especificada, a solicitação é enviada para a classe especificada pela propriedade client , definida como classe CustomClient1:

package 
{ 
    import flash.events.*; 
    import flash.system.fscommand; 
    import flash.utils.Timer; 
    public class CustomClient1 extends Object 
    { 
        public function doMessage(value:String = ""):void 
        { 
            trace(value); 
        } 
        public function doQuit():void 
        { 
            trace("quitting in 5 seconds"); 
            this.close(); 
            var quitTimer:Timer = new Timer(5000, 1); 
            quitTimer.addEventListener(TimerEvent.TIMER, closeHandler); 
        } 
        public function closeHandler(event:TimerEvent):void 
        { 
            fscommand("quit"); 
        } 
    } 
}

Para criar um servidor LocalConnection, chame o método LocalConnection.connect() e forneça um nome de conexão exclusivo. Se você já tiver uma conexão com o nome especificado, um erro ArgumentError será gerado, indicando que houve falha durante a tentativa de conexão, porque o objeto já está conectado.

O snippet seguinte demonstra como criar uma LocalConnection com o nome conn1 :
try 
{ 
    connection.connect("conn1"); 
} 
catch (error:ArgumentError) 
{ 
    trace("Error! Server already exists\n"); 
}
A conexão a um aplicativo primário a partir de um secundário requer primeiramente que você crie um objeto LocalConnection no objeto LocalConnection de envio e, em seguida, chame o método LocalConnection.send() com o nome da conexão e o nome do método a ser executado. Por exemplo, para enviar o método doQuit para o objeto LocalConnection que você criou anteriormente, use o seguinte código:
sendingConnection.send("conn1", "doQuit");

Esse código se conecta a um objeto LocalConnection existente com o nome de conexão conn1 e chama o método doMessage() no aplicativo remoto. Para enviar parâmetros para o aplicativo remoto, especifique argumentos adicionais após o nome do método, no método send() , como mostrado no seguinte snippet:

sendingConnection.send("conn1", "doMessage", "Hello world");

Conexão a conteúdo em domínios diferentes e a aplicativos AIR

Para permitir conexões apenas de domínios específicos, chame o método allowDomain() ou o allowInsecureDomain() da classe LocalConnection e passe uma lista de um ou mais domínios que são permitidos para acessar esse objeto LocalConnection, passando um ou mais nomes de domínios a serem permitidos.

Em versões anteriores do ActionScript, LocalConnection.allowDomain() e LocalConnection.allowInsecureDomain() eram métodos de retorno de chamada que precisavam ser implementados por desenvolvedores e retornar um valor booliano. No ActionScript 3.0, LocalConnection.allowDomain() e LocalConnection.allowInsecureDomain() são métodos internos que os desenvolvedores podem chamar exatamente como Security.allowDomain() e Security.allowInsecureDomain() , transmitindo um ou mais nomes de domínios a serem permitidos.

O Flash Player 8 introduziu restrições de segurança em arquivos SWF locais. Um arquivo SWF com acesso permitido à Internet não pode ter acesso também ao sistema de arquivos local. Se você especificar localhost , qualquer arquivo SWF local poderá acessar o arquivo SWF. Se o método LocalConnection.send() tentar se comunicar com um arquivo SWF a partir de uma caixa de proteção de segurança à qual o código de chamada não possui acesso, um evento securityError ( SecurityErrorEvent.SECURITY_ERROR ) será despachado. Para solucionar esse erro, você pode especificar o domínio do chamador no método LocalConnection.allowDomain() do receptor.

Há dois valores especiais que você pode passar para os métodos LocalConnection.allowDomain() e LocalConnection.allowInsecureDomain() : * e localhost . O valor asterisco (*) permite o acesso de todos os domínios. A string localhost permite chamadas para o aplicativo a partir do conteúdo instalado localmente, mas fora do diretório de recursos do aplicativo.

Se o método LocalConnection.send() tentar se comunicar com um aplicativo a partir de uma caixa de proteção de segurança à qual o código de chamada não tem acesso, um evento securityError ( SecurityErrorEvent.SECURITY_ERROR ) será despachado. Para solucionar esse erro, você pode especificar o domínio do chamador no método LocalConnection.allowDomain() do receptor.

Se você implementar a comunicação apenas entre o conteúdo no mesmo domínio, é possível especificar um parâmetro connectionName que não inicie com um caractere sublinhado ( _ ) e não especifique um nome de domínio (por exemplo, myDomain:connectionName ). Use a mesma string no comando LocalConnection.connect(connectionName) .

Se você implementar a comunicação entre o conteúdo em domínios diferentes, especifique um parâmetro connectionName que inicie com um sublinhado. Especificar o sublinhado torna o conteúdo com o objeto LocalConnection de recebimento mais durável entre domínios. Estes são os dois casos possíveis:

  • Se a string para connectionName não começar com um sublinhado, o tempo de execução adicionará um prefixo com o superdomínio e um caractere de dois pontos (por exemplo, myDomain:connectionName ). Embora isso garanta que a sua conexão não entre em conflito com as conexões de nome idêntico em outros domínios, qualquer objeto LocalConnection de envio deve especificar esse superdomínio (por exemplo, myDomain:connectionName ). Se você mover o arquivo HTML ou SWF com o objeto LocalConnection de recebimento para outro domínio, o tempo de execução alterará o prefixo de para refletir o novo superdomínio (por exemplo, anotherDomain:connectionName ). Todos os objetos LocalConnection de envio precisam ser manualmente editados de modo a apontar para o novo superdomínio.

  • Se a string para connectionName começar com um sublinhado (por exemplo, _connectionName ), o tempo de execução não adicionará um prefixo a essa string. Isso significa que os objetos LocalConnection de recebimento e envio usam strings idênticas para connectionName . Se o objeto de recebimento usar LocalConnection.allowDomain() para especificar que serão aceitas conexões de qualquer domínio, você poderá mover o arquivo HTML OU SWF com o objeto LocalConnection de recebimento para outro domínio sem alterar nenhum objeto LocalConnection de envio.

    Uma desvantagem de usar nomes sublinhados em connectionName é o potencial para colisões, como quando dois aplicativos tentam, ambos, se conectar, usando o mesmo connectionName . Uma outra desvantagem está relacionada à segurança. Nomes de conexões que utilizam sintaxe sublinhada não identificam o domínio do aplicativo ouvinte. Por esses motivos, nomes qualificados de domínio são preferíveis.

Adobe AIR

Para comunicar-se com conteúdo executado na área de segurança de aplicativo do AIR (conteúdo instalado por aplicativo do AIR), você deve utilizar um prefixo no nome da conexão com um superdomínio que identifica o aplicativo do AIR. A string de superdomínio inicia com app# seguido pelo ID de aplicativo ID e um ponto (.) , seguido pelo ID do publicador (se definido). Por exemplo, o superdomínio apropriado a ser utilizado com o parâmetro connectionName para um aplicativo com o ID de aplicativo, com.example.air.MyApp e ID de publicador é: "app#com.example.air.MyApp" . Portanto, se o nome de conexão base for “appConnection,” a string inteira a ser utilizada no parâmetro connectionName é: "app#com.example.air.MyApp:appConnection" . Se o aplicativo possuir o ID de publicador, o ID também deve ser incluído na string do superdomínio: "app#com.example.air.MyApp.B146A943FBD637B68C334022D304CEA226D129B4.1" .

Quando você permite que outro aplicativo do AIR se comunique com seu aplicativo pela conexão local, é preciso chamar o allowDomain() do objeto LocalConnection, passando o nome de domínio da conexão local. Para um aplicativo do AIR, esse nome de domínio é formado a partir das IDs do aplicativo e do editor, da mesma forma que na string de conexão. Por exemplo, se o aplicativo do AIR de envio tem uma ID de aplicativo de com.example.air.FriendlyApp e uma ID de editor de 214649436BD677B62C33D02233043EA236D13934.1 , a string de domínio a usar para permitir que esse aplicativo se conecte é: app#com.example.air.FriendlyApp.214649436BD677B62C33D02233043EA236D13934.1 . (Desde a versão 1.5.3 do AIR, nem todos os aplicativos AIR têm ID de publicador.)