JNI
是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)所以我们需要引用JNI头文件。(引入前做一下平台判断)
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include <android/log.h>
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include <android/log.h>
#endif
在 c++项目路径下cocos2d/cocos/platform/android/jni中的JniHelper.cpp就是cocos为我们封装的Jni接口。里面实现了调用Java内容的方法。
在helloworld类中调用静态方法
// 调用Java中的静态方法
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo info;// 声明一个结构体变量,结构体
JniMethodInfo在导入文件类中已实现
bool isHave = JniHelper::getStaticMethodInfo(minfo,"org/cocos2dx/cpp/TestJni","func1","()V”);//
得到Java类中func1方法
参数:新建类的路径(在pro.android/src/org/..)、方法名、参数列表返回值类型
if (!isHave) {
CCLOG(" 此函数不存在 ");
}else{
CCLOG(" 此函数存在 ");
minfo.env->CallStaticVoidMethod(minfo.classID,minfo.methodID);
}
CCLOG(" 此函数不存在 ");
}else{
CCLOG(" 此函数存在 ");
minfo.env->CallStaticVoidMethod(minfo.classID,minfo.methodID);
}
CCLOG("此函数执行完毕");
#endif
// 调用Java中的非静态方法
首先要考虑新建一个类,因为要调用非静态方法,所以应当使用单例设置模式
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo minfo1;
bool
isHave = JniHelper::getStaticMethodInfo(minfo1,
"org/cocos2dx/cpp/TestJniHelper"
,
"getObj"
,
"()Ljava/lang/Object;"
);
jobject jobs;// object为封装好的对象
if
(!isHave) {
CCLOG( " 此函数不存在 " );
} else {
CCLOG( " 此函数存在 " );
// 获取对象
jobj = minfo1.env->CallStaticObjectMethod(minfo1.classID,minfo1.methodID);
}
bool re = JniHelper::getMethodInfo(minfo1, "org/cocos2dx/cpp/TestJniHelper" , "func" , "()V" );
if (re) {
minfo1.env->CallVoidMethod(jobj,minfo1.methodID);
} else {
CCLOG( " 此函数不存在 " );
}
CCLOG( " 此函数不存在 " );
} else {
CCLOG( " 此函数存在 " );
// 获取对象
jobj = minfo1.env->CallStaticObjectMethod(minfo1.classID,minfo1.methodID);
}
bool re = JniHelper::getMethodInfo(minfo1, "org/cocos2dx/cpp/TestJniHelper" , "func" , "()V" );
if (re) {
minfo1.env->CallVoidMethod(jobj,minfo1.methodID);
} else {
CCLOG( " 此函数不存在 " );
}
CCLOG(
"
此函数执行完毕
"
);
#endif
其中参数与返回值类型的对应表如下:
如何在Xcode中能调用Java的函数,比如在Android端需要加入广告、支付、等第三方平台或者单独处理的一些代码;本文讲解如何在Cocos2dx中访问调用Android的Java层函数;
首先介绍一个类 JniHelper ;
此类主要用于Jni与Java层之间的相互访问的作用,那么此类的常用的一些函数这里首先介绍下,否则直接上代码不太容易吸收 ;
JniHelper
类常用函数:
1. getStaticMethodInfo
(四个参数,bool 返回值)
使用示例代码:
|
bool
isHave
=
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
中先导入如下头文件:
1
2
3
4
5
6
7
|
//
使用预编译,对当前平台为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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
静态函数示例1.无参数,无返回值---------------------------------$$$$$$-----------------------------
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //
判断当前是否为Android平台
JniMethodInfo
minfo
;
//
定义Jni函数信息结构体
//getStaticMethodInfo
次函数返回一个bool值表示是否找到此函数
bool
isHave
=
JniHelper
::
getStaticMethodInfo
(
minfo
,
"com/ai/ommr/OhMonsterMR4Android"
,
"testFun"
,
"()V"
);
if
(
!
isHave
)
{
CCLog
(
"jni:
此函数不存在"
);
}
else
{
CCLog
(
"jni:
此函数存在"
);
//
调用此函数
minfo
.
env
-&
gt
;
CallStaticVoidMethod
(
minfo
.
classID
,
minfo
.
methodID
);
}
CCLog
(
"jni-java
函数执行完毕"
);
#endif
|
Android(Java)
代码:
1
2
3
4
|
//
静态函数示例1.无参数,无返回值
public
static
void
testFun
()
{
Log
.
e
(
"Himi"
,
"
静态函数示例1.无参数,无返回值"
);
}
|
运行截图:
示例代码段2:
Xcode
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//
静态函数示例2.有参数,无返回值------------------------------$$$$$$$--------------------------------
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //
判断当前是否为Android平台
JniMethodInfo
minfo
;
//
定义Jni函数信息结构体
//getStaticMethodInfo
次函数返回一个bool值表示是否找到此函数
bool
isHave
=
JniHelper
::
getStaticMethodInfo
(
minfo
,
"com/ai/ommr/OhMonsterMR4Android"
,
"testFunWithInt"
,
"(I)V"
);
if
(
!
isHave
)
{
CCLog
(
"jni:
此函数不存在"
);
}
else
{
CCLog
(
"jni:
此函数存在"
);
//
调用此函数
minfo
.
env
-&
gt
;
CallStaticVoidMethod
(
minfo
.
classID
,
minfo
.
methodID
,
823
);
}
CCLog
(
"jni-java
函数执行完毕"
);
#endif
|
Android(Java)
代码:
1
2
3
4
|
//
静态函数示例2.有参数,无返回值
public
static
void
testFunWithInt
(
int
_int
)
{
Log
.
e
(
"Himi"
,
"
静态函数示例1.有参数,无返回值;传入的参数int="
+
_int
);
}
|
运行截图:
示例代码段3:
Xcode
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
//
静态函数示例3.有参数,有返回值--------------------------------$$$$$$$--------------------------------
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //
判断当前是否为Android平台
JniMethodInfo
minfo
;
//
定义Jni函数信息结构体
//getStaticMethodInfo
次函数返回一个bool值表示是否找到此函数
bool
isHave
=
JniHelper
::
getStaticMethodInfo
(
minfo
,
"com/ai/ommr/OhMonsterMR4Android"
,
"testFunWithIntAndRtn"
,
"(I)I"
);
jint _int
;
if
(
!
isHave
)
{
CCLog
(
"jni:
此函数不存在"
);
}
else
{
CCLog
(
"jni:
此函数存在"
);
//
调用此函数
_int
=
minfo
.
env
-&
gt
;
CallStaticIntMethod
(
minfo
.
classID
,
minfo
.
methodID
,
823
);
//
尝试jint是否能正常接收返回的int值
JniMethodInfo
minfo_ty
;
bool
isHave
=
JniHelper
::
getStaticMethodInfo
(
minfo_ty
,
"com/ai/ommr/OhMonsterMR4Android"
,
"testFunWithInt"
,
"(I)V"
);
if
(
isHave
)
{
minfo_ty
.
env
-&
gt
;
CallStaticVoidMethod
(
minfo_ty
.
classID
,
minfo_ty
.
methodID
,
_int
);
}
}
CCLog
(
"jni-java
函数执行完毕"
);
#endif
|
Android(Java)
代码:
1
2
3
4
5
|
//
静态函数示例3.有参数,有返回值
public
static
int
testFunWithIntAndRtn
(
int
_int
)
{
Log
.
e
(
"Himi"
,
"
静态函数示例1.有参数,有返回值;传入的参数int="
+
_int
);
return
_int
+
1000
;
}
|
运行截图:
示例代码段4:
Xcode
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //
判断当前是否为Android平台
JniMethodInfo
minfo
;
//
定义Jni函数信息结构体
//getStaticMethodInfo
次函数返回一个bool值表示是否找到此函数
bool
isHave
=
JniHelper
::
getStaticMethodInfo
(
minfo
,
"com/ai/ommr/OhMonsterMR4Android"
,
"testFunWithStringAndRtn"
,
"(I)Ljava/lang/String;"
);
jobject
jobj
;
if
(
!
isHave
)
{
CCLog
(
"jni:
此函数不存在"
);
}
else
{
CCLog
(
"jni:
此函数存在"
);
//
调用此函数
jobj
=
minfo
.
env
-&
gt
;
CallStaticObjectMethod
(
minfo
.
classID
,
minfo
.
methodID
,
823
);
}
CCLog
(
"jni-java
函数执行完毕"
);
#endif
|
Android(Java)
代码:
1
2
3
4
5
|
//
静态函数示例4.有参数,有返回值(String类型)
public
static
String
testFunWithStringAndRtn
(
int
_int
)
{
Log
.
e
(
"Himi"
,
"
静态函数示例4.有参数,有返回值(String类型);int="
+
_int
);
return
"yes,return 'String' is OK --by Himi"
;
}
|
运行截图:
示例代码段5:
Xcode
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) //
判断当前是否为Android平台
JniMethodInfo
minfo
;
//
定义Jni函数信息结构体
//getStaticMethodInfo
次函数返回一个bool值表示是否找到此函数
bool
isHave
=
JniHelper
::
getStaticMethodInfo
(
minfo
,
"com/ai/ommr/OhMonsterMR4Android"
,
//
类的路径
"rtnActivity"
,
//
方法名
"()Ljava/lang/Object;"
);
//
括号里的是参数,后面的是返回值。
jobject
jobj
;
if
(
isHave
)
{
jobj
=
minfo
.
env
-&
gt
;
CallStaticObjectMethod
(
minfo
.
classID
,
minfo
.
methodID
);
}
CCLog
(
"
正确获取到 jobj"
);
//
isHave
=
JniHelper
::
getMethodInfo
(
minfo
,
"com/ai/ommr/OhMonsterMR4Android"
,
//
类的路径
"nostaticFun"
,
//
方法名
"()V"
);
//
括号里的是参数,后面的是返回值。
if
(
isHave
)
{
minfo
.
env
-&
gt
;
CallVoidMethod
(
jobj
,
minfo
.
methodID
);
}
CCLog
(
"jni-java
函数执行完毕"
);
#endif
|
Java
代码:
1
2
3
4
5
6
7
8
9
10
|
//----
函数示例之非静态函数调用
//
(先获取个对象)
public
static
Activity
actInstance
;
//
定义单例
public
static
Object
rtnActivity
()
{
return
actInstance
;
}
//
使用此对象进行调用非静态函数
public
void
nostaticFun
()
{
Log
.
e
(
"Himi"
,
"no static Function is OK - By Himi"
);
}
|
运行截图: