air应用接入移动mm弱联网平台

4 篇文章 0 订阅
3 篇文章 0 订阅

不得不说移动mm平台是比较友好的,遇到的所有问题都在群里有人回答,并且sdk接入十分方便,没有遇到什么大问题。

工作量大概是一天左右,分享一下接入过程。


所需环境:

AIR:3.9

ANDROIDAPI:19

移动mm版本:1.2.2


1.编写as文件


定义函数常量

private static const MM_FUNCTION_INIT:String = "mmsns_function_init";//与java端中Map里的key一致
private static const MM_FUNCTION_BILL:String = "mmsns_function_bill";//与java端中Map里的key一致
private static const MM_FUNCTION_DEBUG:String = "mmsns_function_debug";//与java端中Map里的key一致
private static const EXTENSION_ID:String = "com.mmsns.ane";//与extension.xml中的id标签一致


创建单例
private static var _instance:MMSNSExtension; 
public function MMSNSExtension()
{
	if(extContext == null) {
		extContext = ExtensionContext.createExtensionContext(EXTENSION_ID, "");
		extContext.addEventListener(StatusEvent.STATUS, statusHandler);
	}
} 
/**
 * 获取实例
 * @return DLExtension 单例
 */
public static function getInstance():MMSNSExtension
{
	if(_instance == null) {
		_instance = new MMSNSExtension();
	}
	return _instance;
}


抛事件函数

/**
 * 转抛事件
 * @param event 事件
 */
private function statusHandler(event:StatusEvent):void
{
	dispatchEvent(event);
}

以上是99%的ane都需要复制粘贴的语句。。

然后是定义移动mm的函数,因为弱联网版本只有初始化跟支付两个功能点,所以直接写

/**
 * 初始化
 * @param APPID
 * @param APPKEY
 * @return 
 * 
 */			
public function MMSNSInit(APPID:String,APPKEY:String):void{
	if(extContext ){
		extContext.call(MM_FUNCTION_INIT, APPID, APPKEY);
	}
} 

/**
 * 商品购买接口。
 * @param payCode
 * @param num
 * @param description
 * @return 
 * 
 */		
public function MMSNSBilling(payCode:String, num:uint, description:String = ''):void{
	if(extContext ){
		extContext.call(MM_FUNCTION_BILL, payCode, num, description);
	}
}

以上,as版本真心没技术含量,请大家谅解。


然后是安卓端。。

安卓端我的api一律设为19,然后记得勾上"Mark this project as a library",上面两项都去掉勾

安卓端要先创建context跟extension两个文件,把入口代码站过去。


Context文件

package com.mmsns.ane;

import java.util.HashMap;
import java.util.Map;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.mmsns.func.MMSNSBill;
import com.mmsns.func.MMSNSBillInit;

public class MMSNSContext extends FREContext {
	/**
	 * 初始化
	 */
	public static final String MMSNS_FUNCTION_INIT = "mmsns_function_init";
	/**
	 * 订购
	 */
	public static final String MMSNS_FUNCTION_BILL = "mmsns_function_bill";
	@Override
	public void dispose() {
		// TODO Auto-generated method stub

	}

	@Override
	public Map<String, FREFunction> getFunctions() {
		// TODO Auto-generated method stub
		Map<String, FREFunction> map = new HashMap<String, FREFunction>();
		//映射
		map.put(MMSNS_FUNCTION_INIT, new MMSNSBillInit());
		map.put(MMSNS_FUNCTION_BILL, new MMSNSBill());
		return map;
	}

}

Extension文件

package com.mmsns.ane;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREExtension;

public class MMSNSExtension implements FREExtension {

	@Override
	public FREContext createContext(String arg0) {
		// TODO Auto-generated method stub
		return new MMSNSContext();
	}

	@Override
	public void dispose() {
		// TODO Auto-generated method stub

	}

	@Override
	public void initialize() {
		// TODO Auto-generated method stub

	}

}

把入口定义好后,就是加入功能代码了,因为要完成移动mm的支付,需要完成Handler和OnSMSPurchaseListener这两个类来监测初始化跟支付的状态。


IAPHandler

package com.mmsns.func;


import android.os.Handler;
import android.os.Message;

import com.adobe.fre.FREContext;

public class IAPHandler extends Handler {

	public static final int INIT_FINISH = 10000;
	public static final int BILL_FINISH = 10001;
	public static final int QUERY_FINISH = 10002;
	public static final int UNSUB_FINISH = 10003;

	public IAPHandler(FREContext context) {
		MMSNSShared.context = (FREContext) context;
	}

	@Override
	public void handleMessage(Message msg) {
		super.handleMessage(msg);
	}
}

IAPListener,处理各种完成的回调之类的,抛送信息到as端

package com.mmsns.func;

import java.util.HashMap;

