android NDK 實用學習(五)-c++端調用java接口

1,閱讀此文章前請閱讀前面文章,以避免閱讀出現障礙;html

android NDK 實用學習(一)-獲取java端類及其類變量java

android NDK 實用學習(二)-java端對象成員賦值和獲取對象成員值android

android NDK 實用學習(三)- java端類對象的構造及使用c++

android NDK 實用學習(四)-類緩存緩存

2,java端類接口定義:jvm

 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, 使用:ide

 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類,代碼以下:post

 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 }
View Code

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,注意:ui

若是使用c++端調用java端接口時,就須要經過JniHelper::getEnv()接口獲取env。

相關文章
相關標籤/搜索