About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Feb

    25

    每次 Adobe AIR SDK 升级之后,会发布一些新版 SDK 的功能介绍,但这些功能介绍总是转着转着、传着传着就被曲解了,以下每一种情况都是本人亲自测试结果(技术是严谨的,容不得“好像”、“可能”等模棱两可的词,可以就是可以,不可以就是不可以,如果觉的不确定,那就必须亲自测试判定是否可以;如果有多种条件,那么还要确定在哪些条件下可以哪些条件下不可以。如果凭借着自己的想象给新功能介绍添油加醋、胡乱编造,那样就会误人子弟),本人使用的测试环境为最新的 AIR SDK 4.0 官方正式版本。

    如苹果公司 APP Stroe 平台限制 Adobe AIR for  iOS 打包的应用要求是单个应用域,不允许主 SWF 文件运行外部带有代码的子 SWF 文件,这里面有非常重要的信息容易被人曲解,更有甚者是将它添油加醋(以下测试结果中如果没有特别说明,主文件就是指主 SWF 文件,子文件就是指被加载的子 SWF 文件)比如:

    1、有人会按着自己的猜测而未经测试,理解成  iOS 系统不允许加载外部带有代码的子文件,这是错误的。因为这是 APP Stroe 平台的限制,不是 iOS 限制,本身  Adobe AIR for  iOS 打包的程序可以用非 AOT 模式(解析模式)是允许加载外部子文件的,甚至是服务器上的远程子文件,并且都可以带有 AS 代码,并且正常执行它们。而提交到  APP Stroe 平台是必须使用 AOT 模式,不允许外部带有 AS 的子文件。换种说法,只要是 AOT 编译模式生成了 APP,就不允许主文件加载外部带有 AS 代码的子文件,而跟最终是否发布到 APP Stroe 平台没有关系(APP Stroe 平台只是限制了必须使用 AOT 模式编译的APP)。

    2、以二进制方式将带有 AS 代码的子文件使用 [Embed] 元标签直接嵌入到主文件中,可以像单个主文件那样直接编译成 APP,并使用 Loader 加载库中的二进制子文件,这也是错误的。以二进制方式将子文件嵌入到主文件的库中后,仍然是只能在解析模式下加载并执行代码的。 AOT 模式是不允许的,既便是 Loader 方法加载到主文件的同一个应用域,也是不允许的。因为 AOT 编译模式不会编译库中带有代码的二进制元件,库中的元件编译后在格式上仍然是一个带有可执行 AS 代码的、独立的子文件,使用 Loader 时它仍然算是运行时动态加载带有 AS 代码的子文件(这也是下面要说的第三种情况中,子文件不允许使用 Flex 框架的子文件的原因,因为 Flex 框架的部份组件中含有嵌入的二进制库元件的原因)。

    3、重头大戏:新版 AIR SDK 在 AOT 编译模式下会将子文件中的代码提取出来合并到主文件中去,这里需要分多种情况:只有当条件满足时才是对的,否则就是错的(事实上这种说法本身存在一些问题,因为当所有条件满足时,子文件中的代码只是被打包进 *.ipa 文件了,并不是真的合并到主文件中去了,包括主文件的代码也会被提取,打包到 *.ipa 文件中去;主文件和子文件被剥离了代码后只剩下了资源 SWF 文件,也被打包到 *.ipa 文件中去了。但一般通俗口头上来,也可以认为是子文件中的代码被合并主文件中去了,只是一种更简单的说法罢了)。

    因为子文件中的代码是否会被合并到 *.ipa 文件中去,并不完全由是否使用最新版本的 AIR SDK 决定的(虽然官方是从 3.7 版本开始加入这个功能的,但现在本人用的是4.0),除了需要使用最新版本的 AIR SDK 外,还要求主文件的内部版本号必须大于等于 20(本人测试时使用的是23,关于 SWF 文件内部版本号可参考《Flash 播放器版本与 SWF 内部版本号(含评论)》),以及带有代码的子文件不能以二进制文件的方式被嵌入到主文件的库或其它文件的库中作为元件。否则就算是使用最新的测试版本 AIR 13.0( AIR 为了保持和 Flash 相同的版本号,跳过了5、6、7、8、9……等版本号,下一个版本将直接从 AIR4.0 升到 AIR 13.0),也不会将子文件中的代码合并到主文件中去。

    子文件不允许使用 Flex 框架开发出来的子文件,因为 Flex 框架中的一些组件中含有嵌入的二进制库元件。官方在发行说明中声称加载 Flex 二级 SWF 会导致应用程序崩溃,同时也不允许加载大型的子文件(如包含 Video 这样资源较多的文件),也会导致应用程序崩溃。

    另外子文件被剥离代码后的资源文件是否被打包到 *.ipa 文件中,由一个外部的文本文件以及应用程序描述符文件决定,即资源文件可以不被打包到 *.ipa 文件中,可以远程托管(便于远程更新,但每次更新资源是需要经过编译的,直接替换带有 AS 代码的子文件是不行的),它的完程过程在 Adobe  官方提供了一个完程的教程(《External hosting of secondary SWFs for AIR apps on iOS》。

    备注:还有其它一些乱七八糟的错误说法,大多可能来自一些可能刚加入AIR for iOS 开发者的一些错误的理解,如果觉的不确定,不要自己凭空猜测,请拿实例做测试,附上两个测试用的文件(测试的时候请特别注意主文件的内部版本号,否则就会和很多开发者一样得到一个错误的测试结果)。

    测试文件下载:第一个 Loader 样例:IOS_Test.rar    第二个 Embed 样例:iOS_Embed_Test.rar

    官方帮助链接http://help.adobe.com/zh_CN/air/build/WSfffb011ac560372f7e64a7f12cd2dd1867-8000.html

    Jul

    15

     如果需要控制嵌入的整个 SWF 资源文件方法如下:

    //方法一:[Embed(source="test.swf" , mimeType="application/octet-stream")]
    package {
     import flash.display.Loader;
     import flash.display.LoaderInfo;
     import flash.display.MovieClip;
     import flash.events.Event;
     public class Test extends MovieClip {
      [Embed(source="test.swf" , mimeType="application/octet-stream")]
      private var SWFBytes:Class;
      private var _loader:Loader;
      public function Test() {
       _loader = new Loader();
       _loader.loadBytes(new SWFBytes());
       _loader.contentLoaderInfo.addEventListener(Event.INIT,_listener);
       function _listener(e:Event):void {
        var _mc:MovieClip = _loader.content as MovieClip;
        _mc.gotoAndStop(2);
        addChild(_mc);
       }   
      }  
     } 
    }


    //方法二: [Embed(source="test.swf")]
    package {
     import flash.display.Loader;
     import flash.display.LoaderInfo;
     import flash.display.MovieClip;
     import flash.events.Event;
     public class Test extends MovieClip {
      [Embed(source="test.swf")]
      private var Swf:Class;
      private var _mc:MovieClip;
      public function Test() {
       _mc = new Swf();
       addChild(_mc);
       var _loaderInfo:LoaderInfo = (_mc.getChildAt(0) as Loader).contentLoaderInfo;
       _loaderInfo.addEventListener(Event.INIT,_listener);
       function _listener(e:Event):void {
        MovieClip(_loaderInfo.content).gotoAndStop(2);
       }
      }
     }
    }

    如果需要控制嵌入的 SWF 资源文件中单个的元件或类,需要使用到 ApplicationDomain 类的实例方法 getDefinition() ,详请参考《[Embed] 元数据标签嵌入高版本的 SWF 资源文件时的一些备忘知识

    Jun

    26

    [Embed] 只能在变量定义层支持任何版本的整个 SWF 文件的嵌入,但不能在类定义层嵌入整个的 SWF 文件。  

    在 Flash Player 9(或更高版本)的 SWF 文件中的单个符号和类不可以使用 [Embed] 标签来嵌入,但对 8 以下的版本可以。另外,如果嵌入了整个的 9 以上版本的 SWF 文件,必须通过以下方式来访问单个的符号和类:

    ● 在变量层嵌套 9 以上版本的整个SWF文件,然后使用ApplicationDomain 类的实例方法 getDefinition() 来访问单个的符号或类。

    ● 把整个SWF文件以二进制数据的方式来嵌套,然后使用ApplicationDomain 类的实例方法 getDefinition() 来访问单个的符号或类。

    ● 链接到含有该类或符号的一个SWC库文件。

    Dec

    6

    一旦使用了 Embed 标签将 swf 嵌入到了 SWFLoader 组件中,就无法再使用 Flex 帮助文件中写的 content 属性去引用被嵌入的 SWF 文件。这时 content 属性引用的是一个 flash.display.Loader 对象(并且为私有对象)。需通过getChildAt(0)取到这个 loader 对象的引用,然后再通过 loader 对象的 content 属性引用被嵌入的SWF文件。

    即被嵌入的SWF为以下引用:swfLoader.content.getChildAt(0).content