转自:http://jamesli.cn/blog/?p=1438
过去的三个月中我为iOS平台创建了三个AIR Native Extension的扩展(在Github中可以找到代码),这些扩展全部被用在我们的游戏Stick Cricket Super Sixes中,同时我们也总结了很多经验。虽然我记得并不全面,但下面这几条建议,可以给很多打算开发ANE项目的开发者助以一臂之力。
————-
文档
————-
1. 开始
这两篇文档对初学者很有帮助,如果你不知道该如何起步,可以从阅读这两篇文档开始。在网络上也有很多好的文章,只要Google一下就行了。
• Extending Adobe Air
• AIR Native Extension Example: iBattery for iOS
2. 阅读Adobe官方文档
大部分的开发所需的资料在这篇 Adobe’s documentation 中都可以找得到。
——————-
编写Actionscript代码
——————-
3. 认真编写 Actionscript API
确保你的Actionscript接口是你的项目中想要的。不要往Actionscript里被动地照搬iOS接口,要像编写常规Actioscript类那样定义你的接口。
记住,后期如果修改原生代码只会影响到ANE扩展本身,但如果修改Actionscript接口则会影响到所有使用该ANE的项目。所以在前期要尽可能完善地定义你的Actionscript接口。
4. 尽可能在Actionscript一端做错误检查
为了避免错误的发生,你需要在调用ANE方法的时候做参数合法性的检查,你可以等到调用原生代码时再做检查,但如果提前在调用Actionscript接口的时候就做检查会更简单一些。如果你能保证每次调用原生代码时都不会出错,比如参数个数和参数类型,那么完全可以只在Actionscript里做判断。
当然,如果你习惯于在C里写错误检查,当然可以。我个人更喜欢在Actionscript里做这件事情。
5. 创建一个原生类的替身
即使你打算仅为iOS写扩展,我也建议你创建一个原生类库的替身。用纯Actionscript代码创建这个替身,这样它就可以为所有的平台所用。在这个替身里按照iOS原生接口定义一套纯Actionscript接口方法,即使在调用的时候抛异常或者返回空值也没有关系,至少它是合法的Actionscript调用,而且可以在其他平台比如桌面上测试使用。
如果不用这样一个替身,你就每次只能在iOS设备上做测试,这样会让开发测试工作极为痛苦。相反,如果使用这个替身,你可以在桌面上快速发布应用来测试那些与设备不相关的功能和模块。
—————-
编写原生代码
—————-
6. 使用Objective-C来实现苹果的程序接口
你并不是必须要使用Objective-C,但是如果想要实现苹果的程序接口,用Objective-C会很方便。否则你需要用C或者C++。
7. 把为AIR编写的接口方法写在.m文件里
AIR和原生代码之间的接口是用C写的,所以你的原生代码需要引用一个包含C代码的文件来实现这些接口。如果你把接口放在.c文件中,那么你不能使用任何Objective-C功能(比如你无法用objective-c的语法去调用objective-c接口),但是如果你把接口放在了.m文件就可以。所以用.m文件会更方便一些。
8. 包含AIR原生接口的.m文件不需要.h头文件
但是你需要在XCode项目设置中的警告选项里把”missing function prototypes”这一项给关掉。
9. 为initializer和finalizer方法起一个独一无二的名字
很多ANE的例子都使用了”extInitializer”和”extFinalizer”来给扩展的入口和出口函数命名。但如果在项目中使用多个ANE扩展,这样会导致命名冲突。所以给入口和出口函数起一个独一无二的名字。
10. 在项目中使用宏
在定义接口的时候,你可能需要重复输入很多遍类似这样的代码来定义函数
FREObject someFunction(FREContext context, void* functionData, uint32_t argc, FREObject argv[])
我建议使用宏定义来代替所有这些重复的定义方式。你可以在这个源文件中找到宏定义的例子。(感谢David Wagner的提供)
11. 把“Enable linking with shared libraries”设置成yes
网络上很多关于在XCode里如何设置这个选项的讨论,有人说”no”有人说”yes”。基本上,说设置成”yes”的说明你的应用在发布的时候需要链接外部类库,这个选项就是这个意思。但是这也意味着你在发布含有此扩展的AIR应用时,你必须要告诉编译器你的iOS SDK在哪里,这样你才可以使用那些类库。具体看下面第18条。
如果你得到这样一个编译错误
ld warning: unexpected srelocation type 9
则你可能要么忘了开启这个选项,要么没有给编译器指明SDK的位置。
12. 小心使用线程
你的原生扩展不能在除主线程之外其他线程创建Actionscript对象,而且必须要从AIR端调用。这样会导致在Objective-c中使用块的时候问题重重。然而,你可以通过一种途径来达到这个目的,那就是使用Actionscript ExtensionContext事件派发机制。方法如下:
1,在一个线程中,创建一个原生对象并储存数据。
2,派发事件给ExtensionContext,为下一步传送必要的细节。
3,在事件响应的方法中,调用原生接口来获得这个原生对象。
4,在这个被调用的原生方法里,利用该原生对象创建一个Actionscript对象。
13. 创建原生view对象
AIR应用是在一个标准的window对象里运行的,你可以通过下面的方法获得这个window对象:
[UIApplication sharedApplication].keyWindow
得到window对象后你可以给它添加subviews来显示原生的view对象。
——————–
编译扩展
——————–
14. 批处理编译和测试
当我开发Game Center扩展的时候我创建了一个简单的AIR应用来测试ANE。
我创建了一个ANT脚本来编译整个扩展(编译原生C类,编译AS3类,编译AS3原生替身类,并把它们全部打包入ANE里)。
结果就是,在Eclipse里点击一次,我就可以编译和测试整个项目,下一步就是拖入设备直接测试应用了(XCode里的Organiser可以很方便的实现这步)。总共花了差不多10秒钟的时间来打包,虽然仍然比理想的多了9秒,但已经比我见过的大多数工作流都要好很多。
也许用Flash Builder有更好的方法(因为我用的是FDT),而且你当然不必使用ANT,任何编译工具都可以达到这个效果。但是你需要尽可能的使用流水线的方式来编译和测试这个流程。如果你需要这些代码,可以在Game Center extension project里找到。
15. 使用第三方类库
如果你正在扩展里使用一个第三方类库(比如在Flurry extension里的Flurry统计类库),你需要在编译的时候使用“-platform iPhone-ARM” 参数来引用这个类库。
16. 你可能需要使用platform.xml
如果你会用到任何一个但不是大多数的iOS SDK类库,你需要创建一个platform.xml文件来指明你需要使用的类库,以及应用所需要的最小iOS版本。我为每一个扩展都创建了一个platform.xml文件,因为在使用AIR3.1编译时会出现一个有关未知最小iOS版本的警告,使用这个文件会隐藏这个警告。
—————–
打包应用
—————–
17. 如果IDE编译的时候并不依赖原生扩展,则你的应用需要引用扩展替身swc来保证运行成功
这个SWC里包括了一整套与原生扩展相同的Actionscript接口,所以你可以使用它进行编译,并且在开发的时候用来测试。当然,不依赖原生扩展的IDE不会正确地发布移动应用,但你可以用我介绍过的那种批处理编译脚本来实现最终的正常编译。
18. 发布AIR应用的时候,指明需要引用的iOS SDK地址
默认情况下,AIR编译器会使用iOS SDK 4.0来编译应用。如果你使用了这个版本里所不包括的新功能,则编译的时候就会出错。这时需要指明iOS SDK的新版本位置,从而实现对新功能类库的引用。在这篇文章中查看详细信息。在Flash Builder里,在配置原生扩展的某个面板中可以进行这个设置,但如果你使用命令行来编译,可以使用-platformsdk标签来指定iOS SDK的路径。
19. ld: warning: ARM function not 4-byte aligned
在编译应用的时候你可能会遇到多处下面这样的警告:
ld: warning: ARM function not 4-byte aligned
这些只是警告,不用去理它。4位对齐只是一个优化,并非是必须的。
—————–
最后的最后
—————–
20. 让你的原生扩展更加通用
当完成了扩展的开发,你可以有三个选择:
1, 只让自己使用。
2, 向其他开发者开源。
3, 卖给其他开发者。
你可以问问自己,是什么让你的应用独一无二。如果原因不是你的原生扩展(实际上很少是因为这个),那么请选择第二个或者第三个,如果每个人都这么做,你也会从中受益。
另外,让更多人从你的扩展中受益,可以让Adobe AIR这项技术在移动开发领域里更加强大和稳定。这会鼓励其他的开发者去使用AIR,也会鼓励Adobe继续开发和改进它。
在Stick Sports我们选择了第二项,因为比起花时间来运营我们的原生扩展,我们更愿意花时间来运营和支持我们的游戏。