About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Jun

    11

    在线快速生成 iOS、Android 应用 app 图标,Assets.car、ICON ,含手机应用 ICON 模板和全部尺寸,支持 iOS 全部版本包括 iOS11 和 android 各个版本。自动生成IOS 11要求的 ICON 文件 Assets.car 。
     
    安卓图标使用:把生成的 Android 目录下的图标复制到 Android 项目中。
     
    iOS图标使用:把其他图标复制到项目中并修改配置,把生成的 Assets.car 复制到 iOS 项目根目录下 ,配置 Info.plist 中 CFBundleIconName 值为 AppIcon
    <key>CFBundleIconName</key>
    <string>AppIcon</string>

    在线地址:http://applicationloader.net/appuploader/icontool.php

    Oct

    19

    作为一名纯粹的 AS3 开发者,想要使用第三方平台的功能,总是会涉及到原生的 SDK  觉的很是坑爹,因为很少有平台会直接提供 ANE 文件给 AS3 开发者使用(尽管 GitHub 上有很多开源项目可以下载到源文件,但因为 ANE 太旧不支持 64 位或第三方的 SDK 太旧需要重新替换)。如果已经了解了安卓 ANE 的制作流程,那么基本上也就了解 iOS ANE 的制作流程了,但却又与安卓的 ANE 有很大的不同之处。

    最大的不同之处就是 Xcode 和 OC。如果已经了解了 Flash Builder(简称 FB),那么既便是零基础 ADT Bundle 用户第一次安装也会觉的有点眼熟,毕竟它们都是基于 eclipse 这个环境,知道类文件放在什么位置,第三方库从什么位置引入,并且语法也非常类似,有着相同的“包”的概念。但如果是零基础的 Xcode 用户,第一次安装后那么基本上就傻眼了——

    原本想系统的学习一边 Xcode IDE 环境,在网上找了一遍相关的书籍,基本上都在讲 OC 和 Swift 语言,找不到 Xcode 相关的书籍,唯一能够找到一本中文的书籍是古老的《Xcode 3 高级编程》的译本,看了一天连第3章都没看完,我可耻的放弃了,一是资料过于陈旧, Xcode 6/7 相比之下界面已经有了非常大的变化,二是译者很多口语用的好像都是台湾人的口语,并不是大陆口语习惯(有些句子我甚至读不通),实在看不下去了

    然后直接搜 iOS ANE 相关的教程,基本上找到的还是官方的一些制作教程,都是无关乎 Xcode 和 OC 基础的,搞的 AIR 开发者好像人人都熟悉 Xcode 和 OC 一样,也有非官方的个人博客贴子比如《IOS ANE的坑爹之路(一)》,但是都一样,并没有什么卵用,里面提到了一个“所谓的”有用工具“ANE的XCode模板”,关于它的简单介绍就是“可以省去打包 ANE 手动操作的过程”。我试了在 Xcode7 上运行脚本安装失败了,我猜它是“太老”了,我又重新下载了 Xcode 6.4 版本,再安装,还是失败,我猜它是“太老太老”了……我已经没有耐性再去下载一个更老的版本去测试这个“所谓的”有用工具了,因为在我的心里面已经将它定位成垃圾了,不就是省了一个手动打包的过程么,我在学习制作安卓 ANE 时就已经撑握了。

    对于我的挑战就是成功的制作出静态库 .a 文件发送到 Windows 下。还是直接进入实践了,于是从 Google 开始第一步搜索,如何制作一个 OC 的静态库,代码放在什么位置,啊,为什么没有包的概念,那让我填个公司或组织的反向定义做什么,等等等(不需要等到几年之后再来看这篇贴子,我现在就已经觉的很幼稚了)。同时新建了好几个项目,一边对比一边设置,不管怎么样,终于成功的制作出了 .a 文件,于是便开始了左右开弓,不断的清理,不断的生成,不断的发送到 Windows,不断的打包 ANE,不断的调试,不断的报错,不断的 Google,不断的清理,不断的生成,不断的发送到 Windows,不断的打包 ANE,不断的调试,不断的报错,不断的 Google……幸好买的是两台笔记本可以同时左右开弓操作,如果是两个台机在两个桌子跑来跑去我估计我真的会疯掉的。

    折腾了将近一天之后,当编译器的进度条终于到达 100% 没有报错时,我真想高呼一声 Google 万岁!~

    一篇通用的 64 位 ANE 制作教程《64-bit requirements for iOS apps》。

    PS:XCode 版本必须大于6, iOS SDK 版本必须大于 8,AIR SDK 版本必须大于 16.0

    我不得不说 Adobe 是我见过最好的真正面向全球的国际化公司,无论是 Photoshopw、Illustrator、DreamWeaver、Fireworks、Flash、FlashBuilder、Audition、Premiere 等等我下载过的每一个软件,无论图像、视频、动画、编程工具都提供了国际化的语言,软件从界面,到帮助文件,到 API 手册,甚至到每一个版本的更新说明,都提供了中文本地化,再看看 Xcode 和 Android Studio……我只能叹一口气“唉,英文没学好,怪我喽~”。尽管也有人说微软的产品也提供了全中文化的开发环境和全中文的 API 手册,但我更喜欢 Adobe,因为 AS3 在编程语言排行榜的历史上从来没有进过前10 名,最高一次也只到达过 18,大多时候它都在 30 名以后,有时甚至 50 名开外,它是一个何等小众化的编程语言,却提供了全球化的 API 帮助文档,这才是我喜欢它的地方。

    Aug

    24

     如果只写 zh_Hans 与 zh_Hant 只能对 iOS 系统起作用,在 Android / 安卓中文系统中它们并不会起作用。安卓需要写 zh-CN 与 zh-TW。注意下划线与减号的区别、以及英文字母大小写的区别。
    <name>
        <text xml:lang="en">默认英文名称</text>
        <text xml:lang="zh_Hans">iOS 简体中文名称</text>
        <text xml:lang="zh_Hant">iOS 繁體中文名稱</text>
        <text xml:lang="zh-CN">Android 简体中文名称</text>
        <text xml:lang="zh-TW">Android 繁體中文名稱</text>
    </name>

    Jul

    21

    发现 AS3 调用与系统相关的 API 功能时经常会发现 Bug,虽然这些 API 在桌面设备上看起来运行状态良好,但在移动开发时总会与实际情况不符。

    Microphone 类中有一个 muted 属性,可以用来判断用户是否禁用了麦克风访问权限。在网页中与纯 FlashPlayer 里它运行状况良好,但在 iOS 系统里测试时“XXXX 想访问您的麦克风”,无论我选择“不允许”或“好”,它它总是返回 false。然后又是一边 SDK 版本的替换(啊,又是一个“又”),从 SDK 16,换到17、18 测试结果都一样(因为 19 还是 Beta 版,我也懒的去测了)。

    Google 之,发现早在 4.0 版本时就已经有人在 Adobe 官方论坛提交过这个问题,官方没有作任何回复(除了有一个网友回复了一个无关紧要的相册访问的贴子,因为相册是一个应用,它会从一个应用给出提示,而 Microphone 是一个硬件,所以出错后是不会给你提示的;特别是:它的属性在返回时就已经出错了——“把错的当成对的,怎么可能再给出一个错的提示?”)。

    曲线救国的办法:在 setSilenceLevel() 方法中将 silenceLevel 值设为 0,让麦克风对象的 ActivityEvent.ACTIVITY 事件立即执行。建立一个实例变量并设为 false,在 activity 事件侦听器函数中把这个变量设为 true,加一个类似 setTimeout() 函数在200 或 500 毫秒后检测这个变量是否为 true,就可以判断出 activity 事件是否执行过。如果执行过表示有麦克风的访问权限,如果没有执行过,就表过没有权限,给出一个用户提示“设置——隐私——麦克风——XX应用”打开权限。

    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

    Oct

    5

    要点一

    侦听 CameraRoll 对象的 MediaEvent.SELECT 事件时,在 iOS 系统中是不同于 Android 系统的,不要试图访问 MediaPromise 对象的 file 与 relativePath 的,它们的值都为 null。

    要点二

    通过 mediaPromise.open() 可以得到一个照片文件的数据,但需要先判断 mediaPromise.isAsync 是否为同步或异步,如果是同步的话可以直接读取照片文件的数据,异步的话就要侦听 Event.COMPLETE 事件,等加载完数据后,再操作数据,类似如下代码:

    var dataSource:IDataInput = mediaPromise.open();

    if(mediaPromise.isAsync)
    {
        IEventDispatcher(dataSource).addEventListener(Event.COMPLETE, onDataComplete);
    }else{
        readMediaData(dataSource);
    }

    要点三

    将 dataSource 的数据写入到一个 byteArray 二进制可处理的对象中,如:

    dataSource.readBytes(byteArray);

    要点四: 

    利用第三方的 jp.shichiseki.exif.ExifInfo 类(自己到 GitHub 或 Google 上找一下就有了)读取 byteArray 中的 Exif 信息,如:

    var _exif:ExifInfo = new ExifInfo(imageFileBytes);
    if(_exif && _exif.ifds)
    {
        imageOrientation = _exif.ifds.primary.Orientation;
    }

    这里不推荐使用 Adobe 官方 XMP 开发者中心的 XMP File Info 相关的类读取照片的 Exif 信息,因为 Adobe 提供的 as3_xmp_file 类只能读取文件的 Exif 信息(适合像 Android 这样的系统中使用),不能现成读取 byteArray 对象中的 Exif 信息(也可能包含在其它类中,但我没有发现)。

    要点五

    通过读取 Orientation 的值为一个数字(每个数字对应的含义点击这里),下面是一个现成的类用于位图旋转方向:

    package
    {
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.geom.Matrix;

        public class ExifUtils
        {
            private static const PORTRAIT:int = 6;
            private static const PORTRAIT_REVERSE:int = 8;

            private static const LANDSCAPE:int = 1;
            private static const LANDSCAPE_REVERSE:int = 3;

            static public function getEyeOrientedBitmap( bitmap:Bitmap, _orientation:int ):Bitmap
            {
                var m:Matrix = new Matrix();
                var bitmapData:BitmapData;

                if( _orientation == LANDSCAPE || _orientation == LANDSCAPE_REVERSE )
                {
                    bitmapData = new BitmapData( bitmap.width, bitmap.height, true );
                }
                else
                {
                    bitmapData = new BitmapData( bitmap.height, bitmap.width, true );
                }

                m.rotate( getEyeOrientedAngle( _orientation ) * ( Math.PI / 180 ) );

                if( _orientation == PORTRAIT_REVERSE )
                {
                    m.translate( 0, bitmap.width )
                }else
                {                
                    if( _orientation == PORTRAIT )
                    {
                        m.translate( bitmap.height, 0 );
                    }else
                    {
                        if( _orientation == LANDSCAPE_REVERSE )
                        {
                            m.translate( bitmap.width, bitmap.height );
                        }
                    }
                }
                bitmapData.draw( bitmap.bitmapData, m);
                return new Bitmap( bitmapData );
            }


            static public function getEyeOrientedAngle(_orientation:int):int
            {
                var angle:int = 0;
                switch(_orientation)
                {
                    case LANDSCAPE: 
                        angle = 0
                        break;
                    case LANDSCAPE_REVERSE: 
                        angle = 180
                        break;
                    case PORTRAIT: 
                        angle = 90
                        break;
                    case PORTRAIT_REVERSE: 
                        angle = -90
                        break;
                }
                return angle;
            }
        }
    }

    其它与本文相关的资料链接(外部链接不保证长期有效):

    http://recycledinformation.blogspot.jp/2011/08/reading-exif-data-on-ios.html

    http://www.digifie.jp/blog/archives/1092

    http://snipplr.com/view/59204/exif-image-reorientation-in-android/ 

    http://stackoverflow.com/questions/5286566/using-xmpcore-to-get-metadata-of-a-file-through-actionscript

    Mar

    20

    Adobe AIR for iOS 开发时发现这个方法 System.setClipboard(string:String) 无效,剪贴板中的内容并不会因为这个方法而产生任何改变。但换成以下方法就可以: 

    Clipboard.generalClipboard.clear();
    Clipboard.generalClipboard.setData(ClipboardFormats.TEXT_FORMAT, string:String);

    我没有在安卓中测试,如果在 Adobe AIR for Android 的项目中 System.setClipboard(string:String)  也无效的话,换成上面这个吧。

    More...

    Feb

    6

    字幕是本人自己翻译的,由于视频文件较大,为减轻博客虚拟空间的压力,放在了 QQ 群:15965780 的群共享内(在视频播放器中推荐使用12-14号字体显示字幕),有需要的可以加群下载。

    Jan

    9

    不同的移动操作系统会施加不同的文件系统限制,而且这些限制通常与由桌面操作系统施加的限制有所不同。因此,平台不同,用于保存文件和数据的适当位置也可能各不相同。文件系统之间存在差异所产生的一个结果是,AIR File 类所提供的常用目录的快捷方式不一定总是可用。下表列出了可在 Android 和 iOS 上使用的权限列表:
      Android iOS
    File.applicationDirectory 通过 URL 只读(非本机路径) 只读
    File.applicationStorageDirectory 可用 可用
    File.cacheDirectory 可用 可用
    File.desktopDirectory SDCard 的根目录 不可用
    File.documentsDirectory SDCard 的根目录 可用
    File.userDirectory SDCard 的根目录 不可用
    File.createTempDirectory() 可用 可用
    File.createTempFile() 可用 可用

    iOS 远程云存储(备份与缓存)相关资料点击这里查看。

    Dec

    20