About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Jan

    5

    和 Starling旧版一样,2.0的版本设置步骤仍然是异步的,也就是如下步骤产生 Game 类的实例并不是同步的,不能直接调用 Game 类实例中的方法:

    package
    {
        import flash.display.Sprite;
        import starling.core.Starling;

        [SWF(width="640", height="480",
             backgroundColor="#808080",
             frameRate="60")]
        public class Main extends Sprite
        {
            private var _starling:Starling;

            public function Main()
            {
                _starling = new Starling(Game, stage);
                _starling.start();
            }
        }
    }

    但可以侦听 ROOT_CREATED 事件:

    public function Main()
    {
        _starling = new Starling(Game, stage);
        _starling.addEventListener(Event.ROOT_CREATED, onRootCreated);
        _starling.start();
    }

    private function onRootCreated(event:Event, root:Game):void
    {
        root.start()// 'start' needs to be defined in the 'Game' class
    }

    Dec

    27

    AS3 的一些“奇葩”资料

    • 0 Comments
    • Flash Platform

    1、switch 的 default 关键字通常出现在最后,或者可以被省略,但它却可以合法的出现在 switch 语句的任何地方。

    2、switch 的条件表达式与 case 表达式比较的时候,使用的是“===”,而不是“==”。

    3、Flex 和 MXML 中,程序的主类必须放在匿名包中。

    4、使用数组索引访问数组时,如果索引值大于数组的长度,返回undefined,但数组的长度本身并不产生变化。

    5、get 方法会在 set 方法后自动被调用,所以 get 方法里的变量如果用于计数,会被 set 方法搅乱。

    6、函数内的代码如果放在嵌套函数中,在 return 后是可以继续执行的,函数会自动向前引用。

    7、AVM 加载类的时候才执行类初始化程序(静态初始化/静态块)。

    8、即使在严格模式下,以下三种情况也会忽略类型不匹配错误:

    a、无类型表达式赋值给类型表达式。

    b、任何表达式赋值给 Boolean 类型。

    c、任何数值类型实例被用于希望得到不同的数值类型实列。

    9、实例转换类型包含转型,但实例“转型”不同于“转换”类型(这是在玩文字游戏么……听起来好搞):

    A、类型(表达式),这种是转换。

    a、转换成功返回表达式。

    b、转换失败会有两种结果:如果是原生类型,会被强制转换;如果是非原生类型,产生运行时异常。

    B、表达式 as 类型,这种是转型(不是转换)。

    a、转型成功返回表达式。

    b、转型失败返回 null(就算是转型到原生类型失败也只返回 null 值)。

    10、throw 作为编程惯例只抛出 Error 类或它的子类,但实际上它能抛出任意数据类型。

    11、finally 块中的代码一定会被执行,包括在return/continue/break等语句转出时;而且优先执行于外部冒泡捕获异常时的代码。

    12、一个动态类的子类不被当作是动态的,除非子类也包含 dynamic 修饰。

    13、所有动态实例变量都是无类型且公有的(动态实例变量的性能相较于正规的实例变量的性能低一些)。

    14、标识符的规则不适用于中括号“[]”运行符创建的变量。如 obj["111"]这种纯数字标识符也是合法的。

    15、AS3 依旧支持使用 prototype 增强类。

    16、开放的命名集甚至优先于 use namespace 语句的使用(就好像  use namespace 被自动移动到了一个作用域代码块的顶部)。

    17、开放的命名空间对嵌套作用域保持开放。

    18、一个命名空间一旦被开放,就不能被“关闭”,也不能被移除。

    19、使用通配符 * 导入一个包的时候,只是导入了包的 public 命名空间,并没有开放 internal 命名空间。

    20、E4X 分析器默认忽略 XML 注释与处理指令。

    21、当parent()被调用于表示 XML 实例的一个属性时,它返回属性被定义的那个元素。

    22、XML 是动态类,AS推迟类型检查直到运行时。

    23、AS3.0 实现的 E4X 规定引用不存在的 XML 属性时返回一个空的 XMLList 对象,不会产生异常。

    24、XML 的方法有可能会被“转发”XMLList,但并不涉及类型“转换”,所以当需要类型检验时,一个 XMLList 并不能自动转换成 XML 类型,需要显示引用 XML 实例。

    25、XMLList 中的 XML 元素名并非变量名,使用 for - in 可以遍历出它们的变量名为“0、1、2……”

    26、谓词过滤之前可以先使用 hasOwnPropety() 来检查属性或元素是否存在。

    27、如果在加载策略文件之后立即调用加载数据的命令,FlashPlayer 会在加载数据之前自动等待策略文件的加载。

    28、注册在事件目标阶段的侦听器,如果 usecapture 被设置为 true,就永远不会被触发了。

    29、关于事件流在传播过程中的奇葩情况老贴《AS3事件流机制中二个重要的应用知识

    30、当一个输入法 IME 在使用的时候,键盘事件相关的实例变量keyCode和charCode是不被支持的。

    31、如果通过 TimerEvent.TIMER 事件来更新屏幕,最多可以产生十次(10倍于帧速)。

    32、调用 Graphics 实例的 clean() 方法后,对象的线型会被还原成为 undefined,画笔位置还原为 0,0。

    33、和 appendText 不同,“+=”运算符将文本域中的所有文本格式重置为默认文本格式;并且“+=”的性能也低。

    34、即使被 FlashPlayer 打开的第一个 SWF 文件从舞台上被移除,它仍然被当作舞台拥有者,并且控制相对URL 解析。

    35、使用 Socket 类和 Loader 类的 loadBytes()方法结合使用,可以防止被加载的资源出现在缓冲区(如WIN 系统的IE临时文件夹)。

    36、对于模运算符,如果运算的对象不是整数,可能会出现一些意外的小数。

    37、in 运算符可以用来判断一个对象是否作为另一个对象的键或索引,存在返回 true,否则就是 false。

    38、函数如果使用了...(rest)关键字,那么 arguments 就不能再使用了。

    39、函数语句定义法定义的函数本质:MethodClosure 类不是动态类;函数直接量表达式定义的函数本质:Function-N 是动态类。

    Apr

    18

    机型 宽高比 屏幕模式
     iPhone3GS  320  480  0.667  1x
     iPhone4 & 4S  320  480  0.667  2x
     iPhone5  320  568  0.563  2x
     iPhone6  375  667  0.562  2x
     iPhone6 Plus  414  736  0.563  3x

    纯 AS3 异步读取 iPhone 屏幕物理点数的方法参考以下链接:

    1、《Adobe AIR 读取屏幕物理点数(非物理尺寸、非像素尺寸)的方法

    2、《读取 iOS 屏幕物理点数完整样例代码

    除了纯 AS3 获取方式外,一些第三方的 ANE 带有同步获取屏幕物理点数的方法。

    Apr

    18

    将多个 SWF 文件合并为一个 SWF

    • 0 Comments
    • Flash Platform

    偶然看到的《将多个 SWF 文件合并为一个 SWF 以进行 iOS 部署》,感觉并没有什么用,或者说它是一种已经落后的淘汰的技术。

    iOS 部署现在支持多个 SWF 打包。如果一定要从技术上实现多个 SWF 合并成一个 SWF 文件,更推荐这两种:第一种,以原生库元件技术上合并,推荐使用 SWFTools 的合并功能,同样是命令行操作;第二种,以二进制文件作为库元件来说,不如 hxswfml,既提供了命令行版本,也可以纯 AS3 实现。

    Apr

    2

    Google Play 报 AIR 应用 OpenSSL 漏洞问题已经不是一次两次了,2014 年和 2015 年都有过一次,今年 2016 年果不其然的又来一次,看到 Starling 开发者论坛里其它人也收到了类似的警告(下面是两个案例贴子):

    1、Google Play warning: You are using a vulnerable version of OpenSSL

    2、Open SSL Version in AIR

    警告的内容大致如下(事实上在 Google 搜索里可以找到其它平台的开发人员也收到了类似的警告,不仅仅只是 Adobe AIR 平台的开发者):

    Hello Google Play Developer,
     
    Your app(s) listed at the end of this email utilize a version of OpenSSL that contains one or more security vulnerabilities. If you have more than 20 affected apps in your account, please check the Developer Console for a full list.
     
    Please migrate your app(s) to OpenSSL 1.02f/1.01r or higher as soon as possible and increment the version number of the upgraded APK. Beginning July 11, 2016, Google Play will block publishing of any new apps or updates that use older versions of OpenSSL. If you’re using a 3rd party library that bundles OpenSSL, you’ll need to upgrade it to a version that bundles OpenSSL 1.02f/1.01r or higher.
     
    The vulnerabilities were addressed in OpenSSL 1.02f/1.01r. The latest versions of OpenSSL can be downloaded here. To confirm your OpenSSL version, you can do a grep search for ($ unzip -p YourApp.apk | strings | grep "OpenSSL").
     
    To confirm you’ve upgraded correctly, submit the updated version to the Developer Console and check back after five hours. If the app hasn’t been correctly upgraded, we will display a warning.
     
    The vulnerabilities include "logjam" and CVE-2015-3194. The Logjam attack allows a man-in-the-middle attacker to downgrade vulnerable TLS connections to 512-bit export-grade cryptography. This allows the attacker to read and modify any data passed over the connection. Details about other vulnerabilities are available here. For other technical questions, you can post to Stack Overflow and use the tags “android-security” and “OpenSSL.”
     
    While these specific issues may not affect every app that uses OpenSSL, it’s best to stay up to date on all security patches. Apps with vulnerabilities that expose users to risk of compromise may be considered in violation of our Malicious Behavior policy and section 4.4 of the Developer Distribution Agreement.
     
    Apps must also comply with the Developer Distribution Agreement and Developer Program Policies. If you feel we have sent this warning in error, contact our policy support team through the Google Play Developer Help Center.
     
    Regards,
     
    The Google Play Team
     

    测试了有两种方法可以解决这个问题,但每种方法都会存在问题。

    第一种方法:就如 Starling 论坛里面其它开发人员所述的,使用 AIR SDK 21 重新编译,然后再重新发布新版本。但这种方法并不代表是永久性的消除了问题,过一两年后也许在 2017 年…又会报旧版本 OpenSSL 存在的其它安全问题,或又报新的漏洞。如果帐号下面的应用数量越来越多,那么每过一年左右被这么搞一下是非常蛋疼的(而且你还得保证你的代码不会出什么意外事故)。

    第二种方法:在编译的时候不要集成 AIR 运行时环境,但打包时运行时环境的下载地址一定要选“Android Market - https://market.android.com/details?id=com.adobe.air”,因为 Google Play 政策有规定,应用不允许通过其它第三方平台下载和安装未知来源的应用(如果被 Google 发现是要被下架的)。这种方法的好处就是可以长久性的避免将来由 AIR 运行时环境带来的 OpenSSL 漏洞。缺点也很明确,这样的做法就会导制应用很可能不会被其它平台接受,因为很多平台规定不允许使用运行时共享技术给用户带来不好的体验,同样很多平台也会规定禁止下载其它平台的应用,尤其是在国内,既便国内平台允许用户下载第三方平台的应用,也会因为中国防火墙的问题无法下载 Google Play 上的 AIR 运行时环境(国内的普通用户甚至可能连 Google 帐号都没有)

    备注:虽然警告中写了提交更新 5 小时后如果正确的话警告信息会消失,但实际上你可能要等 10 小时以上。

    Mar

    21

    Mar

    18

    很简单的一行 AS3 代码:

    txt.text = String(parseFloat("9.2.1"));

    使用 Flash CS3 编译输出错误结果:92.1,既便是在高版本的 FlashPlayer 17 以上的版本中运行,也是一样错误的结果 92.1

    使用 Flash CS4 或 CC 输出正确结果:9.2,但如果将它运行在 Flash9 和 10.0 版本中,同样会变成错误的结果:92.1。如果运行在 10.1 以上的版本则输出正确结果 9.2 。

    PS:如果设置成 AS2 输出错误结果:9.21。

    突然对这个 API 感觉很不靠谱……

    Feb

    23

    很多时候我们需要用到设备的唯一识别码。安卓系统获取设备唯一识别码的资料网上比较多,但它们也并不通用,因为现在市场上的很多安卓机实际上它们的系统都是经过设备厂商修改过的,比如小米的系统,阿里云OS手机系统等等,所以实际上并不存在一个真正通用的方法。以下这个方法仅适用于 iPhone / iPad 设备或桌面设备,并不适用于 Android 系统(原因在后面)。

    苹果设备的 “IDFA、IDFV、UDID、OpenUDID 等等”这些标识区别可以在百度上找到,这些标识除了真正的 UDID 和 MAC 物理地址之外,其它的标识在很多情况下是会发生变化的:最常见的情况就是还原出厂设置后,会生成一个新的标识符。网络上一些第三方能够获得 UDID 的 SDK,实际上都是 OpenUDID,并不是真正的 UDID。

    苹果公司政策规定开发者是不能够获取用户设备的物理信息的(在 iOS 4.x 时代是获取 UDID 和 MAC 物理地址的,后来的新系统中都开始禁止了访问这些信息)。如果利用核客技术访问私有 API 被审核人员发现,那么一定会遭到苹果公司拒审;既便上架了被发现也会被下架。

    重要的事情说三边

    1、苹果公司政策规定不允许第三方开发者获取设备真正的唯一识别码!苹果公司政策规定不允许第三方开发者获取设备真正的唯一识别码!苹果公司政策规定不允许第三方开发者获取设备真正的唯一识别码!

    2、利用核客技术或系统漏洞调用苹果私有 API 会拒和下架!利用核客技术或系统漏洞调用苹果私有 API 会拒和下架!利用核客技术或系统漏洞调用苹果私有 API 会拒和下架!

    3、利用任何标识符统计用户数据必须接受苹果公司审核!利用任何标识符统计用户数据必须接受苹果公司审核!利用任何标识符统计用户数据必须接受苹果公司审核!

    4、开发者不要仅研究技术,也要知晓各平台的政策!开发者不要仅研究技术,也要知晓各平台的政策!开发者不要仅研究技术,也要知晓各平台的政策!

    技巧

    同一时间是指精确到毫秒级的时间!目录与创建时间!!硬件磁盘根目录即文件目录!!!

    从理论上来说,我们可以在同一时间创建两个目录,但那仅仅是理论上的,所以标题中“唯一”两个字加了引号。两块闪存盘同时间被格式化完成?这个概率可能比两个目录的创建时间完全相同的机率还要低。

    代码

    import flash.filesystem.File;
    import flash.globalization.DateTimeFormatter;

    trace("硬件信息:");

    var rootDirArr:Array = File.getRootDirectories();

    for (var i:uint = 0; i < rootDirArr.length; i++) 
    {
        var file:File = rootDirArr[i];

        var date:Date = file.creationDate;

        var dtf:DateTimeFormatter = new DateTimeFormatter(LocaleID.DEFAULT);
            dtf.setDateTimePattern("yyyy/MM/dd HH:mm:ss");

        var creationTime:String = dtf.format(date);

        //看到最后的这个 milliseconds 值了吗
        trace(file.nativePath + ":" + creationTime + "," + date.milliseconds);
    }

    如果是在我的 Windows 7 中调试运行,它会显示(它并不需要系统管理员的权限就能读取):

    硬件信息:
    C:\:2009/07/14 10:38:56,526
    D:\:2010/08/23 23:59:31,18
    E:\:2010/08/23 23:59:46,99

    如果是在我的 iOS 9.2 (iPhone6 Plus)中运行,它会显示(不需要越狱):

    硬件信息:
    /:2015/06/25 17:47:25,10

    使用这个方法最大好处就是不需要 ANE 文件。既便用户在系统设置中还原位置与隐私、还原广告标示符、抹掉所有内容与设置、升级系统等,磁盘的创建时间都不会发生变化,既便用户完全重置系统,还原所有设置到出厂状态,磁盘的创建时间都不会发生变化。经过测试,只有在使用线刷 / 强制刷机的情况下,磁盘才会被重新创建并且格式化,磁盘的创建时间才会发生变化 

    额外的话题:关于 Android 系统

    然后,以上这个方法并不适用于 Android 系统,在 Adobe 官方的 API  手册中 getRootDirectories() 方法下面已经有说明:“在根不可读的文件系统上,例如 Android 文件系统,返回的 File 对象的属性并不总是反映真实值。例如,在 Android 上,spaceAvailable 属性报告 0。” 安卓系统可以使用原生的方式获取设备id,制作成 ANE 文件给 AS3 调用。但正如前面第一段所述的,既便是 Google 提供的 getDeviceId() 这个 API 并不通用,因为国内很多手机厂商对安卓系统进行了修改,很多权限都发生了改变。

    比如,在不使用 ANE 的情况下,在未经修改的安卓系统中,可以用如下方法读取 MAC 网卡地址。我在 HTC 手机中进行了测试,-app.xml 中的权限:

    <!--删除 android.permission.INTERNET 权限将导致无法调试设备上的应用程序-->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!--应同时切换 ACCESS_NETWORK_STATE 和 ACCESS_WIFI_STATE 权限,才能使用 AIR 的 NetworkInfo API-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

    AS3:

    var netWorkVec:Vector.<NetworkInterface > = NetworkInfo.networkInfo.findInterfaces();

    for (var i:* in netWorkVec)
    {
        if(netWorkVec[i].hardwareAddress)
            trace("MAC 物理地址:",netWorkVec[i].hardwareAddress);
    }

    结果输出了:

    MAC 物理地址: D8:B3:77:7F:00:47

    但是,同样的代码,在国内厂商经过修改后的系统里,它并不能正常输出 MAC 网卡地址,比如使用阿里云OS的联想手机经过测试就不能。所以如果 AS3 的安卓开发者们想要一个通用的获取设备硬件信息的方法,几乎是不可能。

    Feb

    21

    Adobe AIR Gaming SDK ANE 64位版本

    • 1 Comments
    • Flash Platform

    官方博客里下载到的是 32 位的版本。在官方的论坛里找到了 64 位版本。里面的链接是指向 dropbox.com 域名的,国内用户需要链接 VPN 才能下载,不知道什么原因 Adobe 的工作人员为什么要把文件放在 dropbox 网站去~

    没有 VPN 的话也可以在这里下载:Adobe Gaming SDK 64bit ANE.zip

    在 Adobe 开发者中心还找到了另一个个人升级过的版本,但当点击他的 Game Center Demo 中点击 Score 按钮时闪退了,替换为 dropbox 上下载的 ANE 文件并不会闪退,估计有 Bug……

    Feb

    20

    全局函数 navigateToURL() 功能很强大,仔细看它在 API 手册中的介绍,可以打开很多协议方案,可以用它启动拔号程序,短信程序等,也可以用它来打开 APP Store 程序。

    打开某个 APP 对应的中国市场页面:

    navigateToURL(new URLRequest("itms-apps://itunes.apple.com/cn/app/ANY_APP/idXXXXXXXXXX?mt=8"));

    用下面这种,可以自动识别多语言:

    navigateToURL(new URLRequest("itms-apps://itunes.apple.com/app/idXXXXXXXXXX"));

    跳转到用户评论页面,一般用的最多的估计就是这个:

    navigateToURL(new URLRequest("itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=XXXXXXXXXX"));