In-App Purchase通信结构设计

9 2011 In: Flash/Flex Mobile Dev, iOS, Mobile Dev

ipa-通信设计

  1. iOS App 向 Developer Server 发送请求,获得一份产品列表(一般都是 Product ID)。
    获取产品列表需要 iOS App 主动获得,这样就可以在不升级iOS的情况下添加产品。
  2. Developer Server 返回给 iOS App 包含 Product ID 的列表。
  3. iOS App 向 App Store 发送请求,期望获得到产品的信息。
  4. App Store 返回本地化产品信息。
    所谓本地化的产品信息指的是会根据目前所在的地区返回所在地区的描述信息。
    比如在中国地区,如果该产品有中文的描述,返回中文的描述,
    而如果你在美国,则返回的是英文的描述。
  5. iOS App 把返回的产品信息显示给用户(iOS App 的 Store 界面)
    这个就是商店界面了,包括,在前面请求希望获得产品信息的时候的等待界面。
  6. 用户选择某个产品。
  7. iOS App 向 App Store 发送支付请求。
  8. App Store 处理支付请求并返回交易完成信息。
  9. iOS App从返回交易完成的信息中获得数据,并发送至 Developer Server。
  10. Developer Server 记录数据,并进行审查。
    App Store Server 对于消耗型的商品,是不会保存购买记录的,所以需要 Developer 同步记录到 Developer Server 上。
    App Store Server 对于非消耗性的商品,在 App Store Server 是有记录可以查询的,可以通过 Restore 的方法恢复。
    而恢复的交易信息是新的,但是包含原始的交易信息。
    因此用户试图购买已经买过的非消耗性的商品时,iOS App 收到一个常规的交易信息,而不是恢复的交易信息,
    只不过用户不会被再次付费。因此程序应该把这类交易和原始的交易同等对待。
    其他订阅型的暂时没有测试。
    Developer Server 这边需要做逻辑的严格审查,看是否合理。
  11. Developer Server 将数据发给 App Store来验证该交易的有效性。
  12. App Store对收到的数据进行解析,返回该数据和说明其是否有效的标识。
    App Store 有效性的验证地址会根据是测试还是实际购买有所不同
    测试:也称为Sandbox环境 https://sandbox.itunes.apple.com/verifyReceipt
    实际:https://buy.itunes.apple.com/verfyReceipt
  13. Developer Server 读取返回的数据,确定用户购买的内容。
  14. Developer Server 将购买的内容传递给 iOS App。
  15. iOS App 根据购买最早的结果进行处理。

上面为目前比较通用的In-App Purchase通信结构设计的做法,粗体部分为注意事项。

分享到新浪微博 分享到人人网 分享到豆瓣 分享到鲜果 分享到百度空间 分享到开心网 QQ书签 分享到YAHOO! 分享到Google Google Buzz 分享到Facebook 分享到Plurk Digg delicious Technorati Twitter

Running Panda (熊猫来了)是第一款跨平台技术游戏,使用 Adobe Flash (adobe air) 技术,一次开发就能够在 IOS (iphone itouch ipad ) 系统,Android系统,PC 平台,BlackBerry® PlayBook,BlackBerry Tablet OS 等多个平台运行,即将在这周发布到 Google Market 和苹果 App Store。同时也将登陆 PC 平台和国内各大 App Store。这款游戏的开发让人们看到了flash移动端开发技术广阔的市场前景。
这款游戏开发的作者就是本人。

iTunes下载地址:http://itunes.apple.com/us/app/running-panda/id446065241
APK下载地址:http://www.appchina.com/soft_detail_127151_0_10.html

随着Air2.6大面积推广,Adobe毫不忌讳的踏入了移动领域。在苹果手机和安卓手机大肆PK的今天,平台市场和内容市场也新兴而起,笔者也拿起了笔,不对,准确的说是键盘和鼠标,来尝试一下,如何用熟悉的ActionScript3来开发一款可以跨平台的游戏。

