cocos2dx安卓客户端接入移动MM付费SDK
一、cocos2dx 使用JNI 实现java 和 C++ 相互调用
http://www.himigame.com/iphone-cocos2dx/725.html cocos2dx通过Jni调用Android的Java层代码
http://blog.csdn.net/stupidcodegenerator/article/details/8590821 Cocos2d-x调用Java最终实例代码
http://codingnow.cn/cocos2d-x/992.html cocos2d-x 通过JNI实现c/c++和Android的java层函数互调
http://blog.csdn.net/luxiaoyu_sdc/article/details/15874505 JniHelper类详细使用
1、HelloWorld.cpp
//导入头文件
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include <android/log.h>
#endif
//调用Java代码部分(com/huwujie/gamejni为安卓的包名,JniTest.java)
JniMethodInfo minfo;
if(JniHelper::getStaticMethodInfo(minfo ,"com/huwujie/gamejni/JniTest" ,"sayHelloworld" ,"()V"))
{
minfo.env->CallStaticVoidMethod(minfo.classID , minfo.methodID );
}
// 非静态方法的调用需要从一个静态方法中获得非静态方法所属的对象。即调用了一个返回值类型为java.lang.Object的静态方法
JniMethodInfo minfo;
jobject jobj;
if (JniHelper::getStaticMethodInfo(minfo, "com/huwujie/gamejni/JniTest","getInstance", "()Ljava/lang/Object;"))
{
jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
if (JniHelper::getMethodInfo(minfo, "com/huwujie/gamejni/JniTest","sayHelloworldNotStatic", "()V"))
{
minfo.env->CallVoidMethod(jobj, minfo.methodID);
}
}
//Java调用C++函数,Java里的com.huwujie.gamejni包JniTest.java的函数sayHelloCallBack()对应此C++函数
extern "C"
{
/* 命名规则:Java_Java的包名_类名*/
void Java_com_huwujie_gamejni_JniTest_sayHelloCallBack()
{
CCLog("hello java , i'm c++");
}
}
2、Java里的com.huwujie.gamejni包JniTest.java
//新建的普通测试类,如果是接Sdk,则在项目的主Activity类进行修改
public class JniTest {
// 在调用非静态方法的时候,需要获得方法属于哪一个对象,所以必须有一个静态的实例。
// 而且,这个实例没有办法直接访问,所以必须定义一个静态方法来获得这个实例
// 这个实例必须以Object类型进行输出
public static JniTest tester = null;
public static Object getInstance(){
if (tester == null){
tester = new JniTest();
}
return tester;
}
public native static void sayHelloCallBack();//调用C++
public static void sayHelloworld(){
System.out.println("Java say:hello world!");
sayHelloCallBack();//调用C++
}
public void sayHelloworldNotStatic(){
System.out.println("Java say:hello world,Not Static!");
}
}
二、移动支付官方Demo测试
http://dev.10086.cn/iap/?action=help&dev_cate=4&areaid=1354248456
1、到官网下载文件包 MMBillingSDK 3.0.1
文件包:http://dev.10086.cn/cmdn/supesite/attachments/iap/13-MMBillingSDK_RELEASE(v3.0.1)1014.rar
文档:http://dev.10086.cn/cmdn/supesite/attachments/iap/5-IAP-Developers+Guide-V2.4_201406.doc
解压得到:Demo安卓项目IAP3Demo_simple,mmbilling3.0.1文件夹中有mmbilling.3.0.1.jar、libidentifyApp.so、libcasdkjni.so
2、在eclipse里导入项目IAP3Demo_simple
3、将mmbilling.3.0.1.jar文件拷贝到应用工程的libs目录下,如没有该目录,可新建;“Properties”->“Java Build Path”->“Libraries”->“Add JARs…”,选中该jar文件,最后,检查Referenced Libraries中是否可以看到jar文件,如果可以则配置成功。
4、将libidentifyApp.so和libcasdkjni.so复制到libs\armeabi目录下
5、连接真机跑起来(Demo.java里多了个斜杠“/”,删掉即可)
三、cocos2dx项目接入移动MMBillingSDK
http://www.cnblogs.com/codingdiary/p/3822363.html#3005834 cocos2dx安卓客户端接入移动MM付费SDK
http://blog.sina.com.cn/s/blog_693de6100101jr1c.html cocos2dx项目使用中国移动的android sdk
http://blog.csdn.net/skillart/article/details/18079871 cocos2dx中国移动基地的sdk
http://blog.csdn.net/sozell/article/details/10551309 cocos2dx 中 Android NDK 加载动态库的问题
1、利用Cocos2dx新建项目,【GameJni是项目名称,com.huwujie.gamejni是包名】
终端: cd /Users/ios2/Desktop/Cocosdx2.2/tools/project-creator
执行:./create_project.py -project GameJni -package com.huwujie.gamejni -language cpp
2、Eclipse导入项目GameJni/proj.android,项目提示org.cocos2dx.lib.Cocos2dxActivity找不到的解决方法分别有:
--1、导入cocos2dx lib项目,新建一个Project,选择/Users/ios2/Desktop/Cocosdx2.2/cocos2dx/platform/android文件夹。GameJni项目-》“Properties”->“Android”->“Libraries”->“Add”选中新建的lib【项目“Properties” Is Library表示这个项目是lib,如果是项目非library设置了则报错“Android library projects cannot be launched”】
--2、复制 cocos2d-x根目录\cocos2dx\platform\android\java\src\到你android项目中的src文件夹中
--3、定位 (cocos2d-x根目录)\template\android\,用文本文件打开 copy_files.sh,找到 copy_src_and_jni() 函数,添加入下代码 cp -rf $COCOSJAVALIB_ROOT/src $APP_DIR/proj.android,以后每次新建项目自动生成lib文件夹
3、Java 代码部分
--1、导入库mmbilling.3.0.1.jar,
--2、将Demo中的IAPHandler.java和IAPListener.java复制到包文件夹下com.huwujie.gamejni;
--3、修改项目主Activity类GameJni.Java(也可以新建IAPJni类)
package com.huwujie.gamejni;
import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;
import mm.purchasesdk.OnPurchaseListener;
import mm.purchasesdk.Purchase;
import android.content.Context;
import android.os.Bundle;
public class GameJni extends Cocos2dxActivity{
public static Purchase purchase;
private static Context mcontext;
private static IAPListener mListener;
private static final String APPID = "1111111";
private static final String APPKEY = "111111111";
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mcontext = GameJni.this;
IAPHandler iapHandler = new IAPHandler(this);
/**
* IAP组件初始化.包括下面3步。
*/
/**
* step1.实例化PurchaseListener。实例化传入的参数与您实现PurchaseListener接口的对象有关。
* 例如,此Demo代码中使用IAPListener继承PurchaseListener,其构造函数需要Context实例。
*/
mListener = new IAPListener(this, iapHandler);
/**
* step2.获取Purchase实例。
*/
purchase = Purchase.getInstance();
/**
* step3.向Purhase传入应用信息。APPID,APPKEY。 需要传入参数APPID,APPKEY。 APPID,见开发者文档
* APPKEY,见开发者文档
*/
try {
purchase.setAppInfo(APPID, APPKEY);
} catch (Exception e1) {
e1.printStackTrace();
}
/**
* step4. IAP组件初始化开始, 参数PurchaseListener,初始化函数需传入step1时实例化的
* PurchaseListener。
*/
try {
purchase.init(mcontext, mListener);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
public Cocos2dxGLSurfaceView onCreateView() {
Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
// GameJni should create stencil buffer
glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);
return glSurfaceView;
}
static {
System.loadLibrary("identifyapp");
System.loadLibrary("casdkjni");
System.loadLibrary("cocos2dcpp");
}
public static void buybuybuy()
{
order(mcontext, mListener);
}
public static void order(Context context, OnPurchaseListener listener) {
try {
purchase.order(context,"11111111" , 1,"helloworl",false,listener);
} catch (Exception e) {
e.printStackTrace();
}
}
public native static void orderSuccess();//订单成功,调用C++
public native static void orderFaild();//订单失败,调用C++
}
--2、修改IAPHandler.java和IAPListener.java,将原来和Demo.java相关的改为GameJni.Java,
--3、修改IAPListener.Java购买返回结果
@Override
public void onBillingFinish(int code, HashMap arg1) {
Log.d(TAG, "billing finish, status code = " + code);
/**
*****************省略*****************
**/
if (code == PurchaseCode.ORDER_OK || (code == PurchaseCode.AUTH_OK) ||(code == PurchaseCode.WEAK_ORDER_OK)) {
/**
* 商品购买成功或者已经购买。 此时会返回商品的paycode,orderID,以及剩余时间(租赁类型商品)
*/
/**
*****************省略*****************
**/
GameJni.orderBSuccess();//返回结果调用
} else {
/**
* 表示订购失败。
*/
GameJni.orderFaild();//返回结果调用
}
}
4、C++ 代码部分,HelloWorld.cpp
//导入头文件
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include <android/log.h>
#endif
//触发购买处添加代码
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
if(JniHelper::getStaticMethodInfo(minfo ,"com/huwujie/gamejni/IAPJni" ,"buybuybuy" ,"()V"))
{
minfo.env->CallStaticVoidMethod(minfo.classID , minfo.methodID );
}
#endif
//购买结果回调
void Java_com_huwujie_gamejni_GameJni_orderSuccess()
{
CCLog("do order logic++++++++++orderSuccess");
}
void Java_com_huwujie_gamejni_GameJni_orderFaild()
{
CCLog("do nothing-----------orderFaild");
}
5、项目配置文件
--1、将libidentifyApp.so和libmmSDKjni.so复制到proj.android\jni\hellocpp,在proj.android\jni\Android.mk中加入以下代码,项目编译后将在libs\armeabi目录下生成libidentifyApp.so和libcasdkjni.so。
include $(CLEAR_VARS)
LOCAL_MODULE := libidentifyapp
LOCAL_SRC_FILES := hellocpp/libidentifyapp.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcasdkjni
LOCAL_SRC_FILES := hellocpp/libcasdkjni.so
include $(PREBUILT_SHARED_LIBRARY)
LOCAL_SHARED_LIBRARIES := libidentifyapp
LOCAL_SHARED_LIBRARIES := libcasdkjni
--2、在AndroidManifest.xml中增加iap声明,com.huwujie.gamejni为你的程序包名,/*xxxxx*/部分为说明,请勿添加
/* 添加在application声明里面,此处开始begin>>>>>>>>>>*/
<service
android:name="mm.purchasesdk.iapservice.PurchaseService"
android:exported="true" >
<!-- android:process="mm.iapServices" > -->
/*com.aspire.purchaseservice.BIND,不要自作聪明删除此掉,坑*/
<intent-filter android:priority="301" >
<action android:name="com.aspire.purchaseservice.BIND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="301" >
<action android:name="com.huwujie.gamejni.purchaseservice.BIND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="301" >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAFIAP.COMPONENT" >
</category>
</intent-filter>
</service>
<!-- android:excludeFromRecents="true" -->
<!-- android:launchMode="singleInstance" -->
<activity
android:name="mm.purchasesdk.iapservice.BillingLayoutActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="@android:style/Theme.Translucent" >
<intent-filter android:priority="301" >
<action android:name="com.huwujie.gamejni.com.mmiap.activity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- android:process="safiap.framework.safframeworkmanager" begin -->
<service
android:name="safiap.framework.SafFrameworkManager"
android:exported="true"
android:process="safiap.framework" >
<intent-filter android:priority="630" >
<!-- ID for services declared in AIDL -->
<action android:name="safiap.framework.sdk.ISAFFramework" />
</intent-filter>
<intent-filter android:priority="630" >
<!-- ID for services declared in AIDL -->
<action android:name="safiap.framework.ACTION_START_DOWNLOAD" />
</intent-filter>
<intent-filter android:priority="630" >
<!-- ID for services declared in AIDL -->
<action android:name="safiap.framework.ACTION_CHECK_UPDATE" />
</intent-filter>
</service>
<!-- receivers -->
<receiver android:name="safiap.framework.CheckUpdateReceiver" >
<intent-filter>
<action android:name="safiap.framework.ACTION_CANCEL_NOTIFICATION" />
</intent-filter>
<intent-filter>
<action android:name="safiap.GET_SHARED_DATA" />
</intent-filter>
<intent-filter>
<action android:name="safiap.framework.ACTION_SET_TIMER" />
</intent-filter>
</receiver>
<activity
android:name="safiap.framework.ui.UpdateHintActivity"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:configChanges="orientation"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="safiap.framework.ACTION_TO_INSTALL" />
</intent-filter>
<intent-filter>
<action android:name="safiap.framework.ACTION_TO_INSTALL_IAP" />
</intent-filter>
<intent-filter>
<action android:name="safiap.framework.ACTION_NETWORK_ERROR_IAP" />
</intent-filter>
<intent-filter>
<action android:name="safiap.framework.ACTION_NETWORK_ERROR_FRAMEWORK" />
</intent-filter>
</activity>
<service android:name="safiap.framework.logreport.monitor.handler.LogreportHandler" android:process=":remote"/>
<!-- android:process="safiap.framework.safframeworkmanager" end -->
/* 添加在application声明里面,>>>>>>>>>>此处结束end */
/* 增加权限声明,以确保可以正常读取手机的IMSI/IMEI,读取和网络访问 */
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
--3、在主Activity中加载sdk的库,如上文的GameJni.Java
static {
System.loadLibrary("identifyapp");
System.loadLibrary("casdkjni");
}
6、终端编译:进入/Users/ios2/Desktop/Cocosdx2.2/projects/MyGame/proj.android目录,执行./build_native.sh.
编译完成后,Eclipse,GameJni项目refresh->clean->run,连接真机跑起来!