import mm.sms.purchasesdk.OnSMSPurchaseListener;
import mm.sms.purchasesdk.PurchaseCode;
import mm.sms.purchasesdk.SMSPurchase;
import android.os.Message;
import android.util.Log;

import com.adobe.fre.FREContext;

public class IAPListener implements OnSMSPurchaseListener {
	private final String TAG = "IAPListener";
	private IAPHandler iapHandler;

	public IAPListener(FREContext context, IAPHandler iapHandler) {
		MMSNSShared.context = context;
		this.iapHandler = iapHandler;
	}

	@Override
	public void onInitFinish(int code) {
		MMSNSShared.event(TAG, "Init finish, status code = " + code);
		Message message = iapHandler.obtainMessage(IAPHandler.INIT_FINISH);
		String result = "初始化结果:" + SMSPurchase.getReason(code);
		message.obj = result;
		message.sendToTarget();
	}

	@Override
	public void onBillingFinish(int code, HashMap arg1) {
		MMSNSShared.event(TAG, "billing finish, status code = " + code);
		String result = "订购成功";
		Message message = iapHandler.obtainMessage(IAPHandler.BILL_FINISH);
		// 商品信息
		String paycode = null;
		// 商品的交易 ID,用户可以根据这个交易ID,查询商品是否已经交易
		String tradeID = null;
		if (code == PurchaseCode.ORDER_OK
				|| code == PurchaseCode.ORDER_OK_TIMEOUT) {
			/**
			 * 商品购买成功或者已经购买。 此时会返回商品的paycode,orderID,以及剩余时间(租赁类型商品)
			 */
			if (arg1 != null) {
				paycode = (String) arg1.get(OnSMSPurchaseListener.PAYCODE);
				if (paycode != null && paycode.trim().length() != 0) {
					result = result + ",Paycode:" + paycode;
				}
				tradeID = (String) arg1.get(OnSMSPurchaseListener.TRADEID);
				if (tradeID != null && tradeID.trim().length() != 0) {
					result = result + ",tradeid:" + tradeID;
				}
				MMSNSShared.event("ORDER_SUCCESS", paycode);
			}
		} else {
			/**
			 * 表示订购失败。
			 */
			result = "订购失败:" + SMSPurchase.getReason(code);
			MMSNSShared.event("ORDER_FAIL", SMSPurchase.getReason(code));
			Log.d(TAG, "ORDER_FAIL" + SMSPurchase.getReason(code));
		}
		MMSNSShared.event(TAG, result);

	}
}

好了,现在可以开始写功能函数了,但是我们需要一个共享的类来存储context和一些初始信息,方便我们随时调用。

于是来一个Shared类,专门存储信息

package com.mmsns.func;

import mm.sms.purchasesdk.SMSPurchase;

import android.util.Log;
import android.widget.Toast;

import com.adobe.fre.FREContext;

public class MMSNSShared {
	public static Boolean DEBUG = false;
	
	public static  String APPID = "0000000000";
	public static  String APPKEY = "0000000000";
	
	public static SMSPurchase purchase;
	public  static IAPListener mListener;
	
	public static FREContext context;
	
	public static void event(String code,String level  ){
		Log.d(code, "---------抛出event-------" + ":"+level );
		context.dispatchStatusEventAsync(code, level );
		if (DEBUG){
			Toast.makeText(context.getActivity(), code + ":" + level, Toast.LENGTH_LONG).show();
		}
	}
}

现在实现初始化mm模块

package com.mmsns.func;

import mm.sms.purchasesdk.SMSPurchase;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.adobe.fre.FREObject;

public class MMSNSBillInit implements FREFunction {

	private String TAG = "MMBillInit";
	
	@Override
	public FREObject call(final FREContext context, FREObject[] arg1) {
		MMSNSShared.context = context;
		FREObject result = null; 
		try
		{
			MMSNSShared.APPID = arg1[0].getAsString();
			MMSNSShared.APPKEY = arg1[1].getAsString();
		}
		catch(Exception e)
		{
			return null;
		}
		IAPHandler iapHandler = new IAPHandler(MMSNSShared.context);
		/**
		 * IAP组件初始化.包括下面3步。
		 */
		/**
		 * step1.实例化PurchaseListener。实例化传入的参数与您实现PurchaseListener接口的对象有关。
		 * 例如,此Demo代码中使用IAPListener继承PurchaseListener,其构造函数需要Context实例。
		 */
		MMSNSShared.mListener = new IAPListener(MMSNSShared.context, iapHandler);
		/**
		 * step2.获取Purchase实例。
		 */
		MMSNSShared.purchase = SMSPurchase.getInstance();
		/**
		 * step3.向Purhase传入应用信息。APPID,APPKEY。 需要传入参数APPID,APPKEY。 APPID,见开发者文档
		 * APPKEY,见开发者文档
		 */
		try {
			MMSNSShared.purchase.setAppInfo(MMSNSShared.APPID, MMSNSShared.APPKEY);
		} catch (Exception e1) {
			return null;
		}
		/**
		 * step4. IAP组件初始化开始, 参数PurchaseListener,初始化函数需传入step1时实例化的
		 * PurchaseListener。
		 */
		try {
			MMSNSShared.purchase.smsInit(context.getActivity(), MMSNSShared.mListener); 
		} catch (Exception e) {
			return null;
		}
		//--------------------------------

		return result;
	}
}

