(1)通过AndroID sdk的API得到应用程序的包名(Packagename),然后传递给c++层函数。
(2)通过c++函数调用AndroID的java层函数,显示一个对话框,点击按钮退出程序。
1. 首先来简单学习一下JNI的相关知识,我这篇文章中简单实现了怎么在AndroID Java层调用c++函数。要想使用JNI,必须得包含头文件,androID是使用ndk编译c/c++的,这里jni.h文件位于:\androID-ndk-r8b\platforms\androID-14\arch-arm\usr\include\jni.h,该文件定义了所有和JNI相关的数据类型和接口。下面是相关代码片段:
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | # include <inttypes.h> /* C99 */ typedef uint8_t jboolean; /* unsigned 8 bits */ int8_t jbyte; /* signed 8 bits */ uint16_t jchar; /* unsigned 16 bits */ int16_t Jshort; /* signed 16 bits */ int32_t jint; /* signed 32 bits */ int64_t jlong; /* signed 64 bits */ typedef float jfloat; /* 32-bit IEEE 754 */ double jdouble; /* 64-bit IEEE 754 */ #else unsigned char jboolean; /* unsigned 8 bits */ signed char jbyte; /* signed 8 bits */ short jchar; /* unsigned 16 bits */ Jshort; /* signed 16 bits */ int jint; /* signed 32 bits */ long long jlong; /* signed 64 bits */ /* 32-bit IEEE 754 */ /* 64-bit IEEE 754 */ #endif /* "cardinal indices and sizes" */ jint Jsize; #ifdef __cplusplus /* * Reference types,in C++ */ class _jobject {}; _jclass : public _jobject {}; _Jstring : _jobject {}; _jarray : _jobject {}; _jobjectArray : _jarray {}; _jbooleanArray : _jarray {}; _jbyteArray : _jarray {}; _jchararray : _jarray {}; _JshortArray : _jarray {}; @H_334_403@ _jintArray : _jarray {}; _jlongArray : _jarray {}; _jfloatArray : _jarray {}; _jdoubleArray : _jarray {}; _jthrowable : _jobject {}; _jobject* jobject; _jclass* jclass; _Jstring* Jstring; _jarray* jarray; _jobjectArray* jobjectArray; _jbooleanArray* jbooleanArray; _jbyteArray* jbyteArray; _jchararray* jchararray; _JshortArray* JshortArray; _jintArray* jintArray; _jlongArray* jlongArray; _jfloatArray* jfloatArray; _jdoubleArray* jdoubleArray; _jthrowable* jthrowable; _jobject* jweak; #else /* not __cplusplus */ /* */ typedef voID * jobject; jobject jclass; jobject Jstring; jobject jarray; jarray jobjectArray; jarray jbooleanArray; jarray jbyteArray; jarray jchararray; jarray JshortArray; jarray jintArray; jarray jlongArray; jarray jfloatArray; jarray jdoubleArray; jobject jthrowable; jobject jweak; #endif /* not __cplusplus */ |
struct _jnienv { /* do not rename this; it does not seem to be entirely opaque */ const JNINativeInterface* functions; #if defined(__cplusplus) jint GetVersion() { return functions->GetVersion( this ); } jclass defineClass( const *name,jobject loader, const jbyte* buf, Jsize bufLen) functions->defineClass( ,name,loader,buf,bufLen); } jclass FindClass( * name) functions->FindClass( // 这里省略其他函数... } |
JniMethodInfo_ { jnienv * env; jclass classID; jmethodID methodID; } JniMethodInfo; CC_DLL JniHelper { : static JavaVM* getJavaVM(); static setJavaVM(JavaVM *javaVM); * getExternalAssetPath(); setExternalAssetPath( * externalAssetPath); jclass getClassID( *classname,jnienv *env=0); static bool getStaticmethodInfo(JniMethodInfo &methodinfo,monospace!important; Font-size:1em!important; min-height:auto!important"> *methodname,monospace!important; Font-size:1em!important; min-height:auto!important"> *paramCode); getmethodInfo(JniMethodInfo &methodinfo,monospace!important; Font-size:1em!important; min-height:auto!important"> *paramCode); std::string Jstring2string(Jstring str); private : JavaVM *m_psJavaVM; std::string m_externalAssetPath; }; |
(1)getStaticmethodInfo
用来判断Java的类静态函数是否存在,并初始化结构体JniMethodInfo,该结构体封装了jnienv*和java.lang.class对象、函数ID。这样就可以使用jnienv*调用 CallStaticXXXMethod(jclass clazz,jmethodID methodID,…)和 CallXXXMethod(jobject obj,…)等常用函数(XXX替换为函数返回值类型,如:VoID,Int等)。
第一个参数为JniMethodInfo,第二个参数是类的绝对路径,第三个参数是函数名,第四个参数是函数签名(参数和返回类型),示例代码如下:
if (JniHelper::getStaticmethodInfo(t,CLASS_name, "showTipDialog" "(Ljava/lang/String;Ljava/lang/String;)V" )) { //... } |
@H_301_9@ (2)getmethodInfo
该函数与getStaticmethodInfo类似,用于java类的非静态函数。 @H_301_9@ 2. 下面开始实现文章开头所述的两个功能,本文是在cocos2d-x 2.0版本 自适应屏幕分辨率demo的基础上添加的。
(1)利用cocos2d-x创建一个AndroID工程,名为JniTest,包名为com.alexzhou.jni,此时该包下会自动生成一个JniTest.java文件。
(2)首先来实现把应用程序的包名传递给c++函数,在包下创建JniTestHelper.java,该类封装了给c++调用的函数,添加如下代码:
private static Handler mHandler; public static voID init(Handler handler) { @H_419_903@ JniTestHelper.mHandler = handler; } native setPackagename(String packagename); |
protected voID onCreate(Bundle savedInstanceState){ @H_419_903@ super .onCreate(savedInstanceState); @H_419_903@JniTestHelper.init(mHandler); @H_419_903@JniTestHelper.setPackagename( this .getPackagename()); @H_419_903@} |
test.h
#ifndef TEST_H #define TEST_H #endif |
#include "cocos2d.h" #include <jni.h> #include "platform/androID/jni/JniHelper.h" #include "test.h" #include "JniTest.h" #define CLASS_name "com/alexzhou/jni/JniTestHelper" using namespace cocos2d; extern "C" { Java_com_alexzhou_jni_JniTestHelper_setPackagename(jnienv *env,jobject thiz,Jstring packagename) { *pkgname = env->GetStringUTFChars(packagename,NulL); setPackagename(pkgname); env->ReleaseStringUTFChars(packagename,pkgname); } } |
(5)现在编写c++函数,在Classes目录下创建JniTest.h,代码如下:
#ifndef JNI_TEST_H #define JNI_TEST_H #include "cocos2d.h" cocos2d; setPackagename( *packagename) { cclog( "packagename: %s" } #endif |
LOCAL_SRC_fileS := hellocpp /main .cpp \ hellocpp /test .cpp |
COCOS2DX_ROOT= "/cygdrive/e/cocos2d-x/cocos2d-2.0-x-2.0.4" "NDK_MODulE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/androID/prebuilt:${APP_ROOT}" |
(8)现在来实现通过c++函数调用java层函数,显示一个对话框。在JniTestHelper.java添加如下代码:
exitApp(); showTipDialog( final String Title, String text) Message msg = mHandler.obtainMessage(); @H_419_903@msg.what = JniTest.SHOW_DIALOG; @H_419_903@DialogMessage dm = new DialogMessage(); @H_419_903@dm.Title = Title; @H_419_903@dm.msg = text; @H_419_903@msg.obj = dm; @H_419_903@msg.sendToTarget(); } |
/** author:alexzhou email :zhoujiangbohai@163.com date :2012-12-14 @H_419_903@ **/ class DialogMessage { public String Title; @H_419_903@String msg; } |
final int SHOW_DIALOG = 0x0001 ; private Handler mHandler = Handler() @H_419_903@ @OverrIDe @H_419_903@ handleMessage(Message msg) { switch (msg.what) @H_419_903@{ case SHOW_DIALOG: @H_419_903@DialogMessage dm = (DialogMessage)msg.obj; @H_419_903@AlertDialog.Builder(JniTest. ) @H_419_903@.setTitle(dm.Title) @H_419_903@.setMessage(dm.msg).setNegativebutton( "cancle" DialogInterface.OnClickListener() { @OverrIDe @H_419_903@ onClick(DialogInterface dialog,153)!important">int which) { @H_419_903@dialog.dismiss(); @H_419_903@} @H_419_903@}) @H_419_903@.setPositivebutton( "Ok" @OverrIDe @H_419_903@which) { @H_419_903@dialog.dismiss(); @H_419_903@JniTestHelper.exitApp(); @H_419_903@} @H_419_903@}) @H_419_903@.create().show(); break ; @H_419_903@} @H_419_903@} @H_419_903@}; |
test.h
*msg) { JniMethodInfo t; )) { Jstring jTitle = t.env->NewStringUTF(Title); Jstring jMsg = t.env->NewStringUTF(msg); t.env->CallStaticVoIDMethod(t.classID,t.methodID,jTitle,jMsg); t.env->DeleteLocalRef(jTitle); t.env->DeleteLocalRef(jMsg); } } { setPackagename(pkgname); } Java_com_alexzhou_jni_JniTestHelper_exitApp(jnienv *env,jobject thiz) { exitApp(); } } |
@H_301_9@ 源码下载地址:http://download.csdn.net/detail/zhoujianghai/4890792 @H_301_9@
@H_301_9@ from:http://codingnow.cn/cocos2d-x/992.html 总结
以上是内存溢出为你收集整理的cocos2d-x 通过JNI实现c/c++和Android的java层函数互调全部内容,希望文章能够帮你解决cocos2d-x 通过JNI实现c/c++和Android的java层函数互调所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)