所有内容为记录学习过程,不是大牛尽情谅解。所有分析都参考深入理解Android 卷一
JNIEnv 是一个 与线程相关的代表JNI环境的结构体。(先记下,但是没明白)
JNIEnv 实际上提供了一些JNI系统函数,通过这些函数可以做到
1,调用java函数
2,操作jobject对象等很多事情
关于这个JNIEnv 还是不大明白但是继续看代码
通过JNIEnv 操作jobject
首先我们要了解操作jobject的实质是什么,一个java对象是由成员变量和成员函数组成,所谓的操作jobject的本质就应当是操作这些对象的成员变量和成员函数。所以应先看与成员变量和成员函数有关的内容。
1jfildID 和jmethodID 介绍
看这两个名字也知道 是成员变量的id 和 成员函数的id
在JNI中规定用jfieldID 和jmethodID 来表示JAVA类的成员变量和成员函数
通过 JNIEnv 的下面两个方法得到
jfieldID getFieldID(jclass clazz, const char *name , const char *sig)
jmethodID GetMethodID(jclass clazz, const char* name,const char*sig);
Jclass代表java类, name表示成员函数或者成员变量的名字,sig为这个函数和变量的签名信息
参考android_media_MediaScanner.cpp::MyMediaScannerClient 代码学习一下
对以上代码开始分析
60行 首先找到 android.media.MediaScannerClient类在JNI层中对应的jclass实例
65行 通过MediaScannerClient对象 取出里面的sanFile 函数的jmethodID
67行 通过MediaScannerClient对象 取出里面的handleStringTag 函数的 JmethodID
69 行 71 行一样的意义
并且将这些 jmethod 变量保存为MyMediaScannerClient 成员变量
为什么这里要保存呢,是因为 如果每次都通过env查询jmethodID 或者 jfieldID 的话 那么将影响程序的执行效率,所以在初始化的时候,就保存这种常用的方法的ID,以供后面使用。
那么 取出这些ID 后, 该如何使用呢?
看一下android_media_MediaScanner.cpp::MyMediaScannerClient::scanFile
通过JNIEnv 的 mEnv -> CallVoidMethod 方法 再把 jobject 和jMethodID 和对应的参数传进去,JNI层就可以调用java对象的函数了!!
实际上JNIEnv输出了一系列的类似于CallVoidMethod的函数,形式如下
NativeType Call<type>Method(JNIEnv *env , jobject obj , jmethodID methodID, 函数参数。。。)
其中type 对应Java函数的返回值类型,例如CallIntMethod 等等
上面这种方法时针对于非static函数的,如果想要调用java中国女的static 函数,则用JNIEnv输出的CallStatic<Type>Method系列函数
下面了解一下如何通过JNIEnv的jfieldID操作jobject的成员变量呢
//获取fieldID后 可以调用 Get<type>Field 系列的函数获取jobject对应的成员i按量,
NativeType Get<Type>Field(JNIEnv *env , jobject obj, jmethodID methodID)
或者通过Set<Type>Field系列函数 来改变jobject对应的成员比那两值
学到明白了jfieldID 和jmethodID的作用 也了解了该如何通过JNIEnv的函数来操作jobject。
该文章来源于 深入理解Android 卷一,为我自己看书以后的测试篇