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 }

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

android NDK 实用学习(五)-c++端调用java接口的相关文章

基于 Android NDK 的学习之旅----- C调用Java

http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html 基于 Android NDK 的学习之旅----- C调用Java许多成熟的C引擎要移植到Android 平台上使用 , 一般都会 提供 一些接口, 让Android sdk 和 jdk 实现. 下文将会介绍 C 如何 通过 JNI 层调用 Java 的静态和非静态方法. 1.主要流程 1.  新建一个测试类TestProvider.java a)       

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

1,关于java端类及接口定义请参考: android NDK 实用学习-获取java端类及其类变量 2,对传过来的参数进行赋值: 对bool类型成员进行赋值  env->SetBooleanField(jobj, jfbdata, false); 对double类型成员进行赋值 env->SetDoubleField(jobj, jfddata, 209.22); 对int类型成员进行赋值 env->SetIntField(jobj, jfidata, 3653); 对byte类型成员

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

1,读此文章前我假设你已经读过: android NDK 实用学习-获取java端类及其类变量 android NDK 实用学习-java端对象成员赋值和获取对象成员值 2,java端类对象的构造: ①首先获取类; ②获取类的无参构造函数: jmethodID initID = env->GetMethodID(jcSetDataMgr, "<init>", "()V"); ③构造类实例: jobject jresult = env->New

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

近期为android 端项目包装一些c++代码,故学习ndk相关知识,现总结如下: 1,java与c++类型参照图: 2,此测试中使用的java类: 1 package com.dasea.test.core; 2 public class TestSetData { 3 // 主要是类ID和字段ID,方法ID的缓存 4 static { 5 OnNative(); 6 } 7 8 public native static void OnNative(); 9 10 public boolean

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

1,为什么需要类缓存: 答:由于频繁的查找类及类成员变量需要很大的时间与空间开销,可参考如下文章: http://www.ibm.com/developerworks/cn/java/j-jni/ http://www.28im.com/java/a2379737.html 2,缓存时需要在java类使用static,如下: 1 package com.dasea.test.core; 2 public class TestSetData { 3 // 主要是类ID和字段ID,方法ID的缓存 4

基于 Android NDK 的学习之旅-----序言

http://www.cnblogs.com/luxiaofeng54/tag/android/default.html?page=1 基于 Android NDK 的学习之旅-----目录 duicky 2011-09-15 16:34 阅读:3035 评论:2 基于 Android NDK 的学习之旅-----资源释放 duicky 2011-08-21 14:29 阅读:6173 评论:0 基于 Android NDK 的学习之旅-----数据传输二(引用数据类型)(附源码) duicky

【转】基于 Android NDK 的学习之旅-----数据传输(引用数据类型)

原文网址:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/20/2147086.html 基于 Android NDK 的学习之旅-----数据传输二(引用数据类型)(附源码) 基于 Android NDK 的学习之旅-----数据传输(引用数据类型) 接着上篇文章继续讲.主要关于引用类型的数据传输,本文将介绍字符串传输和自定义对象的传输. 1.主要流程 1.  String 字符串传输 a)         上层定义一个native的方法

Android NDK开发篇(五):Java与原生代码通信(数据操作)

尽管说使用NDK能够提高Android程序的运行效率,可是调用起来还是略微有点麻烦.NDK能够直接使用Java的原生数据类型,而引用类型,由于Java的引用类型的实如今NDK被屏蔽了,所以在NDK使用Java的引用类型则要做对应的处理. 一.对引用数据类型的操作 尽管Java的引用类型的实如今NDK被屏蔽了,JNI还是提供了一组API,通过JNIEnv接口指针提供原生方法改动和使用Java的引用类型. 1.字符串操作 JNI把Java的字符串当作引用来处理,在NDK中使用Java的字符串,须要相

Android NDK开发(五)--C代码回调Java代码【转】

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41862479 在上篇博客里了解了Java层是怎样传递数据到C层代码,并且熟悉了大部分的实际开发知识,基本上掌握这些就可以做一个基本的NDK开发了,但是光是了解Java回调C层的数据是不是还不够啊,考虑问题要考虑可逆性,Java能回调C,那么C能否反过来回调Java呢?答案是肯定可以的,这篇博客就介绍一个C语言如何调用Java层的代码.以下是一些问题场景,我们带着这个问题场景来分析