打开Flash Builder 发现新建里多了两个清新的选项,那就传说中的手机项目,新建后发现和普通项目并没有什么不同,只是多了一个主类同名的XML文件,用他可以配置一些手机上的特性,比如开关GPU,比如横屏锁定等等,除了这个几乎和别的AS项目没有任何不同的地方,感觉完全没有任何门槛,只能一个字来表示,那就是:刺激。

在移动平台中开发思路上可能会有些变化,但是总体上没有任何问题,以下是我开发收集的一些经历,比如我们习惯性用键盘按键来发射子弹,但是平板手机中是没有键盘的,所以改成了触屏,而这在PC上表现为鼠标点击,所以实现就变得通俗容易,并且测试的时候也是用鼠标点击,在细节上会有些变化,比如按钮的划过状态在手机上消失,因为手机上快走指针,只有点击,同理监听MouseMove事件的时候 不用再判断是否MouseDown 因为在手机上不可能在未Down的情况下促发Mouse事件,这些都是一些细节上的不同,但是在实现上方案和传统的一样容易,所以为移动所付出的额外代价只是这些细节,如果你开发3个平台以上的话,那么这些细节需要多多考虑,但是比起重新开发三个版本,那这成本几乎是可以忽略不计的。所以还是那两个字:爽。

启动游戏后,在手机上运行了下,效果没有想象的好,FPS一路走低,由于AS3的所有事件都是被异步优化后基于Frame来执行的,所以虽然理论上帧率过了24就可以消除卡的感觉,但是24fps状态下的操作延迟将近40多毫秒的延迟手感和体验都是比较差的,特别是对于动作游戏,如果你是策略的菜单游戏,那么24基本就可以接受了。但如果要做动作游戏,还是要达到普通人类下意识反应速度18毫秒以内,也就是55fps以行。那么优化也是一个非常大的问题,其实很多朋友会把过多的优化思考在变量的多少或者对象的GC上,其实他只是内存优化,而帧率的根本问题还是画面重绘。AS3是非常高级的语言,我们不需要太多低级的操作方法,只需要在画面上让重绘区域尽量减少,让重绘区域中的层数尽量维持在最少的图层,并且全部都使用位图,如果担心文件体积过大,可以导入矢量素材,用bmp来转换成位图也是一个很好的方法,当然手机资源有限一定要注意释放。经过以上基本简单的优化和设计上的规避,笔者的第一款游戏成功的达到了55fps以上,当我看到帧率发生了如此明显的变化后,我真是激动不已,如果你有兴趣的话,也马上动手来试一试把。

由于商业目的熊猫暂时还没有开源,但如果你研究Flash时间很长,如何拿到源码你懂的。
届时您就可以看到源码中是不是如您所说另有技巧。文章只是抛砖迎玉,并非手把手的教学贴。

熊猫的重绘实现100%只使用了三个系统API
bitmap.bitmapData = someBitmapData;
displayObject.x = someValue;
displayObject.y = someValue;

关键技巧并不在与代码本身,或者有一些鲜为人知的API,而在与实现的方法和思路。

分享到新浪微博 分享到人人网 分享到豆瓣 分享到鲜果 分享到百度空间 分享到开心网 QQ书签 分享到YAHOO! 分享到Google Google Buzz 分享到Facebook 分享到Plurk Digg delicious Technorati Twitter

原文链接:
AIR Native Extension实现iOS应用内付费(In-App Purchase)全教程(四)——ANE面向IAP的测试和开发

本文的内容如下:

  • 在Native扩展中使用StoreKit框架
  • ActionScript扩展
  • ANE-IAP开发实例分享

本文用到的工具和设备如下:
Flash Builder 4.5
Flex SDK 4.5.1
Flash Professional CS5.5
AIR SDK 3.0
Xcode 4.1 + iOS SDK 4.3
iPad 1

