VS2010 通过Jni调用Android的Java层代码(cocos2dx里访问调用Android函数)!


参考:http://codingnow.cn/cocos2d-x/992.html

参考了Himi的博客:http://www.himigame.com/android-game/725.html,总结一下在VS2010上面实现如何在cocos2dx项目里利用JNI调用Android的java层代码。

本人用的是cocos2d-x 2.2.2版本,就用最简单的HelloCpp来当做例子。讲例子之前,希望刚接触的朋友还是先去看看Himi的博客:http://www.himigame.com/android-game/725.html 了解一下JNI大致的一个用法。

在VS2010里面新建TestJNI.h头文件:

<span style="font-size:14px;">#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#endif

#include "cocos2d.h"

USING_NS_CC;

class TestJNI
{
public:
	void test1();
	void test2();
	void test3();

};
</span>

其中在写第一行到第四行的时候,本人编译器就自动报了错:说是找不到jni.h头文件,这个错误估计很多人都会遇到,下面说一下解决的办法:

第一步:选中HelloCpp项目,然后:项目->属性->配置属性->VC++目录->包含目录



第二步,在包含目录右边的路径中把JDK安装目录下的D:\jdk1.6\include和D:\jdk1.6\include\win32的路径加到里面去,本人添加的路径是:D:\jdk1.6\include;D:\jdk1.6\include\win32; 。路径之间用“;”分号隔开,还有把上面的路径改成你们机器下面的具体路径就行了。 添加完成之后,点确定按钮,过一会编译就能通过了。然后去cocos2dx的安装目录下的Debug.win32目录下拷贝几个已经编译好的库文件(本人机器上的路径是:E:\develop_sofware\cocos2d-x-2.2.2\cocos2d-x-2.2.2\Debug.win32),我个人就懒得每个去报了错就去这个目录下找,我是直接拷贝Debug.win32这个目录下的所有文件到:HelloCpp工程目录下的Debug.win32里面去(本人目录:E:\develop_sofware\cocos2d-x-2.2.2\cocos2d-x-2.2.2\samples\Cpp\HelloCpp\proj.win32\Debug.win32)。

不拷贝的话,生成的时候会报诸如:找不到 libcocos2d.lib文件,这些错误。

然后还要配置一下”链接器->输入->附加依赖项",附加依赖项的值增加:如:libExtensions.lib;libcocos2d.lib;libCocosDenshion.lib;opengl32.lib;glew32.lib;libBox2d.lib;libchipmunk.lib;libcurl_imp.lib;pthreadVCE2.lib;websockets.lib;%(AdditionalDependencies

如下图:



这样配置VS基本就应用没什么问题了。(注:每个工程都要这么配置一下!是比较坑爹,我也很郁闷,如果同学们有其他好的方法也请麻烦告诉一下,谢谢!)


测试一下是否可用吧,在VS2010里面再新建一个TestJNI.cpp文件(这里吐槽一下,vs不知道怎么想的,创建头文件的时候不会自动创建相应的CPP文件,可能是本人不会用吧,毕竟没怎么用过VS。Xcode这一点就做的不错。)

<span style="font-size:14px;">#include "TestJNI.h"

void TestJNI::test1(){
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)//判断当前是否为Android平台
	// 调用Android里面无参数、无返回值的静态方法
	JniMethodInfo methodInfo;
	bool isHave = JniHelper::getStaticMethodInfo(methodInfo,"org.cocos2dx.hellocpp.TestJNI","testNoParameNoReturn","()V");
	if(!isHave)
	{
		methodInfo.env->CallStaticVoidMethod(methodInfo.classID,methodInfo.methodID);
	}

#endif
}

void TestJNI::test2(){
	// 有参数,无返回值
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)//判断当前是否为Android平台
	JniMethodInfo methodInfo;
	bool isCall = JniHelper::getStaticMethodInfo(methodInfo,"org.cocos2dx.hellocpp.TestJNI","testNoParameButReturn","(I)V");
	if(isCall)
	{
		methodInfo.env->CallStaticVoidMethod(methodInfo.classID,methodInfo.methodID,999);
	}
#endif
}</span>

简单说一下大致的意思:在test1()方法中,先判断一下当前环境是否是Android,如果是就执行#if  #endif块中的代码。定义一个JniMethodInfo类型的对象 methodInfo ,然后把它传到JniHelper::getStaticMethodInfo()方法中。简单说一下JniHelper::getStaticMethodInfo(参数1,参数2,参数3,参数4)这个方法的四个参数:

参数1:JniMethodInfo类型的实例
参数2:需要调用的Android层下面定义了该方法的类的完整路径
参数3:需要调用的方法的名字
参数4:描述参数的参数列表和返回值

前面3个参数都比较好理解,后面第4个参数就要再多说几句:test1()方法中的"()V",代表的意思是:此函数无参数无返回值。再举个例子:如果Android上面写了这么一个函数:public float getIndex(int index);  参数4就要传入"(I)F",代表调用的方法有一个Int类型的参数,并且会返回一个float类型的数据。具体的类型对照表请看下面:

参数、返回值样式对照表:



调用了JniHelper::getStaticMethodInfo()函数之后,会有个bool返回值,true代表找到了这个方法,false就代表没找着。然后就通过JniMethodInfo类型的对象 methodInfo获得成员变量env,最后通过env调用CallStaticVoidMethod函数来具体调用Android层上面对应的那个方法。(是不是感觉有点像java的反射?呵呵)。


好,VS上面的代码就写到这里,再看看Android工程里面是怎么弄的:

第一步,先导入HelloCpp工程(去cocos2d目录下面去找,本人的路径是:E:\develop_sofware\cocos2d-x-2.2.2\cocos2d-x-2.2.2\samples\Cpp\HelloCpp\proj.android);


第二步,点开工程目录下的jni目录,如下图:



然后打开Android.mk文件,在里面把我们刚才在VS上面新建的那个TestJNI.cpp文件路径也弄进去(注:经常有的时候在VS或者Xcode上面新加了cpp文件,忘记加到这里去,编译的时候老是通过不过,这个地方要小心点!),具体如下:


第三步,编写TestJNI.java文件(这个名字随便起,不过要对应VS上面调用的类名),代码如下:


然后运行,效果如下:


这里注明一下:Android工程的sdk版本必须是2.3以上才能运行正常。


关于多参数传递的问题:

举例:

java代码中有:

public static void showThree(bool b, int i)

那么对应的C++调用代码为:

void TestJNI::showThree(bool b, int i){
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)//判断当前是否为Android平台
    
    JniMethodInfo jmi;
    bool ishave = JniHelper::getStaticMethodInfo(jmi,Package_Utils_Path,"showThree","(ZI)V");
    
    if(ishave)
    {
        jboolean isShow = b;
        jint p = i;
        jmi.env->CallStaticVoidMethod(jmi.classID,jmi.methodID,isShow,p);
    }
#endif
}

上面代码中的"(ZI)V",表示:该函数包含两个参数,分别是:java中的boolean类型和int类型,返回值为void。

总结:获取多参数函数的时候,参数类型之间不用写分隔符。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值