例:
從Native層返回一個Java對象,有兩種操作
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行:
// 獲取類的構造函數,記住這里是調用無參的構造函數 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 );
本文轉自: