Android JNI开发(2)--native方法调用Java方法

很多时候,我们在JNI代码中获取到了我们想要的值,需要返回到Java层,简单的情况下可以使用return某个值来实现。但是复杂情况下,我们需要不断地获取JNI中返回的值,我们就可以在JNI中主动去找Java中的方法,然后调用,并把JNI中的值作为Java方法的参数传入。如下:

//native方法将调用Java方法
JNIEXPORT void JNICALL nativeCallJava(JNIEnv *env, jobject thiz){
    object_global = (jobject)env->NewGlobalRef(thiz);
    JNIEnv *env = NULL;
    //先获取JNIEnv
    if (savedVm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        env = NULL;
    }
    //再通过FindClass来加载当前需要的类
    jclass clazz = env->FindClass("com/XXXX/jni/MainActivity");
    //获取当前类中的静态方法
    jmethodID method1 = env->GetStaticMethodID(clazz,"nativeCall","(Ljava/lang/String;)V");
    jstring result = env->NewStringUTF("aaaaaaaaa");//字符串
    env->CallStaticVoidMethod (clazz, method1,result);//调用静态方法
    //获取普通成员方法
    jmethodID method2 = env->GetMethodID(clazz,"nativeCall_nonStatic","(Ljava/lang/String;)V");
    //调用成员方法,这个时候第一个参数应该是对象
    env->CallVoidMethod (thiz, method2,result);
}

以上是借用JNI主动传进来的jobject ,它就代表对应的Java类的对象。然而有时候,我们没有这样的对象引用作为参数,就需要找到Java的对应的构造器获取Java类的一个对象。

//调用java的静态方法
NIEXPORT void JNICALL callJavaStaticMethod (JNIEnv *env, jclass cls)  
{  
    jclass clazz = NULL;  
    jstring str_arg = NULL;  
    jmethodID mid_static_method;  
    // 1、从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象  
    clazz =(*env)->FindClass(env,"com/study/jnilearn/ClassMethod");  
    if (clazz == NULL) {  
        return;  
    }  

    // 2、从clazz类中查找callStaticMethod方法  
    mid_static_method = (*env)->GetStaticMethodID(env,clazz,"callStaticMethod","(Ljava/lang/String;I)V");  
    if (mid_static_method == NULL) {  
        printf("找不到callStaticMethod这个静态方法。");  
        return;  
    }  

    // 3、调用clazz类的callStaticMethod静态方法  
    str_arg = (*env)->NewStringUTF(env,"我是静态方法");  
    //调用Java的静态方法不需要Java类的对象。后面需要传入参数。
    (*env)->CallStaticVoidMethod(env,clazz,mid_static_method, str_arg, 100);  
    // 删除局部引用  
    (*env)->DeleteLocalRef(env,clazz);  
    (*env)->DeleteLocalRef(env,str_arg);  
}  

/* 
 * 调用java的实例方法 
 */  
JNIEXPORT void JNICALL callJavaInstaceMethod  (JNIEnv *env, jclass cls)  
{  
    jclass clazz = NULL;  
    jobject jobj = NULL;  
    jmethodID mid_construct = NULL;  
    jmethodID mid_instance = NULL;  
    jstring str_arg = NULL;  
    // 1、从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象  
    clazz = (*env)->FindClass(env, "com/study/jnilearn/ClassMethod");  
    if (clazz == NULL) {  
        printf("找不到'com.study.jnilearn.ClassMethod'这个类");  
        return;  
    }  

    // 2、获取类的默认构造方法ID  ,没有参数
    mid_construct = (*env)->GetMethodID(env,clazz, "<init>","()V");  
    if (mid_construct == NULL) {  
        printf("找不到默认的构造方法");  
        return;  
    }  

    // 3、查找实例方法的ID  ,第三个参数传入java方法的名称。第四个是方法参数表达式
    mid_instance = (*env)->GetMethodID(env, clazz, "callInstanceMethod", "(Ljava/lang/String;I)V");  
    if (mid_instance == NULL) {  
        return;  
    }  

    // 4、创建该类的实例  
    jobj = (*env)->NewObject(env,clazz,mid_construct);  
    if (jobj == NULL) {  
        printf("在com.study.jnilearn.ClassMethod类中找不到callInstanceMethod方法");  
        return;  
    }  

    // 5、调用对象的实例方法  
    str_arg = (*env)->NewStringUTF(env,"我是实例方法");  //创建字符串的方法
    (*env)->CallVoidMethod(env,jobj,mid_instance,str_arg,200);  //调用方法,需要传入参数

    // 删除局部引用  
    (*env)->DeleteLocalRef(env,clazz);  
    (*env)->DeleteLocalRef(env,jobj);  
    (*env)->DeleteLocalRef(env,str_arg);  

以上在创建Java类的对象的时候,调用的默认的无参数构造器,如果调用的是有参数的构造器,就需要一下写法:

//获取Student的jclass
    jclass  studentClass=env->FindClass("com/xxxx/Student");
    //获取Student的构造方法ID
    jmethodID  studentCont=env->GetMethodID(studentClass,"<init>","(Ljava/lang/String;I)V");
    //实例化Student并传递参数
    jstring name = env->NewStringUTF("JIN 构造方法新建对象 宝强");
    jint age=30;
    //创建Student的对象,需要传入参数
    jobject student= env->NewObject(studentClass,studentCont,name,age);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值