且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

4399支付SDK供flash游戏使用ANE的使用

更新时间:2022-09-27 14:18:06

 这两天对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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 Map<String, FREFunction> getFunctions() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        return null;
    }
}

空的文件先不管。


2、编写 FREExtension 的派生类(如:YJPaymentApiExtension),在 createContext 方法中创建 YJPaymentApiContext的实例,并作为该方法的结果值返回。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
    }
}


我们通过

1
context.dispatchStatusEventAsync(callbackString, "");

进行回调给as3端。编写完其他接口类即可。


4、修改 YJPaymentApiContext的 getFunctions 方法,将实现的每一个 FREFunction 派生类添加到函数集合中,该函数集合作为该方法的结果值返回;此函数集合即承担接口调用职责

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 Map<String, FREFunction> getFunctions() {
        Map<String, FREFunction> mapFunc = new HashMap<String, FREFunction>();
        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 包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?xml version="1.0" encoding="UTF-8" ?>
<project name="4399paysdk" basedir="." default="exportJar">
                                                                                                                                                                                                                                                                                                                                                                                                                                   
    <!-- 设置全局变量 -->
    <property name="src.dir" value="src" />
    <property name="classes.dir" value="bin/classes" />
    <property name="dist.dir" value="dist" />
    <property name="jar.file" value="4399PaySDKANEJava.jar" />
    <property name="classes.encode" value="UTF-8" />
    <property name="libs.dir" value="libs" />
                                                                                                                                                                                                                                                                                                                                                                                                                                 
    <path id="classpath">
        <fileset dir="${libs.dir}">
            <include name="**/*.jar" />
        </fileset>
        <fileset dir="E:\softinstall\Java\jdk1.6.0_24\jre\lib">
            <include name="**/*.jar" />
        </fileset>
        <fileset dir="E:\soft\android\adt-bundle-windows-x86\sdk\platforms\android-8">
            <include name="android.jar" />
        </fileset>
        <fileset dir="E:\softinstall\ADOBE\Adobe Flash Builder 4.7\sdks\4.6.0\lib\android">
            <include name="FlashRuntimeExtensions.jar" />
        </fileset>
    </path>
                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                       
    <target name="init">
        <!-- Create the time stamp -->
        <tstamp />
    </target>
                                                                                                                                                                                                                                                                                                                                                                                                                                 
    <!-- 编译源文件 -->
    <target name="buildFiles" depends="init">
        <echo message="start building ....." />
        <delete dir="${classes.dir}" />
        <mkdir dir="${classes.dir}" />
        <javac deprecation="on" debug="on" encoding="${classes.encode}" srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath" source="1.6" target="1.6" includeAntRuntime="false" />
        <copy todir="${classes.dir}">
            <!-- copy config files -->
            <fileset dir="${src.dir}" includes="**/*.properties,**/*.xml,**/*.bsh,**/*.logic, **/*.hbm" />
        </copy>
    </target>
                                                                                                                                                                                                                                                                                                                                                                                                                                 
    <!-- 导出jar文件 -->
    <target name="exportJar" depends="buildFiles">
        <delete dir="${dist.dir}" />
        <!-- Create the distribution directory -->
        <mkdir dir="${dist.dir}" />
                                                                                                                                                                                                                                                                                                                                                                                                                                       
        <jar destfile="${dist.dir}/${jar.file}" basedir="${classes.dir}"
            <zipfileset excludes="META-INF/*.SF" src="${libs.dir}/4399PaySdk.jar"/>
                                                                                                                                                                                                                                                                                                                                                                                                                                           
        </jar>        
                                                                                                                                                                                                                                                                                                                                                                                                                                       
        <copy todir="${basedir}/../ane" file="${dist.dir}/${jar.file}" />
    </target>
</project>

这样就完成了本地jar包的生成工作了。


2、创建flex库项目,生成swc库


准备工作:


1)创建项目

4399支付SDK供flash游戏使用ANE的使用

2)属性设置

4399支付SDK供flash游戏使用ANE的使用


编码部分:


这边使用单例模式,创建actionscript代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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、定义常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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的目录下

4399支付SDK供flash游戏使用ANE的使用

这里我们可以看到有个extension.xml,这个就是用于as3代码里面的的拓展标识,用于as3调用jar包中的函数,里面内容是

1
2
3
4
5
6
7
8
9
10
11
12
13
<extension xmlns="http://ns.adobe.com/air/extension/2.5">
    <id>com.sj4399.pay.ane.android</id>
    <versionNumber>1</versionNumber>
    <platforms>
        <platform name="Android-ARM">
            <applicationDeployment>
                <nativeLibrary>4399PaySDKANEJava.jar</nativeLibrary>
                <initializer>com.sj4399.pay.ane.YJPaymentApiExtension</initializer>
                <finalizer>com.sj4399.pay.ane.YJPaymentApiExtension</finalizer>
            </applicationDeployment>
        </platform>
    </platforms>
</extension>

 

signature.p12是air生成的密钥,相信air游戏开发者都清楚这个内容。


以解压的方式打开SWC,解压其中的library.swf到Android-ARM文件夹中。

4399支付SDK供flash游戏使用ANE的使用


将jar包和第三方所需要的res资源文件拷贝到Android-ARM中,如图

4399支付SDK供flash游戏使用ANE的使用


这里都做好了,接下来就是生成ANE了,我们编写一个批处理文件

1
2
3
4
5
6
7
@REM 打包 .ane
SET SWC_FILE=4399PaySDK_ANE_AS.swc
SET ANE_FILE=4399PaySDK.ane
SET JAR_FILE=4399PaySDKANEJava.jar
SET 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了.至于如何调用相信大家都知道,这里就不多说了。



本文转自xuzw13 51CTO博客,原文链接:http://blog.51cto.com/xuzhiwei/1373830,如需转载请自行联系原作者