About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Jul

    20

    在移动设备应用开发过程中,性能优化是非常重要的。硬件设备和操作系统在这个时代的更新速度非常,有时候我们既想兼容旧的设备,又想兼容新设备,所以对于一些复杂的大量数据处理时,往往会对旧设备和新设备采用不同的算法。特别是新设备由于拥有较高的性能,所以算法优化的地步也非常大。

    AS3 在 Capabilities 里提供了 supports64BitProcesses 这个 API,用于检测指定系统是否支持运行 64 位的进程。这个 API  在我的 Win 7 64位版桌面应用开发过程中发现它非常好用,但在 iOS 系统检测结果是 64 位的硬件 + 64 位的系统,它返回都是 false(无论我使用 iPhone6 或 iPad Air, 再加上 8.3 和 8.4的最近版本的 iOS 系统,使用了最新的 AIR SDK 16 和 17 测试结果,它都给我返回 false,这应该算是个移动设备上的 Bug 么?)。

    Google 了一下之后,发现很早以前就有人在 Adobe 官方论坛反映过这个问题,但官方没有任何回复。所以暂时不能通过 AS3 来直接判断当前的 iOS 设备是否为 64 位。又要曲线救国了~~(相对来说比较可以接受的解决方法)。

    通过观查《iOS 设备类型》规律,可以找出它设备的硬件版本号(不是操作系统版本号),便有了将优化过的 64 位算法应用到硬件版本号最低限定的那个版本(我想不管屏幕变大变小,硬件总是越升级越高吧?就这么愉快的决定了)。

    通过 Capabilities 类的 os 属性,得到 “iPhone OS x.x iPhonex,x”、“iPhone OS x.x iPadx,x”等类似的字符串,不管是 iPhone、iPad、iPod,它在返回的字符串中一开始写的都是 iPhone,但在最后面那个空格之后,会具体显示是 iPhone、iPad、iPod,这个就足够了。 

    static private function is64Bit(): Boolean {
        var os: String = Capabilities.os;
        var arr: Array = os.split(" ");

        os = arr.pop();

        if (os.indexOf("iPhone") > -1) {
            //iPhone 5s 以上的手机
            if (String(os.split("iPhone")[1]) >= "6,1") {
                return true;
            } else {
                return false;
            }
        } else if (os.indexOf("iPad") > -1) {
            //iPad air 以上的平板,包括 mini
            if (String(os.split("iPad")[1]) >= "4,1") {
                return true;
            } else {
                return false;
            }
        } else if (os.indexOf("iPod") > -1) {
            //据称将来的 iPod 会支持 64 位,暂时就不考虑了
            return false;
        } else {
            //未知设备,也许是个新设备,防止意外就使用未经优化过的算法吧
            return false;
        }

        return false;
    }

    Jul

    20

    iOS 设备类型

    • 0 Comments
    • Miscellaneous
    DEVICE TYPE PRODUCT NAME
    iPhone1,1 iPhone
    iPhone1,2 iPhone 3G
    iPhone2,1 iPhone 3GS
    iPhone3,1 iPhone 4 (GSM)
    iPhone3,3 iPhone 4 (CDMA)
    iPhone4,1 iPhone 4S
    iPhone5,1 iPhone 5 (A1428)
    iPhone5,2 iPhone 5 (A1429)
    iPhone5,3 iPhone 5c (A1456/A1532)
    iPhone5,4 iPhone 5c (A1507/A1516/A1529)
    iPhone6,1 iPhone 5s (A1433/A1453)
    iPhone6,2 iPhone 5s (A1457/A1518/A1530)
    iPhone7,1 iPhone 6 Plus
    iPhone7,2 iPhone 6
    iPad1,1 iPad
    iPad2,1 iPad 2 (Wi-Fi)
    iPad2,2 iPad 2 (GSM)
    iPad2,3 iPad 2 (CDMA)
    iPad2,4 iPad 2 (Wi-Fi, revised)
    iPad2,5 iPad mini (Wi-Fi)
    iPad2,6 iPad mini (A1454)
    iPad2,7 iPad mini (A1455)
    iPad3,1 iPad (3rd gen, Wi-Fi)
    iPad3,2 iPad (3rd gen, Wi-Fi+LTE Verizon)
    iPad3,3 iPad (3rd gen, Wi-Fi+LTE AT&T)
    iPad3,4 iPad (4th gen, Wi-Fi)
    iPad3,5 iPad (4th gen, A1459)
    iPad3,6 iPad (4th gen, A1460)
    iPad4,1 iPad Air (Wi-Fi)
    iPad4,2 iPad Air (Wi-Fi+LTE)
    iPad4,3 iPad Air (Rev)
    iPad4,4 iPad mini 2 (Wi-Fi)
    iPad4,5 iPad mini 2 (Wi-Fi+LTE)
    iPad4,6 iPad mini 2 (Rev)
    iPad4,7 iPad mini 3 (Wi-Fi)
    iPad4,8 iPad mini 3 (A1600)
    iPad4,9 iPad mini 3 (A1601)
    iPad5,3 iPad Air 2 (Wi-Fi)
    iPad5,4 iPad Air 2 (Wi-Fi+LTE)
    iPod1,1 iPod touch
    iPod2,1 iPod touch (2nd gen)
    iPod3,1 iPod touch (3rd gen)
    iPod4,1 iPod touch (4th gen)
    iPod5,1 iPod touch (5th gen)

     相关链接 iOS Device Typeshttp://support.hockeyapp.net/kb/client-integration-ios-mac-os-x/ios-device-types

    Jul

    19

    先上一段代码:

    var novel:XML = <BOOK ISBN="0141182806">
                        <TITLE>Ulysses</TITLE>
                        <AUTHOR>Joyce, James</AUTHOR>
                        <PUBLISHER>Penguin Books Ltd</PUBLISHER>
                    </BOOK>;

    //生成 XMLList 引用部份文档
    var children:XMLList = novel.*;

    // 删除 <PUBLISHER>
    delete novel.PUBLISHER;

    trace(novel)
    // <BOOK ISBN="0141182806">
    // <TITLE>Ulysses</TITLE>
    // <AUTHOR>Joyce, James</AUTHOR>
    // </BOOK>
    trace("================");
    trace(children)
    // <TITLE>Ulysses</TITLE>
    // <AUTHOR>Joyce, James</AUTHOR>
    // <PUBLISHER>Penguin Books Ltd</PUBLISHER>
    // <PUBLISHER> 还是在的,没有受到前面 XML 对于节点删除的操作影响!

    当 XML 中的节点删除时,引用 XML 的 XMLList 并没有受到影响,看起来这部份引用是死的。接下来再看下一段代码:

    var novel:XML = <BOOK ISBN="0141182806">
                        <TITLE>Ulysses</TITLE>
                        <AUTHOR>Joyce, James</AUTHOR>
                        <PUBLISHER>Penguin Books Ltd</PUBLISHER>
                    </BOOK>;

    //生成 XMLList 引用部份文档
    var children:XMLList = novel.*;

    // 这里稍作修改,将原先的删除 <PUBLISHER> 改为值的修改
    novel.PUBLISHER = "HaHa";

    trace(novel)
    // <BOOK ISBN="0141182806">
    // <TITLE>Ulysses</TITLE>
    // <AUTHOR>Joyce, James</AUTHOR>
    // </BOOK>
    trace("================");
    trace(children)
    // <TITLE>Ulysses</TITLE>
    // <AUTHOR>Joyce, James</AUTHOR>
    // <PUBLISHER>Penguin Books Ltd</PUBLISHER>
    // <PUBLISHER>HaHa</PUBLISHER>

    两段代码其实是一模一样的,只是把前一段代码中的 delete 删除一个节点的操作,改为对节点值修改的操作。会发现这部份引用它是活的。

    按照 Colin Moock 《Essential ActionScript 3.0》中第 18 章 “18.9.6. References to Parts of a Document are Not Live”关于 XML 的说法:

    As you change or add new content to an XML object, bear in mind that any updates you make will not be reflected by variables that refer to part of that document.

    这句话仔细的翻译了一下,应该是理解成对于 XML 文档部份的引用是死的,对 XML 文档内容的修改或添加,它是不会反映到部份引用的 XMLList 对象中才对。虽然它里面有一句“Future versions of E4X may support live references to parts of a document.(意思是将来也许可能支持活的)”。

    但实际情况是我在最早的 FLASH CS3 中测试的结果和最新版本的 FLASH CC 版本测试的结果完全一样,也就是它从一开始到现在就是半死不活的……

    Jul

    16

    有时候经常想要调用一个简单的对话框,可能是提示,或输入确认等,但并不想花很多时间去为各种分辨率进行设计。这时候能想到的最便捷的方法就是使用原生弹出对话框。

    但 AS3 并没有提供这些原生的便利,不能直接调用原生的对话框功能,需要通过 ANE 才能实现。但客户端的 JS 环境提供了很多的便利,因为 AIR 在移动设备上使用 StageWebView 类时调用的直接就是系统浏览器控件。所以实际上不需要通过 ANE ,只需要通过 JS 就能间接的调用原生的弹出对话框

    代码 + 截图,然后再对效果加以改进。以下以 iOS 8 环境中的截图为样例(已经测试过在 iOS 7 和 8 上都完全正常,效果稍有不同后面说明,安卓机上没有去测试,反正代码都一样,有需要的可以自己去测一下。

    备注:如何通过 AS 运行 JS 并读取 JS的返回值参考《读取 iOS 屏幕物理点数完整样例代码》贴子有完整样例代码。

    JS 字符串代码:

    var str:String = (<![CDATA[
        <script type="text/javascript">
        alert("Hello,你好");
        confirm("Hello,你好");
        var name=prompt("Hello,你好,叫什么名字?","匿名");//将输入的内容赋给变量 name ,
        //这里需要注意的是,prompt有两个参数,前面是提示的话,后面是当对话框出来后,在对话框里的默认值
        </script>
    ]]>);

    在 iOS 设备上运行看效果(点击图片可以看大图):

      

    恩,完全可以使用,但发现它的标题是 “http://adobe.1437011307.apollo.air”,效果太差了,Google 了一下之后没有发现可以修改的方法,囧 - - 。但是还是找到了一个去掉标题的方法,继续往下,把 JS 代码修改成下面这样子:

    var str:String = (<![CDATA[
        <script type="text/javascript">
            var iframe = document.createElement("IFRAME");
            iframe.setAttribute("src""data:text/plain;");
            document.documentElement.appendChild(iframe);
            window.frames[0].window.alert("Hello,你好");
            window.frames[0].window.confirm('Hello,你好');
            window.frames[0].window.prompt('Hello,你好,叫什么名字?',"匿名");
            iframe.parentNode.removeChild(iframe);
        </script>
    ]]>);

    再运行看看效果:

      

    标题消失了,仔细一点看,这个没有标题的弹出对话框中文字,相对于前面带有标题的对话框而言文字变粗了一点(在 iOS 7 上它并不会变粗,在 iOS 8 上面才变粗一点)。效果到了勉强可以接受的地步。

    Jun

    28

    升级 iTunes 几天后,发现 FlashBuilder 4.7 在真机调试时 AIR SDK 找不到设备,显示“Flash Bulider找不到连接的设备”。像上次一样 CMD 命令行中输入(啊~,我为什么要说像上次一样):

    <Flash Builder 4.7 Program Files>\eclipse\plugins\com.adobe.flash.compiler_4.7.0.348297\AIRSDK\lib\aot\bin\iOSBin\idb.exe -devices

    提示:

    iTunes MobileDevice library not found.Please check your iTunes installation.

    Google 之,找到“iTunes 12.1.2(Windows 版)(64 位,适用于较早的显卡)”,下载,安装,搞定。

    备注:具体原因不清楚,但可以肯定不是因为显卡原因,因为刚一开始自动升级 iTunes 12.1.2 版本后的几天是可以真机调试的,过了几天才不能真机调试。

    Jun

    26

    继续《Adobe AIR 读取屏幕物理点数(非物理尺寸、非像素尺寸)的方法》,如果不使用 StageWebViewBridge-master,这里提供一个通过 StageWebView 获取 iOS 屏幕物理点数的样例代码(如果是安卓系统,可以直接用那篇文章中引用的官方推荐值 DPI 值 160)。

    JS 部份主要代码:

    package
    {
        public class ScreenJS
        {
            public function ScreenJS()
            {
                throw Error("无法实例化的类")
            }

            //这是一个奇怪的字符串写法
            //可以参考这个贴子:http://blog.zinewow.com/post/270.html
            //这样写的目的只是为了方便字符串在AS中换行
            static public const xmlString:String =

            (<![CDATA[
                <script type="text/javascript">

                    function getInfo() 
                    {
                        var u = navigator.userAgent;


                        if(u.indexOf('iPhone') > -1 || u.indexOf('iPad') > -1)
                        {
                            window.location.href = "http://127.0.0.1/?" + window.screen.height + "x" + window.screen.width;
                        }
                    }     

                    getInfo() ;

                </script>
            ]]>);
        }
    }

    AS 部份主要代码:

    //某个地方生成了 StageWebView 对象并添加了侦听器,一般就要主函数吧
    var view:StageWebView = new StageWebView();

    view.stage = stage;
    view.addEventListener(LocationChangeEvent.LOCATION_CHANGING, locationChaningHandler);
    view.loadString(ScreenJS.xmlString);


    //侦听器函数
    private function locationChaningHandler(e:LocationChangeEvent):void
    {
          e.preventDefault();//我们并不是为了跳转网页,所以这里中止跳转

          var location:String = e.location;
          var dpi:String= String(location.split("?")[1]);
          trace("dpi:", dpi);
    }

    Jun

    25

    BlackBerry PlayBook SDK for Adobe AIR

    • 0 Comments
    • Flash Platform

    在找资料的时候发现黑莓曾经居然为 ADOBE AIR 移动开发做过独立的组件:

    https://developer.blackberry.com/playbook/air/apis/qnx/ui/listClasses/package-detail.html

    Jun

    24

    将 APP 制作成为横向的应用,在 -app.xml 中设置 aspectRatio 为 landscape,并禁止它的旋转功能 autoOrients 为 false,通过 StageWebView 调用 JS 读取屏幕的宽与高。时此 JS 返回的仍然是垂直时 APP 的屏幕物理点数(关于物理点数,请参考这里),并非是旋转后屏幕的物理点数(与 stage 方向并不一致,不知道这算不算 Bug)。

    以 iPad AIR 为例:

    读取屏幕:alert(window.screen.height + " x " + window.screen.width);

    向的 APP 得到的物理点数并非  768 x 1024,而是1024 x 768(依旧是垂直方向的物理点数)。

    Jun

    24

    LabelItemRenderer 的文本在通过 setStyle 方法设置 fontFamily 时如果提供的是中文或日文,并不一定能按 Font 类的 fontName 来正确显示样式。

    推荐使用自定义 ItemRenderer 类,内部放入一个比较重量级 spark 的 Label 组件(因为移动开发时不支持 mx 组件,所以只能退而求其次选 spark 了)。这样就能通过 fontFamily 正确的显示所有非英文字体的样式了。

    Jun

    20

    物理尺寸单位一般用英寸表示,比如 iphone4s 为 3.5 英寸。像素尺寸单位一般就直接以像素表示,比如 iphone4s 屏幕分辨率为 640 像素 x 960 像素,一般用 PP 表示。物理点数(有些人称它为逻辑分辨率,也有些人称它为设备独立像素)一般用 DP 表示,比如 IPHONE 4S 与 3GS 有相同的物理点数都是320 x 480,但 4S 拥有不同的像素尺寸 640 x960。

    AS 可以有不少类的 API 都可以获取屏幕的像素分辨率尺寸,然后可以通过 Capabilities 类的 screenDPI 属性计算出一个设备屏幕的物理尺寸。但 AS 并没有提供任何属性或方法可以获取屏幕的物理点数。虽然 screenDPI  看上去像是获取每英寸内的 DP  值,但实际上它获取的是每英寸内 PP 值。

    如果使用 FeathersUI 的话,它里面提供了 DeviceCapabilities 类,能更方便的获取物理尺寸,但依然是不能获取物理点数的。

    Adobe 官方的博客有一节专门讲解了 “Calculating physical dimensions”:

    Looking at the dots-per-inch (more properly called PPI or pixels-per-inch), you can estimate how big your interface should be to avoid fat-finger mistakes. Apple suggests the minimum size for buttons and interactive objects should be 44 x 44 pixels for a 163 dpi screen (for example, an iPhone 3GS).

    Android uses the concept of density-independent pixels (dp), which is a normalized pixel unit for defining resolution compared to a 160 dpi screen. A device's dp is calculated as pixels * 160 / DPI. To determine the dpi, dp, and size in inches you can use the following code:

    Adobe 官方指出苹果公司推荐的 DPI 值是 160(实际是163,注意这个不是 Capabilities 里面 screenDPI 值,因为 screenDPI 实际是一个 PPI 值),但实际测试发现这个值在 IPHONE 上算出正确结果,但 PAD 上是完全错误的,所以这并没有什么卵用。

    移动版本的 AIR 并不支持 HTMLLoader 类,既便支持也不会有什么卵用,因为它使用的是 AIR Web 控件,所以读到的 99% 依然会是像素尺寸,不会是物理点数(因为不支持 HTMLLoader,所以我猜的)。

    但 AIR 支持 StageWebView ,它实际上调用的是系统原生的 Web 控件,而 Web 控件可以运行 JS,所以可以通过它来获取系统更多的信息。

    var swv:StageWebView = new StageWebView();
    swv.loadString('<script>function getInfo() {alert(window.screen.width + "x" + window.screen.height)} getInfo();</script>');

    现在可以很轻松的获得屏幕的物理点数了,但 StageWebView 中的 JS 是不能直接与 AS 交互的,所以要通过 location 来传递参数,但使用起来会比较不方便。推荐使用 StageWebViewBridge-master,它已经很好的包装了这个 location 属性,可以很方便的让 JS 与 AS 之间的通信。

    如果不知道 StageWebViewBridge 如何使用,这里有篇中文资料:http://bbs.9ria.com/thread-418243-1-1.html