Pergunta

Atualmente estou experimentando com o carregamento de arquivos SWF externos, tanto uma aplicação AS3 padrão, e um aplicativo AIR. Parece que o aplicativo AIR não age da mesma forma um SWF padrão correr pelo Flash Player faz.

De acordo com a , a propriedade applicationDomain de LoaderContext é utilizável em um aplicativo AIR também, mas ele só parece não estar funcionando.

Eu tenho o seguinte código:

package {
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;
    import flash.system.LoaderContext;

    public class Invoker extends Sprite
    {
        private var _ldr : Loader;

        public function Invoker()
        {
            _ldr = new Loader();
            _ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onChildOneComplete);

            var ldrC : LoaderContext = new LoaderContext(false,
                new ApplicationDomain(ApplicationDomain.currentDomain)
            );

            _ldr.load(new URLRequest("otherSwf.swf"), ldrC);
        }

        private function onChildOneComplete(e : Event) : void
        {
            var c1ad : ApplicationDomain = (e.target as LoaderInfo).applicationDomain;
            var inad : ApplicationDomain = ApplicationDomain.currentDomain;

            trace("Child One parentDomain : " + c1ad.parentDomain);
            trace("Invoker parentDomain   : " + inad.parentDomain);

            trace("Child One has Invoker  : " + c1ad.hasDefinition("Invoker"));
            trace("Invoker has Invoker    : " + inad.hasDefinition("Invoker"));
        }
    }
}

Compilar este código como um arquivo SWF e lançá-lo com o Flash Player faz esta saída, o que parece certo:

Child One parentDomain : [object ApplicationDomain]
Invoker parentDomain   : null
Child One has Invoker  : true
Invoker has Invoker    : true

Mas o mesmo código como um aplicativo AIR faz uma saída diferente:

Child One parentDomain : null
Invoker parentDomain   : null
Child One has Invoker  : false
Invoker has Invoker    : true

De acordo com a documentação, a primeira saída (usando um SWF com o Flash Player, e não um aplicativo AIR) é o caminho certo. Além disso, a brincar com esse trecho e mudando o domínio de aplicação para os outros possíveis configurações (como new ApplicationDomain(null), ou ApplicationDomain.currentDomain) faz exaclty o que diz a documentação com o SWF, mas não altera a saída do aplicativo AIR.

Qualquer indício porque AIR é simplesmente ignorando o domínio de aplicação passou para o contexto loader? Toda a documentação sobre este assunto particular?

Muito obrigado.

Foi útil?

Solução

Got-lo.

O problema foi causado por um comportamento diferente no sistema SecurityDomain dentro de um aplicativo AIR. Quando um arquivo SWF é carregado dentro de um aplicativo AIR, ele sempre dependem de uma sandbox diferente. Assim, o AIR cria uma nova SecurityDomain para este SWF.

Uma vez que um SecurityDomain é um grupo de uma ou mais ApplicationDomains, este comportamento forçou a criação de uma nova ApplicationDomain (dentro do novo SecurityDomain), ignorando o especificado (que pertencem ao SecurityDomain 'main').

Existe uma solução usando URLLoader. Quando carregado a partir de código de bytes (usando Loader.loadBytes), um SWF é carregado dentro da mesma SecurityDomain. É por isso que você tem que colocar o allowLoadBytesCodeExecution a verdade, uma vez que pode ser inseguro. Então carregar o SWF indiretamente, primeiro embora uma URLLoader, e depois com Loader.loadBytes, resolver esta questão.

Aqui está o trecho:

package {
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLLoader;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;
    import flash.system.LoaderContext;
    import flash.utils.ByteArray;

    public class Invoker extends Sprite
    {
        public function Invoker()
        {
            var uldr : URLLoader = new URLLoader();
            uldr.dataFormat = URLLoaderDataFormat.BINARY;
            uldr.addEventListener(Event.COMPLETE, onBytesComplete);

            uldr.load(new URLRequest("otherSwf.swf"));
        }

        private function onBytesComplete(e : Event) : void
        {
            var bytes : ByteArray = (e.target as URLLoader).data;

            var ldr : Loader = new Loader();
            ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onChildComplete);

            var ldrC : LoaderContext = new LoaderContext();

            // This property was for AIR 1.0.
            //ldrC.allowLoadBytesCodeExecution = true;

            // Since AIR 2.0, it's allowCodeImport.
            ldrC.allowCodeImport = true;

            ldr.loadBytes(bytes, ldrC);
        }

        private function onChildComplete(e : Event) : void
        {
            var c1ad : ApplicationDomain = (e.target as LoaderInfo).applicationDomain;
            var inad : ApplicationDomain = ApplicationDomain.currentDomain;

            trace("Child One parentDomain : " + c1ad.parentDomain);
            trace("Invoker parentDomain   : " + inad.parentDomain);

            trace("Child One has Invoker  : " + c1ad.hasDefinition("Invoker"));
            trace("Invoker has Invoker    : " + inad.hasDefinition("Invoker"));
        }
    }
}

Espero que isso ajude.

Outras dicas

que é uma boa, thanx:)

Apenas mais um detalhe: allowLoadBytesCodeExecution é agora uma propriedade legado, foi definido no AIR 1.0. De AIR 2.0 em uso allowCodeImport em seu lugar.

ciao, PG

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top