cocos2d-x中通过jni调用android方法

前端之家收集整理的这篇文章主要介绍了cocos2d-x中通过jni调用android方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

最近的一个cocos项目有使用到JNI,结果又是通过百度来查找使用方法,为了方便以后查看,在这里小结一下,应该会比较适合初次使用Jni的小伙伴们:)


JNI是JavaNative Interface的缩写,中文Java本地调,是Java语言提供的一种通用接口,用于Java代码与本地化代码的交互。

所谓本地化代码(Native Code)是指已被编译为特定于处理器的二进制代码,如Windows下的DLL,MAC OS X下的SO文件

通过JNI可以实现C++与Java的相互调用


这里主要是讲解在Cocos2d-x中通过Jni调用Java方法

以下将会从创建一个新项目开始,完整讲解Jni的使用过程


1、创建一个Cocos2d-xC++项目,包名“com.game.UseJni”

2、在Eclipse中导入项目中的Android工程,在src目录下新建包“com.game.JniMethod”,并在包中新建一个java“JniMethod.java”。这里的名字都是随意取的,在C++调用时会用到。



在JniMethod.java中写了一些静态方法,供C++中调用


JniMethod.java

[java] view plain copy
  1. packagecom.game.JniMethod;
  2. importandroid.util.Log;
  3. publicclassJniMethod
  4. {
  5. //不带参数
  6. staticvoidAndroidFunc1()
  7. {
  8. Log.d("jni","AndroidFunc1called");
  9. }
  10. //带一个float参数
  11. voidAndroidFunc2(floatnumber)
  12. Log.d("jni","AndroidFunc2called:"+number);
  13. }
  14. //带一个String参数
  15. voidAndroidFunc3(Stringname)
  16. "AndroidFunc3called:"+name);
  17. //带两个参数
  18. voidAndroidFunc4(Stringname,intage)
  19. "AndroidFunc4called:"+age);
  20. //带一个boolean参数,并返回一个int
  21. intAndroidFunc5(booleanflag)
  22. "AndroidFunc5called");
  23. returnflag?10:100;
  24. //带一个int数组参数
  25. voidAndroidFunc6(intarr[])
  26. intsum=0;
  27. for(inti:arr)
  28. sum+=i;
  29. "AndroidFunc6called:"+sum);
  30. //返回一个int数组
  31. int[]AndroidFunc7()
  32. intarr[]={10,20,0); background-color:inherit">30,0); background-color:inherit">40};
  33. returnarr;
  34. }


3、用xcode打开项目的C++工程, 在Class目录下新建C++类JniMethod.h、JniMethod.cpp,在这个类中调用刚才写的Java静态方法





JniMethod.h
copy
    </pre><pre>

[cpp] copy
    //
  1. //JniMethod.h
  2. //UseJni
  3. //
  4. //Createdbytryon14-10-3.
  5. #ifndef__UseJni__JniMethod__
  6. #define__UseJni__JniMethod__
  7. #include<stdio.h>
  8. #ifdefined(ANDROID)
  9. classJniMethod
  10. public:
  11. voidcallAndroidFunc1();
  12. voidcallAndroidFunc2(floatnumber);
  13. voidcallAndroidFunc3(std::stringname);
  14. voidcallAndroidFunc4(std::stringname,intage);
  15. staticintcallAndroidFunc5(boolflag);
  16. voidcallAndroidFunc6(std::vector<int>arr);
  17. staticstd::vector<int>callAndroidFunc7();
  18. };
  19. #endif
  20. #endif/*defined(__UseJni__JniMethod__)*/

JniMethod.cpp

