1,阅读此文章前请阅读前面文章,以免阅读出现障碍;
android NDK 实用学习(一)-获取java端类及其类变量
android NDK 实用学习(二)-java端对象成员赋值和获取对象成员值
android NDK 实用学习(三)- java端类对象的构造及使用
2,java端类接口定义:
1 public class RTKNativeManager { 2 // 其他接口 3 4 // 开给c++端的接口 5 public static void notifyResolveResult(short id, TestSetData setData) { 6 Log.d(TAG, "notifyResult start"); 7 8 boolean bb = setData.bData; 9 int ii = setData.iData; 10 String msg = String.format("get msg: %b-%d", bb, ii); 11 Log.d(TAG, msg); 12 13 Log.d(TAG, "notifyResult end!"); 14 } 15 }
3, c++ 端获取类接口:
1 // 获取类 2 jclass jnativeMgr = NULL; 3 jmethodID jnotifyKQResolveResult = NULL; 4 5 // 获取类和方法 6 jnativeMgr = env->FindClass("com/dasea/test/core/RTKNativeManager"); 7 8 jnotifyKQResolveResult = env->GetStaticMethodID( 9 jnativeMgr, "notifyKQResolveResult", "(SLcom/dasea/test/core/TestSetData;)V");
3, 使用:
1 void Jni_Call_Java_notifyResolveResult(short id){ 2 DEBUG_OUT(" WHAT QINGKUANG!!"); 3 4 JNIEnv* env = JniHelper::getEnv(); 5 if (NULL == env) 6 { 7 DEBUG_OUT(" ENV IS NULL!"); 8 return ; 9 } 10 11 // 获取类和方法 12 jclass jnativeMgr = env->FindClass("com/dasea/test/core/RTKNativeManager"); 13 if (NULL == jnativeMgr) 14 { 15 DEBUG_OUT("Native mgr is NULL;!"); 16 } 17 18 // 构造jni实例 19 jclass jcSetDataMgr = env->FindClass("com/dasea/test/core/TestSetData"); 20 if(NULL == jcSetDataMgr){ 21 DEBUG_OUT("Not find class!"); 22 return ; 23 } 24 25 DEBUG_OUT("AllocObject object !"); 26 jmethodID initID = env->GetMethodID(jcSetDataMgr, "<init>", "()V"); 27 jobject jresult = env->NewObject(jcSetDataMgr, initID); 28 29 if (NULL == jresult || env->ExceptionOccurred()) 30 { 31 DEBUG_OUT("Construct object failed!"); 32 return ; 33 } 34 35 // 成员变量赋值,可以参考前面几篇文章 36 37 DEBUG_OUT("CallStaticVoidMethod"); 38 39 // 调用静态方法 40 env->CallStaticVoidMethod(jnativeMgr, jnotifyKQResolveResult , 20, jresult); 41 }
4,上面代码中有Jnihelper类,代码如下:
1 #ifndef __ANDROID_JNI_HELPER_H__ 2 #define __ANDROID_JNI_HELPER_H__ 3 4 #include <jni.h> 5 #include <string> 6 7 typedef struct JniMethodInfo_ { 8 JNIEnv * env; 9 jclass classID; 10 jmethodID methodID; 11 } JniMethodInfo; 12 13 class JniHelper { 14 public: 15 static void setJavaVM(JavaVM *javaVM); 16 static JavaVM* getJavaVM(); 17 static JNIEnv* getEnv(); 18 19 static bool setClassLoaderFrom(jobject activityInstance); 20 static bool getStaticMethodInfo(JniMethodInfo &methodinfo, 21 const char *className, const char *methodName, 22 const char *paramCode); 23 static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, 24 const char *methodName, const char *paramCode); 25 26 static std::string jstring2string(jstring str); 27 28 static jmethodID loadclassMethod_methodID; 29 static jobject classloader; 30 31 private: 32 static JNIEnv* cacheEnv(JavaVM* jvm); 33 34 static bool getMethodInfo_DefaultClassLoader(JniMethodInfo &methodinfo, 35 const char *className, const char *methodName, 36 const char *paramCode); 37 38 static JavaVM* _psJavaVM; 39 }; 40 41 #endif // __ANDROID_JNI_HELPER_H__
1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2013-2014 Chukong Technologies Inc. 4 5 http://www.cocos2d-x.org 6 7 Permission is hereby granted, free of charge, to any person obtaining a copy 8 of this software and associated documentation files (the "Software"), to deal 9 in the Software without restriction, including without limitation the rights 10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 copies of the Software, and to permit persons to whom the Software is 12 furnished to do so, subject to the following conditions: 13 14 The above copyright notice and this permission notice shall be included in 15 all copies or substantial portions of the Software. 16 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 THE SOFTWARE. 24 ****************************************************************************/ 25 #include "JniHelper.h" 26 #include <string.h> 27 #include <pthread.h> 28 #include "CBasePara.h" 29 30 static pthread_key_t g_key; 31 32 jclass _getClassID(const char *className) { 33 if (NULL == className) { 34 return NULL; 35 } 36 37 JNIEnv* env = JniHelper::getEnv(); 38 39 jstring _jstrClassName = env->NewStringUTF(className); 40 41 // jclass _clazz = (jclass) env->CallObjectMethod(JniHelper::classloader, 42 // JniHelper::loadclassMethod_methodID, 43 // _jstrClassName); 44 45 jclass _clazz = (jclass) env->FindClass(className); 46 47 if (NULL == _clazz) { 48 DEBUG_OUT("Classloader failed to find class of %s", className); 49 env->ExceptionClear(); 50 } 51 52 env->DeleteLocalRef(_jstrClassName); 53 54 return _clazz; 55 } 56 57 JavaVM* JniHelper::_psJavaVM = NULL; 58 jmethodID JniHelper::loadclassMethod_methodID = NULL; 59 jobject JniHelper::classloader = NULL; 60 61 JavaVM* JniHelper::getJavaVM() { 62 pthread_t thisthread = pthread_self(); 63 //LOGD("JniHelper::getJavaVM(), pthread_self() = %ld", thisthread); 64 return _psJavaVM; 65 } 66 67 void JniHelper::setJavaVM(JavaVM *javaVM) { 68 pthread_t thisthread = pthread_self(); 69 //LOGD("JniHelper::setJavaVM(%p), pthread_self() = %ld", javaVM, thisthread); 70 _psJavaVM = javaVM; 71 72 pthread_key_create(&g_key, NULL); 73 } 74 75 JNIEnv* JniHelper::cacheEnv(JavaVM* jvm) { 76 JNIEnv* _env = NULL; 77 // get jni environment 78 jint ret = jvm->GetEnv((void**) &_env, JNI_VERSION_1_4); 79 80 switch (ret) { 81 case JNI_OK: 82 // Success! 83 pthread_setspecific(g_key, _env); 84 return _env; 85 86 case JNI_EDETACHED: 87 // Thread not attached 88 89 // TODO : If calling AttachCurrentThread() on a native thread 90 // must call DetachCurrentThread() in future. 91 // see: http://developer.android.com/guide/practices/design/jni.html 92 93 if (jvm->AttachCurrentThread(&_env, NULL) < 0) { 94 DEBUG_OUT( 95 "Failed to get the environment using AttachCurrentThread()"); 96 97 return NULL; 98 } else { 99 // Success : Attached and obtained JNIEnv! 100 pthread_setspecific(g_key, _env); 101 return _env; 102 } 103 104 case JNI_EVERSION: 105 // Cannot recover from this error 106 DEBUG_OUT("JNI interface version 1.4 not supported"); 107 default: 108 DEBUG_OUT("Failed to get the environment using GetEnv()"); 109 return NULL; 110 } 111 } 112 113 JNIEnv* JniHelper::getEnv() { 114 JNIEnv *_env = (JNIEnv *) pthread_getspecific(g_key); 115 if (_env == NULL) 116 _env = JniHelper::cacheEnv(_psJavaVM); 117 return _env; 118 } 119 120 bool JniHelper::setClassLoaderFrom(jobject activityinstance) { 121 JniMethodInfo _getclassloaderMethod; 122 if (!JniHelper::getMethodInfo_DefaultClassLoader(_getclassloaderMethod, 123 "android/content/Context", "getClassLoader", 124 "()Ljava/lang/ClassLoader;")) { 125 return false; 126 } 127 128 jobject _c = JniHelper::getEnv()->CallObjectMethod(activityinstance, 129 _getclassloaderMethod.methodID); 130 131 if (NULL == _c) { 132 return false; 133 } 134 135 JniMethodInfo _m; 136 if (!JniHelper::getMethodInfo_DefaultClassLoader(_m, 137 "java/lang/ClassLoader", "loadClass", 138 "(Ljava/lang/String;)Ljava/lang/Class;")) { 139 return false; 140 } 141 142 JniHelper::classloader = JniHelper::getEnv()->NewGlobalRef(_c); 143 JniHelper::loadclassMethod_methodID = _m.methodID; 144 145 return true; 146 } 147 148 bool JniHelper::getStaticMethodInfo(JniMethodInfo &methodinfo, 149 const char *className, const char *methodName, const char *paramCode) { 150 if ((NULL == className) || (NULL == methodName) || (NULL == paramCode)) { 151 return false; 152 } 153 154 JNIEnv *env = JniHelper::getEnv(); 155 if (!env) { 156 DEBUG_OUT("Failed to get JNIEnv"); 157 return false; 158 } 159 160 jclass classID = _getClassID(className); 161 if (!classID) { 162 DEBUG_OUT("Failed to find class %s", className); 163 env->ExceptionClear(); 164 return false; 165 } 166 167 jmethodID methodID = env->GetStaticMethodID(classID, methodName, paramCode); 168 if (!methodID) { 169 DEBUG_OUT("Failed to find static method id of %s", methodName); 170 env->ExceptionClear(); 171 return false; 172 } 173 174 methodinfo.classID = classID; 175 methodinfo.env = env; 176 methodinfo.methodID = methodID; 177 return true; 178 } 179 180 bool JniHelper::getMethodInfo_DefaultClassLoader(JniMethodInfo &methodinfo, 181 const char *className, const char *methodName, const char *paramCode) { 182 if ((NULL == className) || (NULL == methodName) || (NULL == paramCode)) { 183 return false; 184 } 185 186 JNIEnv *env = JniHelper::getEnv(); 187 if (!env) { 188 return false; 189 } 190 191 jclass classID = env->FindClass(className); 192 if (!classID) { 193 DEBUG_OUT("Failed to find class %s", className); 194 env->ExceptionClear(); 195 return false; 196 } 197 198 jmethodID methodID = env->GetMethodID(classID, methodName, paramCode); 199 if (!methodID) { 200 DEBUG_OUT("Failed to find method id of %s", methodName); 201 env->ExceptionClear(); 202 return false; 203 } 204 205 methodinfo.classID = classID; 206 methodinfo.env = env; 207 methodinfo.methodID = methodID; 208 209 return true; 210 } 211 212 bool JniHelper::getMethodInfo(JniMethodInfo &methodinfo, const char *className, 213 const char *methodName, const char *paramCode) { 214 if ((NULL == className) || (NULL == methodName) || (NULL == paramCode)) { 215 return false; 216 } 217 218 JNIEnv *env = JniHelper::getEnv(); 219 if (!env) { 220 return false; 221 } 222 223 jclass classID = _getClassID(className); 224 if (!classID) { 225 DEBUG_OUT("Failed to find class %s", className); 226 env->ExceptionClear(); 227 return false; 228 } 229 230 jmethodID methodID = env->GetMethodID(classID, methodName, paramCode); 231 if (!methodID) { 232 DEBUG_OUT("Failed to find method id of %s", methodName); 233 env->ExceptionClear(); 234 return false; 235 } 236 237 methodinfo.classID = classID; 238 methodinfo.env = env; 239 methodinfo.methodID = methodID; 240 241 return true; 242 } 243 244 std::string JniHelper::jstring2string(jstring jstr) { 245 if (jstr == NULL) { 246 return ""; 247 } 248 249 JNIEnv *env = JniHelper::getEnv(); 250 if (!env) { 251 return NULL; 252 } 253 254 const char* chars = env->GetStringUTFChars(jstr, NULL); 255 std::string ret(chars); 256 env->ReleaseStringUTFChars(jstr, chars); 257 258 return ret; 259 }
5,在c++端定义JNI_OnLoad接口:
1 jint JNI_OnLoad(JavaVM *vm, void *reserved) { 2 JniHelper::setJavaVM(vm); 3 4 return JNI_VERSION_1_4; 5 }
6,注意:
如果使用c++端调用java端接口时,就需要通过JniHelper::getEnv()接口获取env。
时间: 2024-11-04 19:38:44