[Android5.0源码透析](四)JNI调用Java对象

一、得到静态(static)和实例(instance)的域与方法的JNI函数

函数  描述
GetFieldID  得到一个实例的域的ID
GetStaticFieldID  得到一个静态的域的ID
GetMethodID 得到一个实例的方法的ID
GetStaticMethodID

得到一个静态方法的ID

实例:

//创建一个class的引用
/**
* Lpackagename/classname; 
* L代表这是在描述一个对象类型
* packagename/classname是该对象耳朵class路径
* 请注意一定要以分号(;)结束
*/
jclass cls = (*env)->FindClass(env, "Lpackagename/classname;");  
jmethodID id = (*env)->GetMethodID(env, cls, "", "(D)V");  //注意这里方法的名称是"",它表示这是一个构造函数,而且构造参数是double型的
jobject obj = (*env)->NewObjectA(env, cls, id, args);  //获得一实例,args是构造函数的参数,它是一个jvalue*类型。

二、JNI函数的定义

在android系统中,使用了一种与传统定义Java JNI方式有所不同的方式定义Native函数,最主要的区别是,其在Android中使用了一种java和C函数的映射表数组,并在其中描述了函数的参数和返回值。该数组定义如下:

typedef struct {
    const char* name;//Java中函数的名字
    const char* signature;//描述了函数的参数和返回值
    void* fnPtr;//函数指针,指向C函数
} JNINativeMethod;

在使用时,第二个参数的传入值会像下面这些:

"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"

对于这些字符串的具体说明如下:

(1)"()"中的字符表示函数参数,"()"后面的表示函数的返回值。

(2)

字符对应关系表
字符 Java类型 C类型
V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
数组对应关系表
字符 Java类型 C类型
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]

如果需要传入Java对象时,则要以"L"开头,以";"结尾,中间使用"/"分隔包及类名。其对应的C函数名的参数为joblect(String类例外,String类对应的类为jstring)

如果Java函数位于一个嵌入类,则可以使用$作为类名间的分隔符。

如:"(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"

三、注册工作

//定义一个JNINativeMethod数组
static JNINativeMethod method[]={
    {
        "native_init"
        "()V"
        (void*)android_media_MediaScanner_native_init
    },
    ...
}
//注册数组
char* classname="xxxx";
int register(JNIEnv *env)
{
    return AndroidRuntime::registerNativeMethods(env,classname,method,NELEM(method));
}

四、在本地方法中调用Java对象的方法

1、获取所需的Java类

jclass cls = (*env)->GetObjectClass(env, obj);       // 使用GetObjectClass方法获取obj对应的jclass。 
jclass cls = (*env)->FindClass(“android/util/log”) // 直接搜索类名,需要是static修饰的类。

2、获取MethodID

/**
* env-->JNIEnv
* cls-->第一步获取的jclass
* "callback"-->要调用的方法名
* "(I)V"-->方法的Signature, 签名同前面的JNI规则。 
*/
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); 
//GetStaticMethodID(…),获取静态方法的ID使用GetMethdoID方法获取你要使用的方法的MethdoID

3、调用方法

/**
* env-->JNIEnv
* obj-->通过本地方法穿过来的jobject
* mid-->要调用的MethodID(即第二步获得的MethodID)
* depth-->方法需要的参数(对应方法的需求,添加相应的参数) 
*/
(*env)->CallVoidMethod(env, obj, mid, depth);// CallStaticIntMethod(….) , 调用静态方法

系统提供的调用方法函数:

CallVoidMethod
CallStaticVoidMethod
CallIntMethod
CallStaticVoidMethod
CallBooleanMethod
CallStaticVoidMethod
CallByteMethod
CallStaticVoidMethod

猜你喜欢

转载自blog.csdn.net/gengkui9897/article/details/81623645
今日推荐