copy
    //JniMethod.cpp
  1. //#if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)
  2. #include"cocos2d.h"
  3. #include"JniMethod.h"
  4. #include"platform/android/jni/JniHelper.h"
  5. USING_NS_CC;
  6. //调用android静态方法:没有参数
  7. voidJniMethod::callAndroidFunc1()
  8. JniMethodInfominfo;
  9. boolisHave=JniHelper::getStaticMethodInfo(minfo,"com/game/JniMethod/JniMethod","AndroidFunc1","()V");
  10. CCASSERT(isHave,"jnicallAndroidFunc1notfound");
  11. if(isHave)
  12. minfo.env->CallStaticVoidMethod(minfo.classID,minfo.methodID);
  13. //调用android静态方法:一个float参数
  14. voidJniMethod::callAndroidFunc2(floatnumber)
  15. JniMethodInfominfo;
  16. "AndroidFunc2","(F)V");
  17. CCASSERT(isHave,"jnicallAndroidFunc1notfound");
  18. if(isHave)
  19. minfo.env->CallStaticVoidMethod(minfo.classID,minfo.methodID,number);
  20. //调用android静态方法:一个string参数
  21. voidJniMethod::callAndroidFunc3(std::stringname)
  22. "AndroidFunc3","(Ljava/lang/String;)V");
  23. "jnicallAndroidFunc3notfound");
  24. jstringjStr=minfo.env->NewStringUTF(name.c_str());
  25. //调用android静态方法:多个参数
  26. voidJniMethod::callAndroidFunc4(std::stringname,87); background-color:inherit; font-weight:bold">intage)
  27. "AndroidFunc4","(Ljava/lang/String;I)V");
  28. "jnicallAndroidFunc4notfound");
  29. jstringjName=minfo.env->NewStringUTF(name.c_str());
  30. intJniMethod::callAndroidFunc5(boolflag)
  31. "AndroidFunc5","(Z)I");
  32. "jnicallAndroidFunc5notfound");
  33. jintnum=minfo.env->CallStaticIntMethod(minfo.classID,flag);
  34. returnnum;
  35. return-1;
  36. voidJniMethod::callAndroidFunc6(std::vector<int>arr)
  37. "AndroidFunc6","([I)V");
  38. "jnicallAndroidFunc6notfound");
  39. jintArrayjarr=minfo.env->NewIntArray(arr.size());
  40. jint*intArr=minfo.env->GetIntArrayElements(jarr,NULL);
  41. for(inti=0;i<arr.size();++i)
  42. //http://www.2cto.com/kf/201312/268735.html
  43. intArr[i]=arr[i];
  44. std::vector<int>JniMethod::callAndroidFunc7()
  45. int>arr;
  46. "AndroidFunc7","()[I");
  47. "jnicallAndroidFunc7notfound");
  48. jintArrayjarr=(jintArray)minfo.env->CallStaticObjectMethod(minfo.classID,minfo.methodID);
  49. jsizelen=minfo.env->GetArrayLength(jarr);
  50. jint*intArr=minfo.env->GetIntArrayElements(jarr,NULL);
  51. inti=0;i<len;++i)
  52. arr.push_back(intArr[i]);
  53. returnarr;
  54. #endif

4、在HelloWorldScene.cpp中调用JniMethod.cpp的方法,这里是直接放到boolHelloWorld::init()方法调用

copy
    #ifdefined(ANDROID)
  1. JniMethod::callAndroidFunc1();
  2. JniMethod::callAndroidFunc2(3.14f);
  3. JniMethod::callAndroidFunc3("hello");
  4. JniMethod::callAndroidFunc4("hello",3);
  5. intret=JniMethod::callAndroidFunc5(true);
  6. log("callAndroidFunc5:%d",ret);
  7. int>arr6;
  8. arr6.push_back(1);
  9. arr6.push_back(20);
  10. arr6.push_back(300);
  11. JniMethod::callAndroidFunc6(arr6);
  12. int>arr7=JniMethod::callAndroidFunc7();
  13. inti:arr7)
  14. log("callAndroidFunc7:%i",i);
  15. #endif


5、修改UseJni/proj.android/jni工程目录下的Android.mk文件添加JniMethod.cpp

6、在终端运行UseJni/proj.android目录下的build_native.py,编译成功,可以看到生成了SO文件

7、回到Eclipse,刷新安卓工程然后运行,可以在日志中查看运行结果

Tag为“jni”的是在安卓中自己输出的日志,Tag为“Cocos2d-x debug info”的是在C++中输出的日志

8、程序写完了,这里说明一下上面的函数使用方法,主要是JniMethod.cpp中的内容

copy
    //定义Jni函数信息结构体
  1. JniMethodInfominfo;
copy
    //查找函数是否存在
  1. //第二个参数为函数所在的包名+类名,注意以“/”分隔
  2. //第三个参数为函数
  3. //最后一个参数是函数的参数与返回值的描述信息,括号里的是传入的参数类型,括号右边的是返回值类型,
  4. //AndroidFunc1为无参所以括号内为空没有返回值,括号右边的返回值类型为V
  5. "()V");
copy
    //AndroidFunc2的参数描述信息是"(F)V",传入参数为float(签名F),返回值为空(签名V)
  1. //AndroidFunc4的参数描述信息是"(Ljava/lang/String;I)V",传入参数为String(签名Ljava/lang/String;)和int(符号I),返回值为空(签名V)
  2. //AndroidFunc6的参数描述信息是"([I)V",传入参数为int[](签名[I),返回值为int(签名I)



参数返回值类型 的签名(Signature)与Java类型 的对应关系,有了这个对应关系以上写的函数就很好理解了




copy
    //调用Java静态函数,前两个参数为固定写法,从第三个参数起可以加自己传入的参数
  1. //没有返回值的静态函数调用为CallStaticVoidMethod,注意函数名中的Void
  2. //返回int的静态函数调用为CallStaticIntMethod,注意函数名中的Int,我在这犯了不少错。。。


下面列出常用的一些调用方法





callAndroidFunc7jint *intArr = minfo.env->GetIntArrayElements(jarr,NULL);

通过函数GetIntArrayElements来获得jintArray中的数组指针,然后通过指针操作数组元素


这里给出其它数组类型的函数,通过看Array Type的类型,可以看到不同类型的数组有不同的JNI类型名



9、参考文献

http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html#wp20949

http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html#wp23720

http://www.linuxidc.com/Linux/2011-10/44997.htm

http://xiaominghimi.blog.51cto.com/2614927/908818/

http://public0821.iteye.com/blog/423941

http://www.jb51.cc/article/p-qumwvlyp-qy.html

猜你在找的Cocos2d-x相关文章