本文例子中的Objective-C部分和AS扩展类库部分的代码作者为我的同事Saumitra Bhave
———————————————————————————–
在Native扩展中使用StoreKit框架

下载安装XCode 4和iOS SDK之后,让我们先来了解一下苹果原生类库是如何处理应用内付费功能的。iOS SDK中有一个框架叫做StoreKit,它负责应用程序和应用商店的业务流程。StoreKit中有一些负责具体功能的类,商品的请求,请求结果,结果回调,购买,购买队列等都由不同的类来完成。
StoreKit的业务流程
如上图所示,StoreKit解决内付费业务的大体流程可以概括成这样,SKProductsRequest向商店发出请求获得商品信息,商店通过回调函数SKProductsRequestDelegate把请求的结果SKProductsReponse传了回来,如果用户选择购买商品,则创建一个SKPayment实例到购买队列SKPaymentQueue中,然后通过回调SKPaymentTransactionObserver来返回购买的结果。

我现在拿请求商品信息的部分来举例说明一下:

SKProductsRequest* req = [[SKProductsRequest alloc] initWithProductIdentifiers:pids]; 
	req.delegate = observer;
	[req start];

上面的Objective-C的代码如果转译成ActionScript 3.0,相当于这个意思:

var req:SKProductsRequest = SKProductsRequest.initWithProductIdentifiers(pids);
req.delegate = observer;
req.start();

SKProductsRequest继承于父类SKRequest,通过静态方法initWithProductIdentifiers和参数pids创建了一个实例req,参数pids是一个数组,列出了需要请求的内付费商品ID。req通过start方法向商店发出请求,并在发出请求的动作之前给自己注册了一个回调函数observer。

observer是SKProductsRequestDelegate的实例,回调接口如下:

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response;

转译成AS是如下的代码:

function productsRequest(request:SKProductsRequest, response:SKProductsResponse):void;

其中response就是请求的结果。

下面是一个完整的Objective-C函数体:

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
	NSLog(@"Products Received");
	NSMutableString* retXML = [[NSMutableString alloc] initWithString:@""];
	for (SKProduct* p in response.products) {
		[retXML appendFormat:@"%@%@%@%@%@",p.localizedTitle,p.localizedDescription,p.price,[p.priceLocale localeIdentifier],p.productIdentifier];
	}
	[retXML appendFormat:@""];
	for(NSString* s in response.invalidProductIdentifiers){ 
		[retXML appendFormat:@"%@",s];
	}
	[retXML appendFormat:@""]; 
	FREDispatchStatusEventAsync(g_ctx, (const uint8_t*)"productsReceived", (const uint8_t*)[retXML UTF8String]);
	[retXML release];
	[request release]; 
}

这里主要实现的是将结果格式化成一个XML流,然后通过派发事件传回给AS扩展类,注意这里派发事件用的是FREDispatchStatusEventAsync方法,它定义在FlashRuntimeExtension.h内部,前文我介绍过,这是负责与AS扩展类通信的类。

在AS类包中,通过注册的StatusEvent来侦听这个事件,并从e.level中取得XML流里的商品信息。

ext.addEventListener(StatusEvent.STATUS,onStatus);
...
function onStatus(e:StatusEvent):void{
     switch(e.code){
          case "productsReceived":
          var xml:XML = new XML(e.level);
          ......
     }
}

购买的业务流程和请求信息的流程十分相似,这里我不一一介绍,大家可以在最后下载项目的代码来查看。
———————————————————————————
ActionScript扩展

在Saumitra提供的ANE扩展类中,AS部分的结构是这样的:
com.adobe.nativeExtensions.AppPurchase;
com.adobe.nativeExtensions.AppPurchaseEvent;
com.adobe.nativeExtensions.Base64;
com.adobe.nativeExtensions.Product;
com.adobe.nativeExtensions.Transaction;

其中AppPurchase负责业务流程以及与Native扩展的接口,AppPurchaseEvent定义了各种StatusEvent的状态,Product和Transaction定义了数据模型,Base64负责为参数转码。整个扩展类库简单易懂,我会在下面的项目实例中介绍其中用到的一些方法。
———————————————————————————–
ANE-IAP开发实例分享

最后总结本系列教程所有的知识来做一个例子。
我首先做的准备是在iTunesConnect中创建了一个新的应用,并新建了四个内付费商品:plane(非消耗型),diary(非消耗型),bottle(消耗型),key(消耗型)。我希望在iPad的沙箱环境中测试以下的业务流程:
请求商品信息,购买消耗型和非消耗性商品,恢复非消耗型商品的购买状态,如果都成功则我的应用调试成功。

分析一下这个应用的UI需求,我需要一个按钮来触发请求商品信息的动作,然后需要一个列表来显示商品信息,接下来需要给每个商品添加一个购买的按钮。由于iPad上无法用trace等debug方法调试,所以我还需要一个监测的窗口来打印所有的流程信息。

下面是该应用的截屏:
请求商品列表
图2 请求商品列表
显示商品信息
图3 显示商品信息
恢复非消耗型商品的购买状态
图4 恢复非消耗型商品的购买状态
购买新的消耗型商品
图5 购买新的消耗型商品
输入测试用户密码
图6 输入测试用户密码
购买成功
图7 购买成功

资源:
实例ANE-IAP(包括AS扩展类,Native扩展类)下载

如何使用本例:
开发者需要使用自己的证书和设备来打包和发布,有关如何打包ANE和如何发布IPA,我已经在这个系列教程的前文提到过了,本文不做重复介绍。

注意事项:
1,本例使用Flash Professional作为Compiler,使用Flash Builder作为代码编辑IDE,请在Flash Professional的发布设置中选择Flash Player,并在发布的时候忽略这个错误: VerifyError: Error #1014: Class flash.external::ExtensionContext could not be found。直接使用生成的SWF即可。

2,在iPad上测试之前务必要先注销已经登陆的苹果帐号,注销方法为,进入系统偏好设置,在左边列表内点击Store图标,然后点击在右侧出现的帐号,再在弹出的窗口中点击”注销“。

3,如果你没有用过XCode,不知道如何发布OBJC项目,请在安装XCode之后打开下载的Native扩展包里的AppPurchase.xcodeproj文件,项目打开后按Command+B,在左边项目资源列表的Products文件夹内会生成一个.a文件,右键点击后可以在Finder中找到这个文件。

总结:
本文所提供的例子,只是应用内付费的入门,如果要做真正的产品,你需要搭建自己的服务器用来验证购买商品的收据,以及在本地记录商品的使用状态并与服务器同步等等。这些知识不是本文的重点,这里不做详细介绍,感兴趣的朋友可以和我做进一步的探讨。谢谢各位!

分享到新浪微博 分享到人人网 分享到豆瓣 分享到鲜果 分享到百度空间 分享到开心网 QQ书签 分享到YAHOO! 分享到Google Google Buzz 分享到Facebook 分享到Plurk Digg delicious Technorati Twitter

原文链接:
AIR Native Extension实现iOS应用内付费(In-App Purchase)全教程(三)——iOS应用内付费简介和准备流程

本文的主要内容如下:

  • IAP简介
  • 商品与交易
  • 测试IAP的准备流程

————————————————————————————
IAP简介

IAP的全称是In-App Purchase,应用内付费。这种业务模式允许用户免费下载试用,对应用内提供的商品选择消费,比如购买游戏道具,购买游戏等级等等。相比完全收费的应用而言,应用内付费给用户试用的机会,不会让优秀的应用因为缺乏用户的认知而丧失消费者;而且对于开发商,也不需要为了让用户试用而单独发布一款免费的精简版本。

————————————————————————————
商品与交易

苹果官方的关于IAP的帮助文档是只对注册开发者开放的,所以我不方便把它转载在这里,但我可以对IAP里的关键因素做一个通俗易懂的介绍。

IAP里有两个关键的词,商品(Product)和交易(Transaction)。
商品可以是一种虚拟的道具,一个隐藏的关卡或者地图,但必须是直观的,可以让用户购买后直接获益的产品。IAP的商品从消费性质上分为四种:

1,消耗型商品,比如游戏道具,子弹,药品等等。由于这类商品可以被消耗,所以支持重复购买。苹果应用商店不保存此类商品的购买记录,如果要保存则需要开发者同步到自己的服务器上。

2,非消耗型商品,比如游戏关卡,隐藏地图等等。这类商品只要购买一次便可以了,苹果应用商店里每一个用户对非消耗型商品的购买都有记录,可以在不同的设备上恢复购买状态,这个恢复的过程叫做Restore。

3,自动重置型订阅,比如电子杂志,读物等。消费者购买这类商品时会从列表中选择一个有效期限,卖家在定义商品的时候从一群固定的选项中选择添加一个有效期,比如7天,一个月,两个月。过了有效期之后,商品的购买状态会被自动重置成未购买,要想继续获得内容则需要再次订阅。这种类型的商品和非消耗型商品一样,会在苹果商店内保存购买记录。

4,非自动重置型订阅,比如用户订阅电子杂志和读物报刊时需要从自定义的期限列表中选择期限,而不是苹果提供的固定选项,比如9天,一个半月或任意时间。在这种情况下,苹果商店无法根据期限来控制订阅的到期行为,所以一切都需要开发商自己编写相应的逻辑来实现。

交易是指用户对一个商品的购买行为,当用户点击购买一件商品时,一个新的付费行为就被添加到付费队列中,付费队列是一条系统线程,即使应用程序终止仍然会继续执行。

————————————————————————————
测试IAP的准备流程

如果你是一个注册的苹果开发者,接受了最新的苹果开发者协议,并且签署了iOS付费应用合同,那么你就可以继续IAP的测试了。

如果此时你对iOS的开发流程不是很熟悉,在阅读下面的内容之前,我强烈建议你先看看我的这几篇文章:
如何成为一个合法的iOS开发者
如何使用iOS开发者授权以及如何申请证书
如何为iTunes Connect准备应用

如果你已经注册成为苹果开发者,并且熟知了如何给设备授权,如何申请证书,如何发布应用,那么请继续阅读我下面的内容:

使用未越狱的设备
测试IAP的项目不能使用越狱的设备,否则会出现无法连接到应用商店的错误。恢复设备到未越狱的系统后,登陆Provisioning Portal添加设备的UID。

使用没有通配符的App ID
在定义App的Bundle ID的时候,我曾经介绍过可以使用类似 com.jamesli.* 这样的值来覆盖多个应用的ID。这种定义方式不能用在打算使用IAP的应用上面,定义IAP的应用必须使用唯一的ID,如com.jamesli.ghostbride。如果正确定义了,应用的In-App Purchase的功能是默认开启的,如下图:

在iTunesConnect创建应用
登陆iTunesConnect,创建一个新的应用,即使该应用尚未开发,也可以用一些假的文字和图片来代替,创建好之后切记要点击Ready to Upload binary将应用的状态变为Waiting for upload。

管理In-App Purchase商品
在应用列表中点击新创建的应用图标,进入应用首页,在右面的一行按钮中选择Manage In-App Purchase,进入内付费商品管理页面。通过点击左上角的Create New按钮可以进入商品页面选择创建一个新的商品。页面中显示的四种商品分别是我在本文介绍过的四种商品,消耗型商品(Consumable),非消耗型商品(Non-Consumable),自动重置型订阅(Auto-Renewable Subscriptions),非自动重置型订阅(Non-Renewing Subscription)。

