android JNI 系列 三

主题:

● 获取Java类

● 访问Java属性

●访问Java方法

●创建Java对象

●抛异常

 

1. 获取Java类

    方法一:

    jclass clazz = env->GetObjectClass(thisObj);

    方法二:

    jclass cls = env->FindClass("com/lht/JNITest");

以上方法是先获取到Class对象,当然这是c++的写法,c的写法是不一定的,我是喜欢用c++的方式来实现JNI

 

2. 读写Java属性

以后是用到的JNI 函数

    jfieldID    (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);

    jobject     (*GetObjectField)(JNIEnv*, jobject, jfieldID);
    jboolean    (*GetBooleanField)(JNIEnv*, jobject, jfieldID);
    jbyte       (*GetByteField)(JNIEnv*, jobject, jfieldID);
    jchar       (*GetCharField)(JNIEnv*, jobject, jfieldID);
    jshort      (*GetShortField)(JNIEnv*, jobject, jfieldID);
    jint        (*GetIntField)(JNIEnv*, jobject, jfieldID);
    jlong       (*GetLongField)(JNIEnv*, jobject, jfieldID);
    jfloat      (*GetFloatField)(JNIEnv*, jobject, jfieldID);
    jdouble     (*GetDoubleField)(JNIEnv*, jobject, jfieldID);

    void        (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject);
    void        (*SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean);
    void        (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte);
    void        (*SetCharField)(JNIEnv*, jobject, jfieldID, jchar);
    void        (*SetShortField)(JNIEnv*, jobject, jfieldID, jshort);
    void        (*SetIntField)(JNIEnv*, jobject, jfieldID, jint);
    void        (*SetLongField)(JNIEnv*, jobject, jfieldID, jlong);
    void        (*SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat);
    void        (*SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble);

我们先看一下

jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);//这个方法相当的耗时,请不要频繁的使用,当读到以后应该保存起来

JNIEnv*就不用说了,jclass是要访问属性的类的class对象,如何获取已在上一节讲述了,第三个参数为属性名称,如你定义了一个String mName;那么参数为"mName",

第四个参数是属性的签名,mName的类型为String,那么它的签名应该是指"Ljava/lang/String;"

所以我们代码写成:jfieldID nameId = env->GetFieldID(class, "mName", "Ljava/lang/String;")

拿到nameId我们再来看看

jString name = (jString)env->GetObjectField(jObj, nameId);

jObj是java调用传入的this对象。

如果属性域是静态的,那么方法为GetStaticFieldID, GetStaticObjectField

获取完了以后,我们要设置呢?

env->SetObjectField(jObj, nameId, name); //第三个参数为值

 

3. 访问Java方法

根读写java属性的步骤一致。

先获取方法的ID

jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)

jclass, 就是要访问的类的类对象,是需要根据本篇的第一节的描述获取的jclass对象

name, 方法名称

sig, 方法的签名,如:“(Ljava/lang/String;I)V”

CallVoidMethod(jclass clazz,, methodID, ...);

CallVoidMethod(jclass clazz,, methodID, jvalue args[]);

CallVoidMethod(jclass clazz,, methodID, va_list args);

... ,  用来传递参数,这个相信在Java中用的比较的多,如println类,你可以在后面跟很多个参数,如jString,jint and so on.

jvalue是一个枚举类:

typedef union jvalue {
    jboolean    z;
    jbyte       b;
    jchar       c;
    jshort      s;
    jint        i;
    jlong       j;
    jfloat      f;
    jdouble     d;
    jobject     l;
} jvalue;

va_list,是c语言中用来解决变参的宏,

后面两个调用方法不用管,一般我们用第一个就够了。

调用静态的方法:

跟上面的没有什么区别,只是分别用GetStaticMethodID和CallStaticVoidMethod方法

CallStaticObjectMethod(class, methodid, env->newStringUTF("java.class.path"))

 

4. 在JNI中创建Java类对象

jobject NewObject(jclass clazz, jmethodID methodID, ...)

参数说明:

clazz, java类

jmethodID, 构造函数ID

..., 构造参数

 

5. 抛异常

有两个接口可以实现

jint        (*Throw)(JNIEnv*, jthrowable);
jint        (*ThrowNew)(JNIEnv *, jclass, const char *);

 

6. 创建Java虚拟机

在非JNI的代码中,我们可以通过创建一个Java虚拟机来访问Java类

JavaVMOption options[1];

JavaVMInitArgs vm_args;

JavaVM *jvm;

JNIEnv *env;

 

options[0].optionString = "-Djava.class.path=.";

memset(&vm_args, 0, sizeof(vm_args));

vm_args.version = JNI_VERSION_1_4;

vm_args.nOption = 1;

vm_args.options = options;

JNI_CreateJavaVM(&jvm, (void**) & env, &vm_args);

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值