一、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,連接真機跑起來!