JniHelper调用java静态和非静态方法总结(即cocos2dx中调用android平台下显示第三方广告)

调用非静态方法首先就是调用的静态方法得到要调用的java的类对象然后通过调用
minfo.env->CallVoidMethod(activityObj, minfo.methodID);方法把对象和要调用的方法以及参数(如果有

)传递个java类对象中的非静态方法;

java类:

// c++中調用的方法
public static Object rtnActivity() {
System.out.println("----------rtnActivity");
return mainActivity;
}

public void showAD() {
Log.i("test", "jnihelper do ...show ad");
// ad
// 展示插播广告,可以不调用loadSpot独立使用
SpotManager.getInstance(MainActivity.this).showSpotAds(
MainActivity.this, new SpotDialogListener() {
@Override
public void onShowSuccess() {
Log.i("SpotAd", "展示成功");
}

@Override
public void onShowFailed() {
Log.i("SpotAd", "展示失败");
}

});
}
红色部分替换成你要展示的广告即可

c++调用cpp:

//判断当前是否为Android平台;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

//定义Jni函数信息结构体;
JniMethodInfo minfo;
//返回一个bool值表示是否找到此函数;
bool isHave = JniHelper::getStaticMethodInfo

(minfo,"org/cocos2dx/hellocpp/MainActivity","rtnActivity", "()Ljava/lang/Object;");
jobject activityObj;
if (isHave) {
//CallStaticObjectMethod调用java函数,并把返回值赋值给activityObj
activityObj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
}

//2. 查找displayWebView接口,获取其函数信息,并用jobj调用;
//定义Jni函数信息结构体;
isHave = JniHelper::getMethodInfo(minfo,"org/cocos2dx/hellocpp/MainActivity","showAD",

"()V");

if (!isHave)
{
CCLog("jni:showAD 函数不存在;");
}
else
{
//调用displayWebView函数,并传入参数
minfo.env->CallVoidMethod(activityObj, minfo.methodID);
}

#endif

对于要调用带参数的java非静态方法的可参见分割线一下部分

-----------------华丽的分割线---------------------------------------------

主体思路
通过JNI获取java虚拟机,再获取当前程序的JNI环境,通过JNI环境获取需要调用的java类信息,再获取需要调用的java类中的函数信息。再通过JNI环境调用,使用类信息、函数信息,调用对应的java函数。
看起来好像有点复杂,but不用担心,cocos2d-x中有一个JniHelper类(头文件的copyright为:cocos2d-x.org,是Google提供的还是cocos2d-x小组自己封装的我就不清楚了),它已经把这些工作封装好了。

JniHelper类的使用
加入如下头文件:

#include "platform/android/jni/JniHelper.h"
需要使用的接口如下:

static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
实现上我们只需要使用上面这两个接口,就可以获取java类的所有函数信息了。JNI环境的获取、各种错误处理都已经在这两个接口实现中封装好了。
先上代码,再来依次讲解每个参数的意义和使用方法:

//函数信息结构体
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo,/*JniMethodInfo的引用*/
"com/omega/MyApp",/*类的路径*/
"getJavaActivity",/*函数名*/
"()Ljava/lang/Object;");/*函数类型简写*/
jobject activityObj;
if (isHave)
{
//CallStaticObjectMethod调用java函数,并把返回值赋值给activityObj
activityObj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
}
OK,很简单。上面的代码,就是使用JNI在C++中调用java类静态函数的典型使用方法。只有两步:

1. 获取java函数的信息,classid、methodid等等
2. 选择JNIEnv中的接口,进行函数调用
getStaticMethodInfo参数详解
两个接口的参数一样,意义也相同,详解如下:
JniMethodInfo &methodinfo JniMethodInfo对象的引用,函数执行中会把jniEvn、classid、methodid写入到引用中。
const char *className 类的路径,把类的完整包名写全,用法如以上代码。
const char *methodName 函数名,函数名写上就行了。

const char *paramCode 函数类型简写
这个参数需要单独介绍,它的格式为:(参数)返回类型。
例如:无参数,void返回类型函数,其简写为 ()V
java中的类型对应的简写如下:

参数类型 参数简写
boolean Z
byte B
char C
short S
int I
long J
float F
double D
void V
Object Ljava/lang/String; L用/分割类的完整路径
Array [Ljava/lang/String; [签名 [I
多参数的函数
如果函数有多个参数,直接把简写并列即可。注意Object与Array型参数简写结尾的分号,示例:
IIII //4个int型参数的函数
ILjava/lang/String;I //整形,string类型,整形组合 (int x, String a, int y)

通过JNIEnv进行函数调用
JNIEvn有一系列的CallStatic[返回类型]Method、Call[返回类型]Method接口,需要针对不同的函数返回类型选择调用。
[返回类型]以函数返回类型的不同,对应不同的函数名。
例如:
CallStaticVoidMethod ———void
CallVoidMethod ———void
其对应关系如下:

函数名 函数返回值类型
Void void
Object jobject
Boolean jboolean
Byte jbyte
Char jchar
Short jshort
Int jint
Long jlong
Float jfloat
Double jdouble
参数传递
调用有参数的java函数时,需要把对应的参数传递进去。需要把参数按顺序加入到classid、methodid后面,并且需要做类型转换。例如:

jint jX = 10;
jint jY = 10;
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, jX, jY);
参数类型转换关系如下:

C++类型 JAVA类型
boolean jboolean
byte jbyte
char jchar
short jshort
int jint
long jlong
float jfloat
double jdouble
Object jobject
Class jclass
String jstring
Object[] jobjectArray
boolean[] jbooleanArray
byte[] jbyteArray
char[] jcharArray
short[] jshortArray
int[] jintArray
long[] jlongArray
float[] jfloatArray
double[] jdoubleArray
string类型的转换
实际上我们最常用的参数类型,主要是内建的数据类型、string字符串类型。数据类型可以直接转为j类型,但是string类型需要做如下处理:

jstring jmsg = minfo.env->NewStringUTF("http://www.baidu.com");
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, jmsg);
非静态函数的调用
非静态函数的调用与静态函数的调用类型,但是需要通过一个静态函数获取java类对象。
示例:

//C++代码
//1. 获取activity静态对象
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo,
"com/omega/MyApp",
"getJavaActivity",
"()Ljava/lang/Object;");
jobject activityObj;
if (isHave)
{
//调用静态函数getJavaActivity,获取java类对象。
activityObj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
}

//2. 查找displayWebView接口,获取其函数信息,并用jobj调用
isHave = JniHelper::getMethodInfo(minfo,"com/omega/MyApp","displayWebView", "(IIII)V");

if (!isHave)
{
CCLog("jni:displayWebView 函数不存在");
}
else
{
//调用此函数
jint jX = (int)tlX;
jint jY = (int)tlY;
jint jWidth = (int)webWidth;
jint jHeight = (int)webHeight;
//调用displayWebView函数,并传入参数
minfo.env->CallVoidMethod(activityObj, minfo.methodID, jX, jY, jWidth, jHeight);
}
详尽的示例代码
最后,放一块比较详细的JNI使用代码,基本上覆盖了的全部使用情况。

JniMethodInfo minfo;//JniHelper

/* 测试用方法 */ 
/*bool isHave = JniHelper::getStaticMethodInfo(minfo,"com/cocoa/HiWorld","loginGree", "()V"); //
if (isHave) {
//CCLog("有showText ");
minfo.env -> CallStaticVoidMethod(minfo.classID,minfo.methodID);
}else
{
//CCLog("没有方法showText");
}*/

/* 分享 */
/*//将c++中的string转换成java中的string
//char str[] = "test";
bool isHave = JniHelper::getStaticMethodInfo(minfo,"com/cocoa/HiWorld","shareSina", "(Ljava/lang/String;Ljava/lang/String;)V"); //
if (isHave) {
//CCLog("有share ");
jstring jstr = minfo.env->NewStringUTF("test1 share");
jstring jst = minfo.env->NewStringUTF("/data/data/com.cocoa/cy.png"); 
//jstring jst = minfo.env->NewStringUTF("");
minfo.env -> CallStaticVoidMethod(minfo.classID,minfo.methodID,jstr,jst);
}else
{
//CCLog("没有方法share");
}*/
/* 设置高分 */
/*jint ind = 0;
jlong lsre = 2202l;
bool isHave = JniHelper::getStaticMethodInfo(minfo,"com/cocoa/HiWorld","setHighScore", "(IJ)V"); 
if (isHave) {
minfo.env -> CallStaticVoidMethod(minfo.classID,minfo.methodID,ind,lsre);  
}*/
/* 成就解锁 */
/*jint aind = 0;
bool isHave = JniHelper::getStaticMethodInfo(minfo,"com/cocoa/HiWorld","unLock", "(I)V"); 
if (isHave) {
minfo.env -> CallStaticVoidMethod(minfo.classID,minfo.methodID,aind);  
}*/
/* 测试用方法 */ 
bool isHave = JniHelper::getStaticMethodInfo(minfo,"com/cocoa/HiWorld","rtnActivity","()Ljava/lang/Object;");
jobject jobj;
if (isHave) { 
jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID); 
}  
//CCLog(" jobj存在"); 
/* 测试用方法,非静态无参数无返回值方法 */
/*isHave = JniHelper::getMethodInfo(minfo,"com/cocoa/HiWorld","showText", "()V"); 
if (isHave) {
minfo.env -> CallVoidMethod(jobj,minfo.methodID);
}*/
/* 测试用方法,非静态有java类型的String参数无返回值方法 */
/*isHave = JniHelper::getMethodInfo(minfo,"com/cocoa/HiWorld","showText", "(Ljava/lang/String;)V"); 
if (isHave) {
jstring jmsg = minfo.env->NewStringUTF("msg okey!");
minfo.env -> CallVoidMethod(jobj,minfo.methodID,jmsg);
}*/
/* 测试用方法,返回java类型的String,有java类型的String和int参数方法 */
/*isHave = JniHelper::getMethodInfo(minfo,"com/cocoa/HiWorld","showText", "(Ljava/lang/String;I)Ljava/lang/String;"); 
if (isHave) {
jstring jmsg = minfo.env->NewStringUTF("msg okey! return string");
jint index = 0;
minfo.env -> CallObjectMethod(jobj,minfo.methodID,jmsg,index);
}*/
/* 测试用方法,返回java类型的String[],有java类型的String[]和int参数方法 */
/*isHave = JniHelper::getMethodInfo(minfo,"com/cocoa/HiWorld","showText", "([Ljava/lang/String;I)[Ljava/lang/String;"); 
if (isHave) {
jobjectArray args = 0;
jstring str;
jsize len = 5;
const char* sa[] = {"Hi,","World!","JNI ","is ","fun"};
int i = 0;
args = minfo.env->NewObjectArray(len,minfo.env->FindClass("java/lang/String"),0);
for(i=0;iNewStringUTF(sa[i]);
minfo.env->SetObjectArrayElement(args,i,str);
}
//minfo.env->GetStringArrayRegion(args,0,10,buf);
//jintArray jmsg = {1,2,3};
//minfo.env->NewStringUTF("msg okey! return string");
jint index = 0;
minfo.env -> CallObjectMethod(jobj,minfo.methodID,args,index);
}*/
/* 测试用方法,无返回类型,有java类型的int[]和int参数方法 */
/*isHave = JniHelper::getMethodInfo(minfo,"com/cocoa/HiWorld","testArr", "([II)V"); 
if (isHave) {
jint buf[]={7,5,8,9,3};
jintArray jintArr; //定义jint数组
jintArr = minfo.env->NewIntArray(5);
minfo.env->SetIntArrayRegion(jintArr,0,5,buf);
jint index = 0;
minfo.env -> CallVoidMethod(jobj,minfo.methodID,jintArr,index);
}*/
/* 测试用方法,无返回类型,有java类型的byte[]和int参数方法 */
isHave = JniHelper::getMethodInfo(minfo,"com/cocoa/HiWorld","testArr", "([BI)V"); 
if (isHave) {
jbyte buf[]={7,5,8,9,3};
jbyteArray jbyteArr; //定义jbyte数组
jbyteArr = minfo.env->NewByteArray(5);
minfo.env->SetByteArrayRegion(jbyteArr,0,5,buf);
jint index = 0;
minfo.env -> CallVoidMethod(jobj,minfo.methodID,jbyteArr,index);
}
private static HiWorld hiWorld = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hiWorld = this;
if (detectOpenGLES20()) {
// get the packageName,it‘s used to set the resource path
String packageName = getApplication().getPackageName();
super.setPackageName(packageName);
// set content
setContentView(R.layout.game_demo);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.window_title);