以消耗型商品为例,点击Select进入创建页面。
Reference Name是商品名字,这不是最终用户会看到的名字,而是会在内付费管理的商品列表中显示的字符,类似于变量名。
Product ID是商品的唯一标识,这个ID十分重要,在编写应用程序的时候会用它来识别改商品。

接下来是为不同的语言定义该商品的显示名称,最终用户看到的就是这个名称。定义好名称后是为商品定价以及上传缩略图,这个商品就算是定义完了。如下图,定义完成的商品会显示在内付费管理的商品列表中。每一个内付费商品的创建和修改都需要提交审核,但这里需要注意的是,在一个新的应用版本内创建的内付费商品,必须和这个应用版本一起提交审核,而在该应用版本通过审核之后再为它创建的内付费商品,可以通过这个列表中的Ready to submit按钮来提交。
product-iap

刚刚创建好的内付费应用,已经可以用来调试了。

使用测试帐号调试应用

苹果应用商店是一个交易环境,任何用户可以在这个环境内购买应用,但如果要测试正在开发过程中的应用内付费,我们不能在真正的苹果商店里进行。苹果给开发者提供了一个用于调试购买行为的测试沙箱,它完全复制了应用商店的交易环境,但在沙箱环境中我们不能用平常的苹果帐号,而是需要用测试帐号。

在iTunesConnect的首页可以点击Manage Users进入用户管理页面,然后选择Test User来创建测试帐号。创建测试帐号可以使用一个不存在的Email地址,但是密码必须是符合规范的。这里创建的帐号可以用来购买开发过程中的应用内付费,但必须记住,测试帐号不能用来登陆真正的应用商店并在产品环境中进行购买行为,否则你的iTunes帐号将有可能被停用。

分享到新浪微博 分享到人人网 分享到豆瓣 分享到鲜果 分享到百度空间 分享到开心网 QQ书签 分享到YAHOO! 分享到Google Google Buzz 分享到Facebook 分享到Plurk Digg delicious Technorati Twitter

原文链接:
AIR Native Extension实现iOS应用内付费(In-App Purchase)全教程(二)——AIR面向iOS设备的原生扩展

本文的主要内容如下

  • AIR Native Extension介绍
  • ANE的组成部分
  • ActionScript 3.0扩展
  • Objective-C 扩展
  • 使用ADT打包ANE
  • 使用ADT打包IPA

————————————————————————————
AIR Native Extension介绍

AIR Native Extension (ANE)是AIR 3.0的一项重要特性,简单的说,它允许AIR应用程序通过扩展文件与原生应用程序类库相互通讯,从而让AIR应用实现一些只有原生程序才可以做到的功能。
在ANE出现以前,移动平台上的AIR对系统的访问非常有限,功能的实现都是封装在封闭的,由Adobe定义好的ActionScript 3.0 API内,比如Accelerometer, GeoLocator等AS类。ANE则将AIR彻底开放出来,AIR不再针对具体的功能提供封闭的API,而是允许开发者通过AIR的扩展机制自由调用使用原生语言开发的类库。这样可以让AIR应用程序享有与原生应用程序同等的机会,其意义对Flash技术来说是划时代的。
————————————————————————————
ANE的组成部分

ANE支持向Windows、Mac OSX、Android和iOS各个平台原生应用程序的扩展,本文只针对iOS平台进行介绍。在iOS平台中,ANE的组成部分基本分为ActionScript 3.0扩展类库和Objective-C原生扩展类库两个部分,这两个部分打包后生成AIR扩展文件(.ane),最后和AIR应用程序一起打包成iOS原生应用IPA文件。如下图所示。

ANE的组成部分

图1 ANE的组成部分
————————————————————————————
ActionScript 3.0扩展

ANE的AS扩展部分是一个SWC,AIR 3.0 SDK里为flash.external.ExtensionContext类添加了新的方法。如下例所示:

import flash.external.ExtensionContext;
...
private var ext:ExtensionContext;
...
ext = ExtensionContext.createExtensionContext("com.adobe.appPurchase","");

