昨天同事問我一個JNI問題,想從Native代碼中返回一個Java對象,可是網上找的例子運行就崩潰了。仔細一想,我好想也沒作過這樣的操做,趕忙學習一下。java
從Native層返回一個Java對象,有兩種操做c++
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
複製代碼
//方法1 從Java層傳入一個對象
public native Person getPerson(Person person);
//方法2 徹底從Native代碼中建立對象
public native Person getPerson2();
複製代碼
extern "C"
JNIEXPORT jobject JNICALL Java_com_myapplication_MainActivity_getPerson(JNIEnv *env, jobject instance, jobject person) {
// 找到對象的Java類
jclass myClass = env->FindClass("com/myapplication/Person");
// 對應的Java屬性
jfieldID name = env->GetFieldID(myClass, "name", "Ljava/lang/String;");
jfieldID age = env->GetFieldID(myClass, "age", "I");
//屬性賦值,person爲傳入的Java對象
env->SetObjectField(person, name, env->NewStringUTF("liuwei"));
env->SetIntField(person, age, 20);
return person;
}
複製代碼
extern "C"
JNIEXPORT jobject JNICALL Java_com_myapplication_MainActivity_getPerson2(JNIEnv *env, jobject instance) {
jclass myClass = env->FindClass("com/myapplication/Person");
// 獲取類的構造函數,記住這裏是調用無參的構造函數
jmethodID id = env->GetMethodID(myClass, "<init>", "()V");
// 建立一個新的對象
jobject person_ = env->NewObject(myClass, id);
jfieldID name = env->GetFieldID(myClass, "name", "Ljava/lang/String;");
jfieldID age = env->GetFieldID(myClass, "age", "I");
env->SetObjectField(person_, name, env->NewStringUTF("liuwei"));
env->SetIntField(person_, age, 20);
return person_;
}
複製代碼
能夠看到,方法1和方法2的代碼區別就2行app
// 獲取類的構造函數,記住這裏是調用無參的構造函數
jmethodID id = env->GetMethodID(myClass, "<init>", "()V");
// 建立一個新的對象
jobject person_ = env->NewObject(myClass, id);
複製代碼
在開發時 env->GetMethodID(myClass, "<init>", "()V");
極可能會在寫代碼是標紅,提示沒法找到<init>
,不須要理會,直接編譯就行了。函數
TextView tv = findViewById(R.id.sample_text);
Person person = new Person();
//傳入Java對象,返回的也是同一個對象
getPerson(person);
tv.setText(person.getName() // 方法1
+ " : " +
getPerson2().getAge() // 方法2
);
複製代碼
搞定!又學習了一個知識點。學習
對了,同事代碼崩潰的問題就是Java層用了方法2,可是JNI代碼卻用了方法1,沒有建立出一個對象,致使崩潰。this