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 Map<String, FREFunction> getFunctions() {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        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 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 包

<?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)創建項目

wKioL1Mfym6wAzwSAAIC2wb9fL0946.jpg

2)屬性設置

wKiom1Mfyw-wm420AAKqRUbLYTw291.jpg


編碼部分:


這邊使用單例模式,創建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的目錄下

wKioL1MfzI_ji7T2AADbEQgvUJM369.jpg

這裏我們可以看到有個extension.xml,這個就是用於as3代碼裏面的的拓展標識,用於as3調用jar包中的函數,裏面內容是

<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文件夾中。

wKiom1MfzgTQpYkWAAHftNFQRW4246.jpg


將jar包和第三方所需要的res資源文件拷貝到Android-ARM中,如圖

wKiom1MfzlOiDSo2AACD6pc1nJU317.jpg


這裏都做好了,接下來就是生成ANE了,我們編寫一個批處理文件

@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了.至於如何調用相信大家都知道,這裏就不多說了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章