在这个例子里,ExtensionContext通过静态方法createExtensionContext()来获得一个实例,参数com.adobe.appPurchase是这个扩展的ID,它非常重要,在扩展的配置文件里和应用程序描述文件中都需要用这个ID进行配对。

调用原生类中定义的方法可以用方法call()来实现,由于是同步调用,所以函数可以有返回值。如在原生类中定义的方法finish,可以用下面的代码来调用。

var result:Object = ext.call("finish");

我们还可以给ExtensionContext类添加事件侦听,用来获取从原生类中派发回来的事件。

ext.addEventListener(StatusEvent.STATUS,onStatus);
public function onStatus(e:StatusEvent):void{ 
	switch(e.code){
             case "removeTransaction":
             ...
        }
}

————————————————————————————
Objective-C 扩展
接下来是原生类的部分,如果你注册成为苹果iOS开发者,那么你可以在苹果开发者网站上免费下载Object-C的开发工具XCode。关于如何注册成为苹果iOS开发者,请参考我的这篇文章,如何成为一个合法的iOS开发者

总的来说,Objective-C 虽然语法比较奇怪,但只要掌握了基本的规则,还是和ActionScript一样易懂。OBJC扩展类需要引入一个FlashRuntimeExtension.h类包,它实现了和ActionScript沟通的接口。

引入FlashRuntimeExtension.h之后,可以用下面的代码定义一个FREObject方法,FREObject是接口类型。这里要注意,与AS的接口包括函数返回值,都要定义成FREObject类型,比如代码中的retVal。

FREObject finishTransaction1(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
	NSLog(@"Finish Transaction Called");
	BOOL matchFound = NO;
	const uint8_t* str = nil;
	uint32_t len = -1;
	......
	FREObject retVal;
	if(FRENewObjectFromBool(matchFound, &retVal) == FRE_OK){
		return retVal;
	}else{
		return nil;
	}
}

要把FREObject方法定义成接口,还需要在ContextInitializer方法内进行配置,如下:

//这里是需要定义的接口的数量
*numFunctionsToTest = 6;
 
//定义一个FRENamedFunction类型的实例func,初始化函数的个数
FRENamedFunction* func = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)*6);
 
//定义一个接口,name是字符串"getProducts",函数体是getProducts
func[0].name = (const uint8_t*)"getProducts";
func[0].functionData = NULL;
func[0].function = &getProducts; 
 
func[1].name = (const uint8_t*)"startPayment";
func[1].functionData = NULL;
func[1].function = &startAppPayment; 
 
func[2].name = (const uint8_t*)"finish"; 
func[2].functionData = NULL;
func[2].function = &finishTransaction1;
 
func[3].name = (const uint8_t*)"muted"; 
func[3].functionData = NULL;
func[3].function = &muted;
 
func[4].name = (const uint8_t*)"restore"; 
func[4].functionData = NULL;
func[4].function = &restoreTrans;
 
func[5].name = (const uint8_t*)"trans"; 
func[5].functionData = NULL;
func[5].function = &getTrans;
 
*functionsToSet = func;
....

而ContextInitializer方法,是在原生扩展类的初始化函数ExtInitializer中指定的:

void ExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, 
					FREContextFinalizer* ctxFinalizerToSet) {
	NSLog(@"Extension Initialized");
	*extDataToSet = NULL;
	*ctxInitializerToSet = &ContextInitializer;
	*ctxFinalizerToSet = &ContextFinalizer;
}

ExtInitializer是原生扩展的程序入口,它可以通过扩展配置文件extension.xml来定义:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<extension xmlns="http://ns.adobe.com/air/extension/2.5">
  <id>com.adobe.appPurchase</id>
  <versionNumber>1</versionNumber>
  <platforms>
    <platform name="iPhone-ARM">
            <applicationDeployment>
                <nativeLibrary>libAppPurchase.a</nativeLibrary>
                <initializer>ExtInitializer</initializer>
                <finalizer>ExtFinalizer</finalizer>
            </applicationDeployment>
        </platform>
  </platforms>
