聲明:本文轉載自android開發網,http://www.android123.com.cn/androidkaifa/683.html
前幾天Android123有關Android JNI開發系列教程中有關的原始碼,可以在本文中尋找:
一、 在JNI中執行Java方法
class AndroidJniDemo {
private native void executeMethod();
private void show() {
System.out.println("Java cwj print"); //執行了show方法後列印java層的輸出
}
public static void main(String args[]) { //這裡我們在J2SE中測試,Android開發人員可以放到Activity中的onCreate調用
AndroidJniDemo ajd = new AndroidJniDemo();
ajd.executeMethod();
}
static {
System.loadLibrary("AndroidJniDemo");
}
}
下面是JNI代碼:
JNIEXPORT void JNICALL
Java_AndroidJniDemo_executeMethod(JNIEnv *env, jobject obj)
{
jclass clazz = (*env)->GetObjectClass(env, obj); //通過類的對象
jmethodID mid = (*env)->GetMethodID(env, clazz, "show", "()V"); //尋找java中的show方法的ID,最後的簽名符號為void類型
if (mid == NULL) {
return; //如果方法ID沒有找到
}
printf("JNI cwj print"); //從JNI中列印輸出
(*env)->CallVoidMethod(env, obj, mid); //執行show方法
}
二、擷取/設定類的域或者說屬性欄位
(1 String類型的屬性讀寫
class AndroidJniDemo2 {
private String sTmp;
private native void readwriteField();
public static void main(String args[]) {
AndroidJniDemo2 ajd2 = new AndroidJniDemo2();
ajd2.sTmp = "cwj";
ajd2.readwriteField();
System.out.println("Java cwj print ="+ajd2.sTmp); //java層列印結果
}
static {
System.loadLibrary("AndroidJniDemo2");
}
}
下面是JNI層代碼:
JNIEXPORT void JNICALL
Java_AndroidJniDemo2_readwriteField(JNIEnv *env, jobject obj)
{
jfieldID fid;
jstring jstr;
const char *szTemp;
jclass clazz = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetFieldID(env, clazz, "sTmp", "Ljava/lang/String;"); // 注意sTmp是Java中聲明的,String類型在java.lang.String包中,簽名符號的格式注意
if (fid == NULL) {
return;
}
jstr = (*env)->GetObjectField(env, obj, fid); //Java的String類型,要用GetObjectField函數擷取,這裡Android123提示大家沒有GetStringField這樣的函數在JNI中,或者說在C語言中
szTemp = (*env)->GetStringUTFChars(env, jstr, NULL); //因為還需要賦值,在C中我們轉換為utf8的類型。
if (szTemp == NULL) {
return;
}
printf("JNI cwj print=%s", szTemp); //先列印Java層傳進來的值
(*env)->ReleaseStringUTFChars(env, jstr, szTemp); //szTemp列印完不用了要及時釋放掉
jstr = (*env)->NewStringUTF(env, "android123"); //返新的欄位值,供Java層列印
if (jstr == NULL) {
return;
}
(*env)->SetObjectField(env, obj, fid, jstr); //設定新的屬性值。
}
(2 int或double類似的類型的屬性讀寫,本例同時屬性值是一個靜態定義,注意下面加粗的static關鍵字
class AndroidJniDemo3 {
private static int sAge;
private native void readwriteField();
public static void main(String args[]) {
AndroidJniDemo3 ajd3 = new AndroidJniDemo3();
AndroidJniDemo3.sAge = 23;
ajd3.readwriteField(); //執行jni層
System.out.println("Java cwj print="+sAge); //java層列印新的值,應該為120
}
static {
System.loadLibrary("AndroidJniDemo3");
}
}
JNIEXPORT void JNICALL
Java_AndroidJniDemo3_readwriteField(JNIEnv *env, jobject obj)
{
jfieldID fid;
jint nTemp;
jclass clazz = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetStaticFieldID(env, clazz, "sAge", "I"); //因為是整形,這裡簽名符號為I,注意使用的函數中包含Static代表是一個靜態屬性
if (fid == NULL) {
return;
}
nTemp = (*env)->GetStaticIntField(env, clazz, fid);
printf("JNI cwj print=%d", nTemp); //這裡應該顯示23
(*env)->SetStaticIntField(env, clazz, fid, 120); //設定新的值為120,注意包含了Static,java層中定義的sAge是靜態。
}
今天Android開發網給出了較完整的JNI下執行Java的原始碼第一部分,有關第二部分可以查看 Android JNI執行個體代碼(二)