轉載自【黑米GameDev街區】 原文鏈接: http://www.himigame.com/android-game/725.html
很多看過之前Himi的【iOS-cocos2d-X 遊戲開發之七】整合Cocos2dX的Android項目到Xcode項目中,Xcode編寫&編譯代碼,Android導入打包運行即可! 博文的童鞋都在問我如何在Xcode中能調用Java的函數,比如在Android端需要加入廣告、支付、等第三方平臺或者單獨處理的一些代碼;那麼本篇Himi分享如何在Cocos2dx中訪問調用Android的Java層函數;
首先Himi大概的介紹一個類 JniHelper ;
此類主要用於Jni與Java層之間的相互訪問的作用,那麼此類的常用的一些函數這裏首先介紹下,否則直接上代碼不太容易吸收 ;
JniHelper 類常用函數:
1. getStaticMethodInfo (四個參數,bool 返回值)
使用示例代碼:
boolisHave = JniHelper::getStaticMethodInfo(minfo,"com/ai/ommr/OhMonsterMR4Android","testFun","()V");
此函數主要用於獲取Java定義的類靜態函數是否存在,返回bool;
此函數有3個參數:
第一參數: minfo ->JniMethodInfo 類型,後面詳細說;
第二個參數:類的路徑。
第三個參數:方法名(第一參數類中的函數)
第四個參數:(參數)返回類型
關於第一個和第二個參數都比較容易理解,那麼第三個參數需要重點介紹一下;例如你在Java中定義一個如下函數 public void helloJni(){};
那麼getStaticMethodInfo函數第三個參數你應該傳入 “()V” 表示此函數無參無返回值!
如果有這麼一個函數: public int helloJni(int _int){return 823};
那麼getStaticMethodInfo函數第三個參數你應該傳入 “(I)I” 表示此函數需要傳入一個int類型的參數並且返回一個int類型!
大概說兩個童鞋們應該基本理解了,那麼下面詳細寫一些對照表,留給大家對照;
參數、返回值樣式對照表:
這裏的簽名指的就是getStaticMethodInfo函數第三個參數中傳入的樣式;
2. getMethodInfo 類似與第一個函數,只是對應非靜態函數;此函數主要用於獲取Java定義的類非靜態函數是否存在,返回bool;
JniMethodInfo 類:
此類型主要用戶保存類結構體,可以通過JniHelper類的getStaticMethodInfo函數實例化JniMethodInfo對象,從而使用實例的env屬性調用CallStaticVoidMethod,CallVoidMethod,CallStaticIntMethod等函數進行對保存的類結構調用函數;
常用的函數如下:(靜態系列函數)
1. CallStaticVoidMethod(classID,methodID);
2. CallStaticIntMethod(classID,methodID);
3~(n-1) ……省略掉,童鞋們一看就明白;
n. CallStaticObjectMethod(classID,methodID);
帶參數的函數:(如int類型)
CallStaticVoidMethod(classID,methodID,int _int);
非靜態系列函數:
1. CallVoidMethod(jobj,methodID);
2. CallIntMethod(jobj,methodID);
3~(n-1) ……省略掉,童鞋們一看就明白;
n. CallStaticObjectMethod(jobj,methodID);
帶參數的函數:(如int類型)
CallVoidMethod(classID,methodID,int _int);
這裏講解下幾個參數函數:
1. classID: 類ID , JniMethodInfo 對象包含此屬性;
2. methdID: 方法ID,JniMethodInfo 對象也包含此屬性;
3. jobj : java中Object類型,如自定義類,String…
非靜態函數調用的時候,需要的是對象,所以與靜態函數調用的第一個參數不同;
那麼既然能調用Java的函數,那就能得到函數返回值,但是這裏我們得到的返回值書寫類型如下:
譬如返回int 類型,在Xcode中使用 jint 這種形式,更多形式如下:
int -> jint
…省略,大家一看就懂得;
object -> jobject
估計有的童鞋已經暈了,沒關係,下面Himi寫了一些例子代碼,結合來看就一目瞭然啦。
Xcode中先導入如下頭文件:
//使用預編譯,對當前平臺爲Android時纔會導入如下頭文件
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include <android/log.h>
#endif
示例代碼段1:
Xcode 代碼:
////靜態函數示例1.無參數,無返回值---------------------------------$$$$$$-----------------------------
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判斷當前是否爲Android平臺
JniMethodInfo minfo;//定義Jni函數信息結構體
//getStaticMethodInfo 次函數返回一個bool值表示是否找到此函數
boolisHave = JniHelper::getStaticMethodInfo(minfo,"com/ai/ommr/OhMonsterMR4Android","testFun","()V");
if(!isHave) {
CCLog("jni:此函數不存在");
}else{
CCLog("jni:此函數存在");
//調用此函數
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID);
}
CCLog("jni-java函數執行完畢");
#endif
Android(Java) 代碼:
// 靜態函數示例1.無參數,無返回值
publicstatic void testFun() {
Log.e("Himi","靜態函數示例1.無參數,無返回值");
}
運行截圖:
示例代碼段2:
Xcode 代碼:
//靜態函數示例2.有參數,無返回值------------------------------$$$$$$$--------------------------------
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判斷當前是否爲Android平臺
JniMethodInfo minfo;//定義Jni函數信息結構體
//getStaticMethodInfo 次函數返回一個bool值表示是否找到此函數
boolisHave = JniHelper::getStaticMethodInfo(minfo,"com/ai/ommr/OhMonsterMR4Android","testFunWithInt","(I)V");
if(!isHave) {
CCLog("jni:此函數不存在");
}else{
CCLog("jni:此函數存在");
//調用此函數
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID,823);
}
CCLog("jni-java函數執行完畢");
#endif
Android(Java) 代碼:
// 靜態函數示例2.有參數,無返回值
publicstatic void testFunWithInt(int_int) {
Log.e("Himi","靜態函數示例1.有參數,無返回值;傳入的參數int="+ _int);
}
運行截圖:
Xcode 代碼:
//靜態函數示例3.有參數,有返回值--------------------------------$$$$$$$--------------------------------
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判斷當前是否爲Android平臺
JniMethodInfo minfo;//定義Jni函數信息結構體
//getStaticMethodInfo 次函數返回一個bool值表示是否找到此函數
boolisHave = JniHelper::getStaticMethodInfo(minfo,
"com/ai/ommr/OhMonsterMR4Android","testFunWithIntAndRtn","(I)I");
jint _int ;
if(!isHave) {
CCLog("jni:此函數不存在");
}else{
CCLog("jni:此函數存在");
//調用此函數
_int = minfo.env->CallStaticIntMethod(minfo.classID, minfo.methodID,823);
//嘗試jint是否能正常接收返回的int值
JniMethodInfo minfo_ty;
boolisHave = JniHelper::getStaticMethodInfo(minfo_ty, "com/ai/ommr/OhMonsterMR4Android","testFunWithInt", "(I)V");
if(isHave) {
minfo_ty.env->CallStaticVoidMethod(minfo_ty.classID, minfo_ty.methodID,_int);
}
}
CCLog("jni-java函數執行完畢");
#endif
Android(Java) 代碼:
// 靜態函數示例3.有參數,有返回值
publicstatic int testFunWithIntAndRtn(int_int) {
Log.e("Himi","靜態函數示例1.有參數,有返回值;傳入的參數int="+ _int);
return_int+1000;
}
運行截圖:
Xcode 代碼:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判斷當前是否爲Android平臺
JniMethodInfo minfo;//定義Jni函數信息結構體
//getStaticMethodInfo 次函數返回一個bool值表示是否找到此函數
boolisHave = JniHelper::getStaticMethodInfo(minfo, "com/ai/ommr/OhMonsterMR4Android","testFunWithStringAndRtn","(I)Ljava/lang/String;");
jobject jobj;
if(!isHave) {
CCLog("jni:此函數不存在");
}else{
CCLog("jni:此函數存在");
//調用此函數
jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID,823);
}
CCLog("jni-java函數執行完畢");
#endif
Android(Java) 代碼:
// 靜態函數示例4.有參數,有返回值(String類型)
publicstatic String testFunWithStringAndRtn(int_int) {
Log.e("Himi","靜態函數示例4.有參數,有返回值(String類型);int="+ _int);
return"yes,return 'String' is OK --by Himi";
}
運行截圖:
Xcode 代碼:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //判斷當前是否爲Android平臺
JniMethodInfo minfo;//定義Jni函數信息結構體
//getStaticMethodInfo 次函數返回一個bool值表示是否找到此函數
boolisHave = JniHelper::getStaticMethodInfo(minfo,
"com/ai/ommr/OhMonsterMR4Android", //類的路徑
"rtnActivity", //方法名
"()Ljava/lang/Object;"); //括號裏的是參數,後面的是返回值。
jobject jobj;
if(isHave) {
jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
}
CCLog("正確獲取到 jobj");
//
isHave = JniHelper::getMethodInfo(minfo,
"com/ai/ommr/OhMonsterMR4Android", //類的路徑
"nostaticFun", //方法名
"()V"); //括號裏的是參數,後面的是返回值。
if(isHave) {
minfo.env->CallVoidMethod(jobj, minfo.methodID);
}
CCLog("jni-java函數執行完畢");
#endif
Java 代碼:
//---- 函數示例之非靜態函數調用
//(先獲取個對象)
publicstatic Activity actInstance;//定義單例
publicstatic Object rtnActivity() {
returnactInstance;
}
//使用此對象進行調用非靜態函數
publicvoid nostaticFun() {
Log.e("Himi","no static Function is OK - By Himi");
}
運行截圖: