Android JNI使用总结(二)
2015-10-13 23:53
429 查看
上一篇里面主要是JNI中一些函数的介绍,这篇博客就举个例子来说明这些函数的使用方法。
通过Uart发送消息;
接受Uart传送过来的消息;
因为这里的主要目的不是说明如何使用uart,所以我的这段代码中发送是通过调用下面的方法实现的:
接受是通过注册回调函数实现的。当uart处理机接受到消息之后,将调用我的回调函数。回调函数将消息处理后返回给java层的代码。
声明几个宏。
这几个宏是我在framework/base/service/jni中找到的,挺好用的。
声明全局变量。
声明native方法。
注册native方法。
本地初始化。
这个函数时在UartManagerService里调用的,所以刚好可以用来获取UartManagerService的实例。
实现发送代码。
实现接收的回调。
回调函数的参数是message结构体,而java中的回调函数的参数是int数组,所以这里要新建数组并填内容。
项目介绍
这个例子来源于我实际的项目。这段代码的作用是:通过Uart发送消息;
接受Uart传送过来的消息;
因为这里的主要目的不是说明如何使用uart,所以我的这段代码中发送是通过调用下面的方法实现的:
int uart_send( message *callmsg, // 待发送的消息 message *retmsg, // 发送消息之后的返回值 unsigned timeout // 发送超时 );
接受是通过注册回调函数实现的。当uart处理机接受到消息之后,将调用我的回调函数。回调函数将消息处理后返回给java层的代码。
声明几个宏。
#define FIND_CLASS(var, className) \ var = env->FindClass(className); \ LOG_FATAL_IF(! var, "Unable to find class " className); #define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ var = env->GetMethodID(clazz, methodName, methodDescriptor); \ LOG_FATAL_IF(! var, "Unable to find method " methodName); #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
这几个宏是我在framework/base/service/jni中找到的,挺好用的。
声明全局变量。
static struct { jmethodID recvMsgFromNative; // 这里将存储java类UartManagerService中的方法recvMsgFromNative的ID。 } gUartManagerServiceClassInfo; static jobject gUartManagerServiceObj; // 这个对象将存储UartManagerService对象的实例。 static jclass gUartManagerServiceClass; // 这个东西将存储UartManagerService的class。 static JavaVM * gJavaVM; // 这个就是我在上一遍博文的最后提到的全局的JavaVM对象,在必要的时候,将通过这个对象获取JNIEnv指针。
声明native方法。
static JNINativeMethod gUartManagerServiceMethods[] = { /* name, signature, funcPt */ { "nativeTest", "()V", (void*) nativeTest }, { "nativeInit", "()V", (void*) nativeInit } };
注册native方法。
int register_android_server_iflytek_uartmanagerservice(JNIEnv* env) { int res = jniRegisterNativeMethods(env, "com/android/server/iflytek/UartManagerService", gUartManagerServiceMethods, NELEM(gUartManagerServiceMethods) ); if(res < 0) ALOGD("Unable to register native methods."); env->GetJavaVM(&gJavaVM); return 0; }
本地初始化。
static void nativeInit(JNIEnv* env, jobject obj) { ALOGD("nativeInit() is called"); // 获取UartManagerService对象的实例 gUartManagerServiceObj = env->NewGlobalRef(obj); // Callbacks FIND_CLASS(gUartManagerServiceClass, "com/android/server/iflytek/UartManagerService"); GET_METHOD_ID(gUartManagerServiceClassInfo.recvMsgFromNative, gUartManagerServiceClass, "recvMsgFromNative", "([I)V"); // 注册回调 set_callback(get_msg_cb); }
这个函数时在UartManagerService里调用的,所以刚好可以用来获取UartManagerService的实例。
实现发送代码。
static void nativeTest(JNIEnv* env, jobject obj) { ALOGD("nativeTest() is called"); message callmsg; message retmsg; // 循环发送1000次 for (int i = 0; i < 1000; ++ i) { // 填充callmsg // …… // uart_send(&callmsg, &retmsg, 200); } }
实现接收的回调。
回调函数的参数是message结构体,而java中的回调函数的参数是int数组,所以这里要新建数组并填内容。
void get_msg_cb(message *evtmsg) { ALOGD("get_msg_cb() is called"); int i; JNIEnv* env; gJavaVM->AttachCurrentThread(&env, NULL); // 这里就是上一篇博文的最后提到的“在需要的时候”。因为这里没有JNIEnv指针,所以只能从gJavaVM中重新获取。 if(env == NULL){ ALOGD("JNIEnv is null"); return; } jintArray returnArray = env->NewIntArray(len); int * pArray = (int*)malloc(sizeof(int) * len); // 给本地数组赋值 pArray[0] = ……; pArray[1] = ……; for(i = 0; i < len; i++) { pArray[2+i] = evtmsg->data[i]; } // 将值赋给返回值 env->SetIntArrayRegion(returnArray, 0, len + 2, pArray); // 调用java中的函数 if(gUartManagerServiceObj != NULL){ env->CallVoidMethod(gUartManagerServiceObj, gUartManagerServiceClassInfo.recvMsgFromNative, returnArray); } // 释放内存 free(pArray); }
相关文章推荐
- Android学习实践:11.进度条ProgressBar
- android第一课:android开发环境搭建
- Android学习基本索引(三)——记录,没事自己看
- Android学习基本索引(二)——记录,没事自己看
- Google Android开发入门与实战
- 安卓孵化之路(二)——基于监听的事件处理机制
- Android内存优化之OOM
- android 组件 - Service小结
- Activity 生命周期及启动模式
- Android JNI使用总结(一)
- 2.Android support design NavigationView
- android jni使用
- Android_02_线性布局
- Android之ListView属性描述
- Android学习基本索引(一)——记录,没事自己看
- android WIFI开发
- Android本地视频播放器开发--ffmpeg解码视频文件中的音频(1)
- Android Fragment 生命周期及其API使用(建议使用自定义View替换Fragment)
- bin/ld.exe: error: cannot find -landroid等问题
- 如何跳过Nexus 7二代的开机设置