現在我們知道了怎樣使用native code訪問簡單的資料類型和引用參考類型(string,array),下面我們來介紹怎樣讓jni代碼去訪問java中的成員變數和成員函數,然後可以再jni中回調java中的方法。
-------------------------------------------------------------------------------------
Accessing fields
java提供2中成員,靜態成員和非靜態成員,JNI支援了怎麼樣去get和set這些靜態以及非靜態成員的方法,下面來舉一個例子。
先來訪問非靜態成員。
我們先在類中聲明一個非靜態成員變數:
[java]
public class MyJNI extends Activity {
/** Called when the activity is first created. */
//declear a instance field
private String s="123";
在點擊按鈕的時候我們把title的textview的字串改成s,
[java]
MyJNI mj = new MyJNI();
mj.accessField();
tv.setText(mj.s);
java代碼很簡單,只要實現我們的功能就好了,下面來看jni是如何進入class中的成員變數的:
[cpp]
Java_com_android_jni_MyJNI_accessField(JNIEnv *env,jobject obj)
{
jfieldID fid;
jstring jstr;
const char *str;
//get a reference to obj's class
jclass cls = (*env)->GetObjectClass(env,obj);
// jclass cls = (*env)->FindClass(env,"com/android/jni/Native");
__android_log_print(ANDROID_LOG_INFO,"-JNI-","here in native C!");
//look for the instance field in cls
fid = (*env)->GetFieldID(env,cls,"s",
"Ljava/lang/String;");
if(fid == NULL){
__android_log_print(ANDROID_LOG_INFO,"-JNI-","can not find field");
return;
}
//read the instance field s
jstr = (*env)->GetObjectField(env,obj,fid);
str = (*env)->GetStringUTFChars(env,jstr,NULL);
if(str == NULL)
return;
(*env)->ReleaseStringUTFChars(env,jstr,str);
//create a new string and overwrite the instance field
jstr = (*env)->NewStringUTF(env,"abc");
if(jstr == NULL)
return; //out of memory
(*env)->SetObjectField(env,obj,fid,jstr);
}
為了訪問目標類中的成員變數,要做2步,首先呼叫GetFieldID從類中來得到一個field ID,根據成員的名字和描述:
fid = (*env)->GetFieldID(env,cls,"s",
"Ljava/lang/String;");
然後根據這個field ID來訪問這個成員:
jstr = (*env)->GetObjectField(env,obj,fid);
因為在java中string是對象,所以這邊呼叫的是GetObjectField函數。
最後運行模擬器,點擊按鈕的時候textView會變成JNI中修改的“abc”
ok,這部分結束,下面來看如何訪問靜態成員變數。
同樣的java代碼中:
[java]
public class MyJNI extends Activity {
/** Called when the activity is first created. */
//declear a instance field
private static int si=100;
private String s="123";
我們定義一個靜態整形變數si初始化為100,當我們點擊按鈕的時候通過jni訪問static field來改變si的值,然後再title的textView中顯示出來。
[java]
MyJNI mj = new MyJNI();
mj.accessStaticField();
tv.setText(mj.si+"");
我們來看下如何進入static field:
[cpp]
Java_com_android_jni_MyJNI_accessStaticField(JNIEnv *env,jobject obj)
{
jfieldID fid; //store the field id
jint si;
//get a reference to obj's class
jclass cls = (*env)->GetObjectClass(env,obj);
__android_log_print(ANDROID_LOG_INFO,"-JNI-","here in native C!");
//look for the static field si in lcs
fid = (*env)->GetStaticFieldID(env,cls,"si","I");
if(fid == NULL)
return; //field not found
//access the static field si
si = (*env)->GetStaticIntField(env,cls,fid);
(*env)->SetStaticIntField(env,cls,fid,200);
}