Cocos2d-x与Android利用JNI相互调用

本文详细介绍了Cocos2d-x如何利用JNI与Android原生代码进行交互,包括Cocos调用JAVA代码的步骤、自定义数据类型的传递、在Cocos中创建JAVA类的映射类,以及在Android中调用C++本地库的方法。同时,通过弹出原生AlertDialog的示例展示了Cocos调用Android原生控件的实现过程。
摘要由CSDN通过智能技术生成

1.背景知识

1.1什么是JNI

JNI是Java Native Interface的简写,简单来说,就是一种JAVA和C++之间相互调用的一套接口。利用JNI可以在JAVA代码层(manager code)调用C++代码层(native code)的函数,反之亦可。

如果你之前并不熟悉JNI,可以通过官方文档:Java Native Interface Specification ( http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html)先来了解一下。

英文不好的同学,可以看看这篇博客(http://wiki.jikexueyuan.com/project/deep-android-v1/jni.html)

1.2 为什么要用JNI

Cocos2d-x作为一种跨平台的开源游戏引擎,其特点是一次编写,到处部署。如果部署到Android平台,我们可以利用JNI来调用Android的一些类库和控件,加个Android原生对话框什么的。更重要的是,如果项目里有很多组件是用JAVA编写的,我们应该尽量使用现有的组件,避免重复的制造轮子。

应当指出,Cocos2d-x可以调用Android的控件,但是不应该过分依赖这一点,唯一用到这一功能的情景,是引擎实在没法实现,从解耦的角度考虑,界面逻辑应当尽量放在Cocos当中来做。

2.Cocos2d-x调用JAVA代码

Cocos为我们封装了一些JNI调用的接口,这个类叫JniHelper(其实JAVA自己也提供了JNI调用的接口类,叫JniHelp,这两个类没什么差别),这个类的位置在[cocos安装路径]\cocos\platform\android\jni

这里写图片描述

在Cocos中用JNI调用JAVA程序时,jni.h这个头文件是必须的,好在JniHelper.h中已经帮我们包含了,所以我们只需要包含JniHelper.h这个头文件就可以了。

所以,在需要调用JNI的类中,需要加入

    #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

    #include "platform/android/jni/JniHelper.h"

    #endif

条件编译,是用来说明这个东西是Android平台上用到的。

JniHelper.h当中还包含一个相当重要的结构体:JniMethodInfo,看名字就猜到了,这个结构体是用来定位调用的JAVA方法的,来看看这个结构体的定义

    typedef struct JniMethodInfo_
    {
        JNIEnv *    env;
        jclass      classID;
        jmethodID   methodID;
    } JniMethodInfo;

classID和methodID很好理解,分别代表类和方法,这样就可以定位到具体的方法了。env稍微有点复杂,它表示一个线程相关的结构体,里面保存的是JNI函数指针,不能跨线程访问,其实也不用管这个变量究竟代表什么意思,用起来十分简单。

那么下一个问题是怎么初始化这三个成员变量,或者说怎么注册JAVA方法。

举个例子,待调用的JAVA方法,位于org.cocos2dx.cpp包中,类名叫TestJni,待调用的方法是func1

这里写图片描述

(关于如何将Cocos项目部署到Eclipse上,参考我前一篇博客:http://blog.csdn.net/sgn132/article/details/50481923)

TestJni.java的代码十分简单,注意这里func1方法是静态函数,具体代码如下:

    package org.cocos2dx.cpp;

    import android.util.Log;

    public class TestJni {
   
        public static void func1(){
            Log.d("success","java jni called succeed");
        }
    }

然后打开Cocos项目,我这里使用VS2015作为开发环境的,cocos版本是v3.8.1,在一个按键响应方法里,添加调用JNI的代码

#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    JniMethodInfo info;
    //getStaticMethodInfo判断java定义的静态函数是否存在,返回bool
    bool ret = JniHelper::getStaticMethodInfo(info,"org/cocos2dx/cpp/TestJni","func1","()V");
    if(ret)
    {
        log("call void func1() succeed");
        //传入类ID和方法ID,小心方法名写错,第一个字母是大写
        info.env->CallStaticVoidMethod(info.classID,info.methodID);
    }
#endif
  • getStaticMethodInfo是注册函数
    他有4个参数,前三个很好理解,用来定位JAVA方法,最后一个参数一般称为签名,是用来表示调用的JAVA方法的传递参数和返回值类型的。
  • CallStaticVoidMethod是调用函数
    这个函数也不用多说了,使用来调用指定JAVA方法的。

2.1 JNI怎么传递自定义数据类型

2.1.1 参数、返回值类型组成的字符串——签名

首先要提的是JNI的签名机制,签名其实就是函数的参数类型和返回值类型共同组成的字符串,之所以要有签名机制,是因为C++是允许函数重载的,单靠函数名无法准确定位函数的入口,还需要函数的参数信息。

JNI的规范签名格式是:

(参数1类型标示参数2类型标示...参数n类型标示)返回值类型标示。

举个栗子:
JAVA中函数定义为

    void play(String singer,String album)

对应的签名

    (Ljava/lang/String;Ljava/lang/String;)V

其中L表示引用类型,后面跟的是包名,需要把”.“换成”/“,V表示void。

这里给出标示类型对照表:

标示类型 Java类型
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L/java/lang/String; S
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值