4399支付SDK供flash游戏使用ANE的使用
这两天对Flash游戏如何去接入android平台的SDK做了下研究,做了4399的支付SDK接入的工作,这里与大家分享下。
一、ANE的介绍
(网络描述也是一大堆,这里描述摘自http://blog.csdn.net/myquark/article/details/7904030)
Adobe AIR Native Extension,Adobe AIR的本地扩展,简称ANE。什么叫本地扩展?因为Adobe AIR是跨平台的一个运行时,可以在Windows,Mac,Android,iOS等系统上跑,正是因为其跨平台,所以它本身的功能就有局限性,不可能面面俱到;换句话来说,比如我们想在flash程序中调用一下系统的消息通知功能,但是AIR并没有这个功能,那么怎么办?这就要根据本地平台写段代码,让AIR委托本地平台去执行这段代码,这样就达到了拓展AIR程序的功能。换个角度来看问题,就好像系统有个dll文件,AIR可以去直接调用这个dll文件(这只是一个比方而已,让大家更容易理解,实际上AIR不能直接调用dll文件)。我们可以开发一个Android手机振动程序,然后打包成ANE,这样运行在AIR中的程序就可以调用写好的手机程序了。有了ANE机制,我们就可以开发很多Flash无法完成但是却可以使用的功能。
二、ANE开发步骤
ANE的生成需要两个步骤,一个是生成本地的jar包,一个生成SWC库文件,最后进行编译合成。
本文开发工具为fb 4.7 与eclipse为主
1、创建ane Android项目,生成本地jar包
准备工作
1)在eclipse中创建一个android的项目,假定命名为4399PaySDKANE_JAVA;
2) 将需要依赖的包(4399PaySdk.jar和FlashRuntimeExtensions.jar)添加到项目的libs目录下。
3)在项目属性中-java build path-Libraries下,添加以下
4399PaySdk.jar(4399的支付sdk包,在http://opensj.4399api.net/dev/downloadExchange可以下载到)
FlashRuntimeExtensions.jar(该包在E:\softinstall\ADOBE\Adobe Flash Builder 4.7\sdks\4.6.0\lib\android可找到)
4)在项目属性 - Java Build Path - Order and Export 下,将游戏 SDK 及其依赖的 JAR 包(4399PaySdk.jar)打上勾,确保能够被输出到生成的 JAR 包中;
准备工作有些多哈。接下来正式进入开发。
编码部分:
1、编写 FREContext 的派生类(YJPaymentApiContext.java)
package com.sj4399.pay.ane;import java.util.HashMap;import java.util.Map;import com.adobe.fre.FREContext;import com.adobe.fre.FREFunction;public class YJPaymentApiContext extends FREContext { @Override public void dispose() { } @Override public MapgetFunctions() { return null; }}
空的文件先不管。
2、编写 FREExtension 的派生类(如:YJPaymentApiExtension),在 createContext 方法中创建 YJPaymentApiContext的实例,并作为该方法的结果值返回。
package com.sj4399.pay.ane;import com.adobe.fre.FREContext;import com.adobe.fre.FREExtension;public class YJPaymentApiExtension implements FREExtension { @Override public FREContext createContext(String arg0) { // TODO Auto-generated method stub return new YJPaymentApiContext(); } @Override public void dispose() { // TODO Auto-generated method stub } @Override public void initialize() { // TODO Auto-generated method stub }}
3、编写一系列 FREFunction 的派生类(如:YJFInit,YJFLogin……等),以实现每一个接口,每个接口方法用一个 FREFunction 派生类实现;
以YJFInit.java为例
package com.sj4399.pay.ane;import com.adobe.fre.FREContext;import com.adobe.fre.FREFunction;import com.adobe.fre.FREObject;import com.sj4399.pay.YjPaymentApi;public class YJFInit implements FREFunction { private static final String TAG = "YJFInit"; @Override public FREObject call(FREContext context, FREObject[] args) { YJPaymentApiContext yjac = (YJPaymentApiContext)context; YjPaymentApi.getInstance().init(yjac.getActivity()); return null; }}
我们通过
context.dispatchStatusEventAsync(callbackString, "");
进行回调给as3端。编写完其他接口类即可。
4、修改 YJPaymentApiContext的 getFunctions 方法,将实现的每一个 FREFunction 派生类添加到函数集合中,该函数集合作为该方法的结果值返回;此函数集合即承担接口调用职责
package com.sj4399.pay.ane;import java.util.HashMap;import java.util.Map;import com.adobe.fre.FREContext;import com.adobe.fre.FREFunction;public class YJPaymentApiContext extends FREContext { @Override public void dispose() { } @Override public MapgetFunctions() { Map mapFunc = new HashMap (); mapFunc.put("getUser", new YJFGetUser()); mapFunc.put("charge", new YJFCharge()); mapFunc.put("destoryLogin", new YJFLogout()); mapFunc.put("openLogin", new YJFLogin()); mapFunc.put("init", new YJFInit()); return mapFunc; }}
5、编写 ant 配置文件 build.xml,编译导出 JAR 包
这样就完成了本地jar包的生成工作了。
2、创建flex库项目,生成swc库
准备工作:
1)创建项目
2)属性设置
编码部分:
这边使用单例模式,创建actionscript代码
package com.sj4399.pay.ane{ import flash.events.EventDispatcher; import flash.events.IEventDispatcher; import flash.events.StatusEvent; import flash.external.ExtensionContext; public class YjPaymentApi extends EventDispatcher { public static const EXTENSION_ID:String = "com.sj4399.pay.ane.android"; private var _context:ExtensionContext; private static var _instance:YjPaymentApi; public static function getInstance():YjPaymentApi{ if(_instance == null){ _instance = new YjPaymentApi(); } return _instance as YjPaymentApi; } public function YjPaymentApi(target:IEventDispatcher=null) { _context = ExtensionContext.createExtensionContext(EXTENSION_ID,null); if(_context == null){ trace("YjPaymentApi(.as) constructor: _context is null,please call 'init()' first!"); } _context.addEventListener(StatusEvent.STATUS,onStatus); super(target); } /** * SDK初始化 */ public function init(){ _context.call("init",null); } /** * 登录 */ public function openLogin(){ _context.call("openLogin",null); } /** * 注销 */ public function destoryLogin(){ _context.call("destoryLogin",null); } /** * 充值 * amount 充值金额 * server 分服标识 * mark 拓展标记 */ public function charge(amount:int,server:int=0,mark:String=null){ _context.call("charge",amount,server,mark); } /** * 获取用户信息*/ public function getUser():String{ return String(_context.call("getUser")); } private function onStatus(e:StatusEvent):void{ //trace("received status event:"+e.toString()); var eventObject:Object = JSON.parse(e.code); var evt:PayCallbackEvent = new PayCallbackEvent(Constants.EVENT_TYPE_4399PAYSDK_CALLBACK, eventObject.callbackType, eventObject.code, eventObject.data); this.dispatchEvent(evt); } }}
2、编写PayCallbackEvent
package com.sj4399.pay.ane{ import flash.events.Event; /** * 支付SDK回调事件 */ public class PayCallbackEvent extends Event { private var _eventType: String; private var _callbackType: String; private var _code: int; private var _data: Object; public function PayCallbackEvent(eventType:String, callbackType: String, code: int, data: Object, bubbles:Boolean=false, cancelable:Boolean=false) { this._eventType = eventType; this._callbackType = callbackType; this._code = code; this._data = data; super(eventType, bubbles, cancelable); } /** * 获取回调事件类型,Constants 中定义了回调事件类型常量(CALLBACKTYE_*),游戏应根据此回调事件类型对事件进行不同的处理。 * @return * */ public function get callbackType(): String { return _callbackType; } /** * 获取回调事件状态码,表示SDK返回的执行结果和状态,StatusCode 中定义了回调事件状态码常量。不同回调事件类型的事件有自己对应的状态列表,游戏应根据此状态码进行不同的处理。 * @return * */ public function get code(): int { return _code; } /** * 获取SDK返回的执行结果数据,不同回调事件类型的事件具有不同的数据结构,游戏应根据回调事件类型来获取相应的数据。 * @return * */ public function get data(): Object { return _data; }}}
3、定义常量
package com.sj4399.pay.ane{ public class Constants { public static const EVENT_TYPE_4399PAYSDK_CALLBACK = "4399_pay_sdk_callback"; public static const CB_LOGIN:String = "login"; public static const CB_LOGOUT:String = "logout"; public static const CB_CHARGE:String = "charge"; public static const STATUS_LOGIN_COMPLETE:int = -1;//登录完成 public static const STATUS_LOGIN_CANCEL:int = -2; //取消登录 public static const STATUS_LOGOUT_COMPLETE:int = -3; //取消登录 public static const STATUS_CHARGE_COMPLETE:int = -4; //充值完成 public static const STATUS_CHARGE_CANCEL:int = -5; //取消充值 }}
编译在bin目录下可以看到swc库文件。
3、生成ANE
拷贝生成的本地jar文件 与swc文件到要创建ANE的目录下
这里我们可以看到有个extension.xml,这个就是用于as3代码里面的的拓展标识,用于as3调用jar包中的函数,里面内容是
com.sj4399.pay.ane.android 1 4399PaySDKANEJava.jar com.sj4399.pay.ane.YJPaymentApiExtension com.sj4399.pay.ane.YJPaymentApiExtension
signature.p12是air生成的密钥,相信air游戏开发者都清楚这个内容。
以解压的方式打开SWC,解压其中的library.swf到Android-ARM文件夹中。
将jar包和第三方所需要的res资源文件拷贝到Android-ARM中,如图
这里都做好了,接下来就是生成ANE了,我们编写一个批处理文件
@REM 打包 .aneSET SWC_FILE=4399PaySDK_ANE_AS.swcSET ANE_FILE=4399PaySDK.aneSET JAR_FILE=4399PaySDKANEJava.jarSET FLEX_ADT_CMD=java -jar "E:\softinstall\ADOBE\Adobe Flash Builder 4.7\sdks\4.6.0\lib\adt.jar"%FLEX_ADT_CMD% -package -tsa none -storetype pkcs12 -keystore signature.p12 -storepass 123456 -target ane %ANE_FILE% extension.xml -swc %SWC_FILE% -platform Android-ARM -C Android-ARM .pause
好了,这样就可以生成我们的所需要的ANE了.至于如何调用相信大家都知道,这里就不多说了。