前言
jni中除了基本数据类型和数组之外,都是jobject
类型的变量。jni提供了一系列的方法来操作jobject
。
下面的示例都是根据TestObject.java
来进行的。
public class TestObject {
private String firstName;
private String secondName;
public TestObject(String firstName, String secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
public String getResult() {
return String.format("%1$s-=-%2$s", firstName, secondName);
}
}
判断对象类型
IsInstanceOf(env, jobj, jclass)
可以用来判断jobject是否是某个jclass类型。
jclass jTestObject = (*env)->FindClass(env, "com/mislead/testjni/TestObject");
if(jTestObject==NULL)
{
LOGE("cannot found class:com/mislead/testjni/TestObject");
return NULL;
}
if((*env)->IsInstanceOf(env, obj, jTestObject))
{
}
调用对象方法
GetObjectMethodID(env, jclass, methodName, signature)
获取到方法id。CallObjectMethod(env, jobject, methodID)
来调用方法,或者获取结果。
// getResult() method
// first get method id by GetMethodID(JNIEnv, jclass, methodName, methodSignature)
jmethodID jmID=(*env)->GetMethodID(env, jTestObject, "getResult", "()Ljava/lang/String;");
// call method
return (*env)->CallObjectMethod(env, obj, jmID);
关于Signature
如果细心会发现我们在生成的jni头文件,函数前的注释部分都有Signature,你可以参考写法。下面是一些说明:
方法的Signature是由方法的参数和返回值的类型共同构成的,下面是他们的结构:
“(argument-types)return-type”
其中Java程序中参数类型和其对应的值如下:
Signature Java中的类型
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L fully-qualified-class; fully-qualified-class
[ type type[]
( arg-types ) ret-type method type
一个Java类的方法的Signature可以通过javap命令获取:
javap -s -p Java类名
生成一个对象
FindClass(env, className)
得到想要的jclass。GetObjectMethodID(env, jclass, "<init>", signature)
获取到构造方法的ID。类的构造方法名字统一为<init>
,默认无参数的signature为()V
。
/*
* Class: com_mislead_testjni_TestJni
* Method: testCreateObject
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_mislead_testjni_TestJni_testCreateObject
(JNIEnv *env, jobject jobj, jstring first, jstring second)
{
//first, create a TestObject
jclass jTestObject = (*env)->FindClass(env, "com/mislead/testjni/TestObject");
// get construct method id
jmethodID construct = (*env)->GetMethodID(env, jTestObject, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
jobject obj=(*env)->NewObject(env, jTestObject, construct, first, second);
return callGetResult(env, obj);
}
获取对象的属性
GetObjectFieldID(env, jclass, fieldName, signature)
获取fieldID。GetObjectField(env, jobject, fieldID)
获取到属性值。
jclass jcls=(*env)->GetObjectClass(env, obj);
jfieldID fid=(*env)->GetFieldID(env, jcls, "firstName", "Ljava/lang/String;");
jstring firstName=(*env)->GetObjectField(env, obj, fid);
静态方法和属性
调用静态方法:
就是将第二步和第三步调用的方法改为对应的:
GetStaticMethodID获取对应的静态方法的ID
CallStaticIntMethod调用静态方法
获取静态属性:
使用GetStaticFieldID>