Kotlin开发jni程序 二.C调用java/kotlin方法和属性

首先我们声明kotlin的几个方法和属性,如下

package com.example.firstjni

import android.util.Log

object NDKUtil{
    val name = "djfklsd"
    external fun updateArray(array: IntArray)
    external fun updateArrayByPointer(array: IntArray)
    external fun callStaticMethod(i: Int)
    external fun callStaticMethod(i: Long)
    external fun callInstanceMethod(i: Int)
    external fun callInstanceMethod(s: String,i: Long)

    @JvmStatic
    fun callStaticJavaMethod(s: String?,i: Int){
        val len = s!!.length
        Log.i("native","c调用了java静态方法  $s  $i")

    }

    fun callJavaMethod(s: String,i: Int){
        Log.i("native","c调用了java方法  $s  $i")
    }
}

调用java或kotlin方法和属性基本步骤分4步
1.找到类,实例方法和属性要创建对象
2.找到方法或属性id
3.调用方法
4.释放资源

1.C调用kotlin静态方法
首先说一点,kotlin的object类和compaion object中,属性声明都是静态的,方法并不是静态,必须通过@JvmStatic注解,
方法才会声明为静态
Kotlin开发jni程序 二.C调用java/kotlin方法和属性_第1张图片
可以看到kotlin反编译出的代码,只有@JvmStatic声明的方法才真正是静态方法,然后就可以在C中调用静态的方法

//1.首先要在C中获取jclass对象,也就是找到方法所在的类,通过完整  包名+类名
jclass java_first = env->FindClass("com/example/firstjni/NDKUtil");

/**2.找到该方法的方法ID
*参数一:jclass
*参数二:方法名
*参数三:方法签名
*方法签名,网上有详细说明,如果不想查,可以使用javap -s指令查询
*/
 jmethodID static_method_id = env->GetStaticMethodID(java_first, "callStaticJavaMethod",
                                                            "(Ljava/lang/String;I)V");

/**3.调用静态方法
*参数一:jclass
*参数二:方法ID
*参数三:参数三是可变长参数,也就是该方法声明时候对应的参数列表,相当于调用方法时的传参
*这个方法声明的是(s: String, i: Int)
*/
env->CallStaticVoidMethod(java_first, static_method_id, NULL, 2);

//4.删除掉本地引用
env->DeleteLocalRef(java_first);

javap命令查询
Kotlin开发jni程序 二.C调用java/kotlin方法和属性_第2张图片
对于kotlin来说,先通过AS下面的Termial进入build\tmp\kotlin-classes\debug目录 调用javap -s 包名+类名,就会为你显示该类所有的方法签名,就是
descriptor:后面的部分 ,例如:()Ljava/lang/String;

2.调用实例方法
实例方法调用步骤类似,不过实例方法需要对象调用,而不能是直接通过类调用,需要先通过构造器创建对象

//1.找到类
jclass java_first = env->FindClass("com/example/firstjni/NDKUtil");```

//2.找到构造器方法,这个相当于查找无参构造器
jmethodID construct = env->GetMethodID(java_first, "", "()V");

//3.创建对象
jobject NDKObj = env->NewObject(java_first, construct);

//4.再回到和静态调用差不多的步骤,找到目标方法
jmethodID jmethodID1 = env->GetMethodID(java_first, "callJavaMethod", "(Ljava/lang/String;I)V");

//5.通过对象调用方法,这个方法参数是(s: String, i: Int)
jstring message = env->NewStringUTF("调用成功了");
env->CallVoidMethod(NDKObj, jmethodID1, message, 1);

//6.释放资源
env->DeleteLocalRef(message);
env->DeleteLocalRef(NDKObj);

3.调用属性

//调用静态属性

//1.找类
jclass java_first = env->FindClass("com/example/firstjni/NDKUtil");

//2.找属性ID
jfieldID name_id = env->GetStaticFieldID(java_first, "name", "Ljava/lang/String;");

//3.获取属性,string类型是通过GetStaticObjectField,其他的属性都有对应的方法,比如对于Int 就是GetStaticIntField
jstring name_obj = (jstring) env->GetStaticObjectField(java_first, name_id);

//至于实例属性,和调用实例方法步骤差不多,这里不多赘述

NOTE:查找方法和属性ID的时候,方法签名有多个参数,要用;隔开,如果只有一个参数,结尾也要用;

你可能感兴趣的:(Android,kotlin,jni,c调用java)