</extension>

我介绍的这个顺序,实际上就是实际程序编写的思路,先确定接口,再实现连接。 也许有朋友和我一开始接触OBJC的时候一样,对这些代码一头雾水。没有关系,在这篇教程里我只是对流程做简短的介绍,具体的代码解析会在本系列的最后一篇教程里做更详细的讲解。那么接下来让我来介绍下一个部分,打包扩展。
————————————————————————————
使用ADT打包ANE

在图1中,我介绍了.ane文件的组成,它包括了AS类库(.swc)和原生类(.a)两个部分,以及刚才我们介绍的这个扩展配置文件extension.xml。那么要打包ane我们还需要哪些文件呢?
打包ANE所需要的文件
图2 打包ANE所需要的文件

如图2所示,所选择的文件以及文件夹就是打包ANE所需要的所有文件,它包括:
1,AIR SDK打包应用程序和类库(bin,lib)
2,ActionScript扩展类包.swc,如图ANE_IAP_ASLib.swc
3,ActionScript扩展类包.swf,如图library.swf,可以通过将SWC的文件扩展名改成ZIP后解压缩得到。
4,Objective-C扩展类包.a,如图libAppPurchase.a,可以通过在Xcode中编译项目得到。
5,扩展配置文件XML,如图extension.xml
6,一个打包证书,如图selfsigned.p12,可以通过Flash CS5的AIR发布设置生成。

一切就绪后便可以使用命令行进行打包,注意路径,下例路径为当前文件夹。

bin/adt -package -storetype pkcs12 -keystore selfsigned.p12 -storepass 1234 -target ane ext/InApp.ane extension.xml -swc ANE_IAP_ASLib.swc -platform iPhone-ARM library.swf libAppPurchase.a

————————————————————————————
使用ADT打包IPA

.ane文件打包成功后,便可以用来打包IPA文件,也就是iOS应用程序包。如果你对开发iOS应用的必要流程还不很清楚,请参阅我的这篇教程,如何使用iOS开发者授权以及如何申请证书。我以前介绍过如何用Flash Professional CS5打包IPA,今天主要介绍如何用AIR SDK的打包工具ADT来生成含有ANE扩展的IPA。

使用ADT生成含有ANE扩展的IPA所需要的文件
图3 使用ADT生成含有ANE扩展的IPA所需要的文件

如图3所示,所选择的文件就是生成IPA的必要文件:
1,应用程序文件SWF,如图是ANE_IAP_Example.swf。
2,开发者设备授权文件.mobileprovision,如图是ghostbride_dev.mobileprovision。
3,开发者签名证书文件.p12,如图是jameslidevelopment.p12。
4,应用程序描述文件XML,如图是info-app.xml。
5,扩展包路径,如图是ext
6,如果应用程序有图标图片,还需要图标文件夹,如图是icon

在应用描述文件XML中,需要对扩展追加一个定义:

<extensions>
    <extensionID>com.adobe.appPurchase</extensionID>
</extensions>

这里可以看到,在AS扩展类、扩展配置文件extension.xml和应用描述文件info-app.xml中都指定了一个统一扩展的ID: com.adobe.appPurchase。

利用下面的命令行可以打包生成Main.ipa:

bin/adt -package -target ipa-test-interpreter -provisioning-profile ghostbride_dev.mobileprovision -storetype pkcs12 -keystore jameslidevelopment.p12 -storepass 1234 Main.ipa info-app.xml ANE_IAP_Example.swf -extdir ext icon
分享到新浪微博 分享到人人网 分享到豆瓣 分享到鲜果 分享到百度空间 分享到开心网 QQ书签 分享到YAHOO! 分享到Google Google Buzz 分享到Facebook 分享到Plurk Digg delicious Technorati Twitter