mGLView = (Cocos2dxGLSurfaceView) findViewById(R.id.game_gl_surfaceview);
mGLView.setTextField((Cocos2dxEditText) findViewById(R.id.textField));
mGLView.setEGLContextClientVersion(2);
mGLView.setCocos2dxRenderer(new Cocos2dxRenderer());
task = new TimerTask() {
@Override
public void run() {
// HiWorld.shoot(hiWorld);
Log.e("-------------------", "-------------------");
// 调用c++中的方法
System.out.println("------------------------"
+ stringZjy1());
}
};
timer = new Timer();
timer.schedule(task, 5000);
} else {
Log.d("activity", "don‘t support gles2.0");
finish();
}

static {
System.loadLibrary("game");
}

// c++中調用的方法
public static Object rtnActivity() {
System.out.println("----------rtnActivity");
return hiWorld;
}

// c++中調用的方法,传String类型
public void showText(final String msg) { 
// 添加到主线程
hiWorld.runOnUiThread(new Runnable() {
public void run() { 
System.out.println("----------msg:"+msg);
}
});
}
//c++中調用的方法,传String类型和int类型
public String showText(final String msg,final int index) { 
// 添加到主线程
hiWorld.runOnUiThread(new Runnable() {
public void run() { 
System.out.println("----------msg:"+msg+"; index="+index);
}
});
return "okey String showText(final String msg,final int index)";
}
//c++中調用的方法,传String[]类型和int类型
public String[] showText(final String[] msg,final int index) { 
String[] strArr = {"1","2","3","4","5"};
// 添加到主线程
hiWorld.runOnUiThread(new Runnable() {
public void run() { 
for(String _str:msg){
System.out.println("----------String[] msg:"+_str+"; index="+index);
}
}
});
return strArr;
}
//c++中調用的方法,传int[]类型和int类型
public void testArr(final int msg[],final int index) { 
// 添加到主线程
hiWorld.runOnUiThread(new Runnable() {
public void run() { 
System.out.println("----------int[] msg len:"+msg.length);
for(int _bl:msg){
System.out.println("----------int[] msg:"+_bl+"; index="+index);
}
}
});
}
//c++中調用的方法,传int[]类型和int类型
public void testArr(final byte msg[],final int index) { 
// 添加到主线程
hiWorld.runOnUiThread(new Runnable() {
public void run() { 
System.out.println("----------byte[] msg len:"+msg.length);
for(int _bl:msg){
System.out.println("----------byte[] msg:"+_bl+"; index="+index);
}
}
});
}

时间: 2024-09-28 17:14:50

JniHelper调用java静态和非静态方法总结(即cocos2dx中调用android平台下显示第三方广告)的相关文章

C#中静态与非静态方法比较

C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用上会有什么不同呢? 让我们来看看最直观的差别:使用了static 修饰符的方法为静态方法,反之则是非静态方法. 下面我们分四个方面来看看C#静态方法与非静态方法的差异: C#静态方法与非静态方法比较一.C#静态成员: ①静态成员属于类所有,非静态成员属于类的实例所有. ②每创建一个类的实例,都会在内

[转] C# 中静态与非静态方法比较

