http://my.oschina.net/blackylin/blog/95176
这里用上面的例子介绍jni通信。
1.新建一个android_ril_jni.c文件,当然也可以源码或其他地方考一个jni文件来修改。
#define LOG_TAG "GSMService_JNI" #include <jni.h> //#include <android/log.h> #include <assert.h> #include <string.h> //#include <nativehelper/JNIHelp.h> #include <pthread.h> #include <utils/Log.h> typedef struct{ jclass cbclass; jmethodID native_proc; jobject gsm; }fields_t; static fields_t fields; static JavaVM* g_vm = NULL; // ---------------------------------------------------------------------------- #define GSM_PKG_NAME "com/app/gsm/GSMService" extern int open_console(); static jboolean com_app_gsm_GSMService_init(JNIEnv *env, jobject thiz, jobject weak) { jclass clazz; clazz = (*env)->FindClass(env, GSM_PKG_NAME); if(clazz == NULL){ LOGE("Can't find class com/app/gsm/GSMService"); return 0; } fields.cbclass = (*env)->NewGlobalRef(env, clazz); fields.native_proc = (*env)->GetStaticMethodID(env, clazz, "native_proc", "(Ljava/lang/Object;IIILjava/lang/String;)I"); if (fields.native_proc == NULL) { LOGE("Can't find method native_proc in com//app/gsm/GSMService native_proc"); return 0; } if(fields.gsm == NULL){ fields.gsm = (*env)->NewGlobalRef(env,weak); } //打开串口 if(open_console() != 0){ LOGE("open console err..."); return 0; } return 1; } static JNIEnv* attach_jnienv() { jint result; JNIEnv *env = NULL; JavaVMAttachArgs args; args.version = JNI_VERSION_1_4; args.name = NULL; args.group = NULL; assert(g_vm != NULL); result = (*g_vm)->AttachCurrentThread(g_vm,&env,(void*)&args); if (result != JNI_OK) { LOGI("attach_jnienv attach thread failed\n"); return NULL; } return env; } static void detach_jnienv() { assert(g_vm != NULL); (*g_vm)->DetachCurrentThread(g_vm); } int com_native_proc(int msg,int p1,int p2,const char *incoming_num) { int ret = 0; JNIEnv * env = attach_jnienv(); LOGE("com_native_proc,msg=%d....start",msg); if (env && msg) { jstring jvalue = (*env)->NewStringUTF(env, incoming_num); ret = (*env)->CallStaticIntMethod(env,fields.cbclass, fields.native_proc, fields.gsm, msg,p1,p2,jvalue); detach_jnienv(); LOGE("com_native_proc,end,ret=%d",ret); } return ret; } static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = (*env)->FindClass(env, className); if (clazz == NULL) { return JNI_FALSE; } if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE; } static JNINativeMethod gMethods[] = { { "native_init", "(Ljava/lang/ref/WeakReference;)Z",(void *) com_app_gsm_GSMService_init }, }; jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; LOGE("zouxy Enter JNI_OnLoad"); if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("ERROR: GetEnv failed\n"); goto bail; } assert(env != NULL); g_vm = vm; result = registerNativeMethods(env, GSM_PKG_NAME, gMethods, sizeof(gMethods) / sizeof(gMethods[0])); if (result < 0) { LOGE("ERROR: registerNativeMethods failed,result=%d...\n",result); goto bail; } LOGE(" Enter com_app_gsm_GSMService_init"); result = JNI_VERSION_1_4; LOGE("Exit JNI_OnLoad"); bail: return result; }启动GSMService服务,加载static中代码libril_jni.so.
jint JNI_OnLoad(JavaVM* vm, void* reserved)
c映射对应java的函数:
static JNINativeMethod gMethods[] = { { "native_init", "(Ljava/lang/ref/WeakReference;)Z",(void *) com_app_gsm_GSMService_init }, };
这里在之前GSMService构造方法中有调用native_init方法,就是调用这个jni里com_app_gsm_GSMService_init方法。需要注意的是对应的参数,其中Z表示返回值为boolean,其他对应的可以查找源码中jni.h中详细定义。此处就实现java调用c的过程。
2.C调用java
int com_native_proc(int msg,int p1,int p2,const char *incoming_num) { int ret = 0; JNIEnv * env = attach_jnienv(); LOGE("com_native_proc,msg=%d....start",msg); if (env && msg) { jstring jvalue = (*env)->NewStringUTF(env, incoming_num); ret = (*env)->CallStaticIntMethod(env,fields.cbclass, fields.native_proc, fields.gsm, msg,p1,p2,jvalue); detach_jnienv(); LOGE("com_native_proc,end,ret=%d",ret); } return ret; }这个jni里的函数,相当于一个透传作用,被其他c函数调用。
ret = (*env)->CallStaticIntMethod(env,fields.cbclass, fields.native_proc, fields.gsm, msg,p1,p2,jvalue);通过CallStaticInitMethod函数掉用java里的方法,同样这里值得注意的是方法类型、参数和返回值,不然都会报错;c文件的jni和cpp的jni有些不同,就那这个函数来说,cpp的jni没有这个env这个参数,具体的可以参照源码中jni.h。
期待更多的补充O(∩_∩)O.......