JNI是Android系统中Java与Native交互的桥梁
数据类型的转换
Java |
Native |
Signature |
byte |
jbyte |
B |
char |
jchar |
C |
double |
jdouble |
D |
float |
jfloat |
F |
int |
jint |
I |
short |
jshort |
S |
long |
jlong |
J |
boolean |
jboolean |
Z |
void |
void |
V |
String |
jstring |
Ljava/lang/String; |
Java具有重载方法,可以定义方法名相同,但参数不同的方法,所以通过方法签名和方法名就可以找到对应的Java方法。
但是方法签名
比较难写,可以使用如下方法:
1 2 3
| javac xxx.java javap -s -p xxx.class
|
JNIEnv
JNIEnv 是一个指向全部JNI方法的指针,该指针只在创建它的线程有效,不能跨线程传递,因此,不同线程的JNIEnv是彼此独立,可以调用Java的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13
| #if defined(__cplusplus) typedef _JNIEnv JNIEnv; typedef _JavaVM JavaVM; #else typedef const struct JNINativeInterface* JNIEnv; typedef const struct JNIInvokeInterface* JavaVM; #endif
------------------------------------------------------------------------
jfieldID GetFieldID(jclass clazz,const char *name,const char *sig); jmethodID GetFieldID(jclass clazz,const char *name,const char *sig);
|
其中GetFieldID方法的三个参数:
- jclass代表Java类
- name代表成员方法或者成员变量的名字
- sig为这个方法和变量的签名
通过JavaVM的AttachCurrentThread函数可以获取这个线程的JNIEnv,可以在不同的线程中调用Java方法,在使用AttachCurrentThread函数的线程退出前,调用DetachCurrentThread函数来释放资源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| static void android_media_MediaRecorder_native_init(JNIEnv *env){ jclass clazz; clazz = env->FindClass("android/media/MediaRecorder"); if (clazz == NULL) { return; } fields.context = env->GetFieldID(clazz, "mNativeContext", "J"); if (fields.context == NULL) { return; } fields.surface = env->GetFieldID(clazz, "mSurface", "Landroid/view/Surface;"); if (fields.surface == NULL) { return; } jclass surface = env->FindClass("android/view/Surface"); if (surface == NULL) { return; } fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V"); if (fields.post_event == NULL) { return; } }
struct fields_t { jfieldID context; jfieldID surface; jmethodID post_event; }; static fields_t fields;
void JNIMediaRecorderListener::notify(int msg, int ext1, int ext2){ ALOGV("JNIMediaRecorderListener::notify"); JNIEnv *env = AndroidRuntime::getJNIEnv(); env->CallStaticVoidMethod(mClass, fields.post_event, mObject, msg, ext1, ext2, NULL); }
|
参考:
http://liuwangshu.cn/tags/Android%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3JNI/