android NDK 实用学习(五)-c++端调用java接口

1,阅读此文章前请阅读前面文章,以免阅读出现障碍;

android NDK 实用学习(一)-获取java端类及其类变量

android NDK 实用学习(二)-java端对象成员赋值和获取对象成员值

android NDK 实用学习(三)- java端类对象的构造及使用

android NDK 实用学习(四)-类缓存

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

扫描二维码关注公众号,回复: 6623001 查看本文章

如果使用c++端调用java端接口时,就需要通过JniHelper::getEnv()接口获取env。

 
 

转载于:https://www.cnblogs.com/dhf-0214/p/4612946.html

猜你喜欢

转载自blog.csdn.net/weixin_34290390/article/details/93206585
今日推荐