然后是支付函数

package com.mmsns.func;

import android.content.Context;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.adobe.fre.FREObject;

public class MMSNSBill implements FREFunction {

	private String TAG = "MMSNSBill";
	@Override
	public FREObject call(final FREContext context, FREObject[] arg1) {
		String payCode = null,description = null;
		int num = 0;
		FREObject result = null; 
		//get params
		try{
			payCode = arg1[0].getAsString();
			num = arg1[1].getAsInt();
			description = arg1[2].getAsString();
		}catch(Exception e){
			MMSNSShared.event(TAG, "参数错误:" + e.getMessage() + "|" + payCode + "|" + num + description);
			return null;
		}
		/**
		 * 商品购买接口。
		 */
		if(MMSNSShared.context != null){
			order(MMSNSShared.context.getActivity(), payCode, num, description);
		}else{
		}
		//--------------------------------
		return result;
	}
	public void order(Context context, String payCode, int num, String description) {
		try {
			MMSNSShared.purchase.smsOrder(context, payCode, MMSNSShared.mListener, description);
		} catch (Exception e) {
			MMSNSShared.event(TAG, "支付失败" + e.getMessage() + "," + e.toString());
		}
	}

}

好了,程序上的东西都做好了,现在开始打包ane

我们需要as端bin文件夹下的swc文件,和and端bin文件夹下的jar文件

以及一个extension.xml的文件

<?xml version="1.0" encoding="UTF-8"?>
<extension xmlns="http://ns.adobe.com/air/extension/3.9">
  <id>com.mmsns.ane</id>
  <versionNumber>1</versionNumber>
  <platforms>
  
    <platform name="Android-ARM">
      <applicationDeployment>
        <nativeLibrary>mmsnsbillingane.jar</nativeLibrary>
        <initializer>com.mmsns.ane.MMSNSExtension</initializer>
        <finalizer>com.mmsns.ane.MMSNSExtension</finalizer>
      </applicationDeployment>
    </platform>
    
  </platforms>
</extension>


先要合并生成的jar跟移动的jar文件

用winrar之类的打开自己的jar和移动mm的jar,把移动mm的除了assets和META-INF外都复制到自己的jar文件那

我是使用批处理完成这个复杂的操作。。感谢前人的努力写出这段神奇的批处理

rem 你做的主JAR包的路径
set SOURCEJAR=com.mmsns.ane.jar
set MainJar=mmsnsbillingane.jar
rem 第三方JAR包的路径
set ExternalJar=mmsmsbilling1.2.2.jar
rem 第三方JAR包顶级包名称
set packageName=com
set packageName2=mm
rem swc文件名
set SWC=MMANE-SNS.swc
echo =========== start make jar ==============
rem 创建临时目录
md temp
rem 拷贝临时文件
rem copy %SOURCEJAR% %MainJar%
copy .\android-project\bin\%SOURCEJAR% .\temp\%MainJar% >nul
copy .\SDK1.2.2\libs\%ExternalJar% .\temp\ >nul
cd temp
rem 解压第三方包
jar -xf %ExternalJar%
rem 合并主JAR包
jar -uf %MainJar% %packageName% 
rem 合并其他顶级包
jar -uf %MainJar% %packageName2%

然后把生成的jar,swc解压出来的catalog.xml,library.swf,一起扔到android-ARM文件夹里,把swc,extension.xml,p12放到外面

移动mm提供的libsmsiap.so,需要放到android-ARM/libs/armeabi-v7a下面


用一行命令打包,其中p12用自己的p12文件
set FLEX_SDK=D:\AIR_3.9
java -jar "%FLEX_SDK%\lib\adt.jar" -package -storetype PKCS12 -keystore czq.p12 -storepass 123456 -target ane com.mmsns.ane extension.xml -swc *.swc -platform Android-ARM -C Android-ARM mmiap . 

搞定。。

另外打包apk的时候,记得把移动mm的jar包里的assets\mmiap打包进你的apk。

我还做了个一件打包生成ane的自动化批处理文件,包含在源码里面。

本教程的所有代码以及打包函数都在这里。


https://github.com/platformanes/android-mm-sms


第一篇文章,请拍砖。感谢Rect的先期研究。接下来我会放出小米还有移动mm平台,以及我接过的一些ios平台的教程。有些rect的版本改动不大的我就不放出来了,请自己到https://github.com/platformanes去下载。

希望使用air的人能更专注于开发游戏上面,而不要在ane接入上耗费太多时间。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值