Android — JNI如何取得Java Object的值

JLin
3 min readJan 9, 2019

--

如果是JavaArray

TrafficData[] trafficData ;

這樣要怎麼在JNI中取得呢?

首先必須說有幾個檔案結構

  1. Java端的native method,稱為 jni.java
  2. C JNI端的java interface,稱為c_jni.cpp
  3. C JNI端的 header file,稱為c_jni.h

我們首先在jni.java增加

public native void SetTrafficData(TrafficData[] trafficData);

這樣就可以了

在c_jni.h端中

JNIEXPORT jboolean JNICALL Java_com_sdk_1SetTraffics(
JNIEnv *env, jclass,jobjectArray data1);

在c_jni.cpp中實作方法,也就是你實際要運作的c code

JNIEXPORT jboolean JNICALL Java_com_sdk_1SetTraffics(
JNIEnv *env, jclass,jobjectArray data1) {
// TODO
}

注意前面的JNIEnv *env, jclass是固定參數,用來取得一些JNI使用的功能

以上步驟就完成了介面的串接,等等那重點來了,在jni中要怎麼取得java array呢

int size = env->GetArrayLength(data1);

從data1中的array取出jobject

jobject jboject1 = env->GetObjectArrayElement(data1, index);

透過這方式就可以一個一個object取出

接下來我們要對jboject取得物件的兩個int參數

先取得jclass

jclass jclass1 = env->GetObjectClass(jboject1); 

然後透過以上的jclass 跟 jobject取得參數值

int index= env->GetIntField(jboject1, env->GetFieldID(jclass1, “index”, “I”));

注意這邊第一個參數是jobject,後面GetFieldId是使用jclass

如此一來就可以取得java object的參數了

完整的實作如下

JNIEXPORT jboolean JNICALL Java_com_sdk_1SetTraffics(
JNIEnv *env, jclass,jobjectArray data1) {
int size = env->GetArrayLength(data1);
jobject jboject1 = env->GetObjectArrayElement(data1, index);
jclass jclass1 = env->GetObjectClass(jboject1);
int index= env->GetIntField(jboject1, env->GetFieldID(jclass1, “index”, “I”));
}

最後記得是需要把jboject進行deleteRef

env->DeleteLocalRef(jtarget)

另外如果你是需要在native c code中產生一個java object在回傳到app端就需要透過以下方式,但其實不太建議,因為這樣一改動你java端的名稱或者物件就會造成找不到的問題

jclass itemClass = env->FindClass("com/test/sdk/TrafficData");

--

--

JLin

JAVA / Android /Kotlin / Kotlin Native 對於Kotlin衍生的JVM等技術 Compose for web / desktop / Ktor Server,或是生成式AI (Gemini/OpenAI)各式應用, 都有小興趣