Android JNI開發--JNI返回Java對象

昨天同事問我一個JNI問題,想從Native代碼中返回一個Java對象,可是網上找的例子運行就崩潰了。仔細一想,我好想也沒作過這樣的操做,趕忙學習一下。java

從Native層返回一個Java對象,有兩種操做c++

  1. 傳入一個建立好的Java對象,只在JNI代碼中作賦值操做並返回
  2. 徹底在JNI代碼中新建一個對象,賦值並返回
建立一個Person類
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;
    }
}
複製代碼
Native方法
//方法1 從Java層傳入一個對象
public native Person getPerson(Person person);
//方法2 徹底從Native代碼中建立對象
public native Person getPerson2();
複製代碼
C++代碼
方法1
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;
}
複製代碼
方法2
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

相關文章
相關標籤/搜索