C#静态方法与非静态方法的区别不仅仅是概念上的,那么他们有什么具体的区别呢?让我们通过本文向你做一下解析. C#的类中可以包含两种方法:C#静态方法与非静态方法.那么他们的定义有什么不同呢?他们在使用上会有什么不同呢? 让我们来看看最直观的差别:使用了static 修饰符的方法为静态方法,反之则是非静态方法. 下面我们分四个方面来看看C#静态方法与非静态方法的差异: C#静态方法与非静态方法比较一.C#静态成员: ①静态成员属于类所有,非静态成员属于类的实例所有. ②每创建一个类的实例,都会在内

把模块有关联的放在一个文件夹中 在python2中调用文件夹名会直接失败 在python3中调用会成功,但是调用不能成功的解决方案

把模块有关联的放在一个文件夹中 在python2中调用文件夹名会直接失败在python3中调用会成功,但是调用不能成功 解决办法是: 在该文件夹下加入空文件__init__.py python2会把该文件夹整体当成一个包 然后编辑__init__.py 加入__all__ = ["功能名1","功能名2",...../或者类名也行] 再通过from . import 模块名 这样就可以调用包中那些模块功能了 #如果导入这个模块的方式是 from 模块名 import

Java静态属性、静态方法、非静态属性、非静态方法的继承问题简单了解

package com.book.web.controller; /**  * 父类  * @author liweihan  *  */ public class Parent { public String normalStr = "父类非静态属性"; public static String staticStr = "父类静态属性"; public String changeStr = "父类-变量"; public static Stri

java静态与非静态区别

这里的静态,指以static关键字修饰的,包括类,方法,块,字段. 非静态,指没有用static 修饰的. 静态有一些特点: 1.全局唯一,任何一次的修改都是全局性的影响 2.只加载一次,优先于非静态 3.使用方式上不依赖于实例对象. 4.生命周期属于类级别,从JVM 加载开始到JVM卸载结束. 可参考 :http://blog.csdn.net/zhandoushi1982/article/details/8453522/. 关于静态内部类(嵌套类)和非静态内部类的区别,可参考: http:/

9.Java static关键字以及Java静态变量和静态方法

static 修饰符能够与变量.方法一起使用,表示是“静态”的. 静态变量和静态方法能够通过类名来访问,不需要创建一个类的对象来访问该类的静态成员,所以static修饰的成员又称作类变量和类方法.静态变量与实例变量不同,实例变量总是通过对象来访问,因为它们的值在对象和对象之间有所不同. 请看下面的例子: public class Demo { static int i = 10; int j; Demo() { this.j = 20; } public static void main(Str

《java基础知识》Java static关键字以及Java静态变量和静态方法

static 修饰符能够与变量.方法一起使用,表示是“静态”的. 静态变量和静态方法能够通过类名来访问,不需要创建一个类的对象来访问该类的静态成员,所以static修饰的成员又称作类变量和类方法.静态变量与实例变量不同,实例变量总是通过对象来访问,因为它们的值在对象和对象之间有所不同. 请看下面的例子: public final class Demo { static int i = 10; int j; Demo() { this.j = 20; } public static void ma

Android平台下使用lua调用Java代码经验总结

动态语言以其执行的灵活性,可配置性.方便调试能够为开发带来极大的方便.假设用好了.能够极大的提高开发的效率. 怪不得像游戏开发这样复杂的软件开发里没有不集成脚本语言的. 当中,lua以其小巧,灵活.方便扩展,方便嵌入被用于大多数的游戏开发中. 对于我来说.对于一个充分认识到动态的力量的人来说,在软件开发里集成一种脚本语言成为一种非常重要的非常有意义的工作. 可是在Android平台.在试过Python后,发现尽管集成也不是什么困难的事,可是感觉它还是有点大,一个动态库就有3M多,python库还

静态工具类中使用注解注入service(静态方法调用有注解的非静态方法)

原文转载:http://blog.csdn.net/p793049488/article/details/37819121 解决方案如下: /** * */ package cn.common.util; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired;