前幾天有關(guān)Android JNI開(kāi)發(fā)系列教程中有關(guān)的源代碼,可以在本文中查找:
一、 在JNI中執(zhí)行Java方法
view plaincopy to clipboardprint?
class AndroidJniDemo {
private native void executeMethod();
private void show() {
System.out.println("Java cwj print"); //執(zhí)行了show方法后打印java層的輸出
}
public static void main(String args[]) { //這里我們?cè)贘2SE中測(cè)試,Android開(kāi)發(fā)者可以放到Activity中的onCreate調(diào)用
AndroidJniDemo ajd = new AndroidJniDemo();
ajd.executeMethod();
}
static {
System.loadLibrary("AndroidJniDemo");
}
}
class AndroidJniDemo {
private native void executeMethod();
private void show() {
System.out.println("Java cwj print"); //執(zhí)行了show方法后打印java層的輸出
}
public static void main(String args[]) { //這里我們?cè)贘2SE中測(cè)試,Android開(kāi)發(fā)者可以放到Activity中的onCreate調(diào)用
AndroidJniDemo ajd = new AndroidJniDemo();
ajd.executeMethod();
}
static {
System.loadLibrary("AndroidJniDemo");
}
}
下面是JNI代碼:
view plaincopy to clipboardprint?
JNIEXPORT void JNICALL
Java_AndroidJniDemo_executeMethod(JNIEnv *env, jobject obj)
{
jclass clazz = (*env)->GetObjectClass(env, obj); //通過(guò)類(lèi)的對(duì)象
jmethodID mid = (*env)->GetMethodID(env, clazz, "show", "()V"); //查找java中的show方法的ID,最后的簽名符號(hào)為void類(lèi)型
if (mid == NULL) {
return; //如果方法ID沒(méi)有找到
}
printf("JNI cwj print"); //從JNI中打印輸出
(*env)->CallVoidMethod(env, obj, mid); //執(zhí)行show方法
}
JNIEXPORT void JNICALL
Java_AndroidJniDemo_executeMethod(JNIEnv *env, jobject obj)
{
jclass clazz = (*env)->GetObjectClass(env, obj); //通過(guò)類(lèi)的對(duì)象
jmethodID mid = (*env)->GetMethodID(env, clazz, "show", "()V"); //查找java中的show方法的ID,最后的簽名符號(hào)為void類(lèi)型
if (mid == NULL) {
return; //如果方法ID沒(méi)有找到
}
printf("JNI cwj print"); //從JNI中打印輸出
(*env)->CallVoidMethod(env, obj, mid); //執(zhí)行show方法
}
二、獲取/設(shè)置類(lèi)的域或者說(shuō)屬性字段
(1 String類(lèi)型的屬性讀寫(xiě)
view plaincopy to clipboardprint?
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層打印結(jié)果
}
static {
System.loadLibrary("AndroidJniDemo2");
}
}
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層打印結(jié)果
}
static {
System.loadLibrary("AndroidJniDemo2");
}
}
下面是JNI層代碼:
view plaincopy to clipboardprint?
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類(lèi)型在java.lang.String包中,簽名符號(hào)的格式注意
if (fid == NULL) {
return;
}
jstr = (*env)->GetObjectField(env, obj, fid); //Java的String類(lèi)型,要用GetObjectField函數(shù)獲取,這里Android123提示大家沒(méi)有GetStringField這樣的函數(shù)在JNI中,或者說(shuō)在C語(yǔ)言中
szTemp = (*env)->GetStringUTFChars(env, jstr, NULL); //因?yàn)檫€需要賦值,在C中我們轉(zhuǎn)換為utf8的類(lèi)型。
if (szTemp == NULL) {
return;
}
printf("JNI cwj print=%s", szTemp); //先打印Java層傳進(jìn)來(lái)的值
(*env)->ReleaseStringUTFChars(env, jstr, szTemp); //szTemp打印完不用了要及時(shí)釋放掉
jstr = (*env)->NewStringUTF(env, "android123"); //返新的字段值,供Java層打印
if (jstr == NULL) {
return;
}
(*env)->SetObjectField(env, obj, fid, jstr); //設(shè)置新的屬性值。
}
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類(lèi)型在java.lang.String包中,簽名符號(hào)的格式注意
if (fid == NULL) {
return;
}
jstr = (*env)->GetObjectField(env, obj, fid); //Java的String類(lèi)型,要用GetObjectField函數(shù)獲取,這里Android123提示大家沒(méi)有GetStringField這樣的函數(shù)在JNI中,或者說(shuō)在C語(yǔ)言中
szTemp = (*env)->GetStringUTFChars(env, jstr, NULL); //因?yàn)檫€需要賦值,在C中我們轉(zhuǎn)換為utf8的類(lèi)型。
if (szTemp == NULL) {
return;
}
printf("JNI cwj print=%s", szTemp); //先打印Java層傳進(jìn)來(lái)的值
(*env)->ReleaseStringUTFChars(env, jstr, szTemp); //szTemp打印完不用了要及時(shí)釋放掉
jstr = (*env)->NewStringUTF(env, "android123"); //返新的字段值,供Java層打印
if (jstr == NULL) {
return;
}
(*env)->SetObjectField(env, obj, fid, jstr); //設(shè)置新的屬性值。
}
(2 int或double類(lèi)似的類(lèi)型的屬性讀寫(xiě),本例同時(shí)屬性值是一個(gè)靜態(tài)的定義,注意下面加粗的static關(guān)鍵字
view plaincopy to clipboardprint?
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(); //執(zhí)行jni層
System.out.println("Java cwj print="+sAge); //java層打印新的值,應(yīng)該為120
}
static {
System.loadLibrary("AndroidJniDemo3");
}
}
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(); //執(zhí)行jni層
System.out.println("Java cwj print="+sAge); //java層打印新的值,應(yīng)該為120
}
static {
System.loadLibrary("AndroidJniDemo3");
}
}
下面是JNI層代碼:
view plaincopy to clipboardprint?
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"); //因?yàn)槭钦?,這里簽名符號(hào)為I,注意使用的函數(shù)中包含Static代表是一個(gè)靜態(tài)的屬性
if (fid == NULL) {
return;
}
nTemp = (*env)->GetStaticIntField(env, clazz, fid);
printf("JNI cwj print=%d", nTemp); //這里應(yīng)該顯示23
(*env)->SetStaticIntField(env, clazz, fid, 120); //設(shè)置新的值為120,注意包含了Static,java層中定義的sAge是靜態(tài)的。
}
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"); //因?yàn)槭钦危@里簽名符號(hào)為I,注意使用的函數(shù)中包含Static代表是一個(gè)靜態(tài)的屬性
if (fid == NULL) {
return;
}
nTemp = (*env)->GetStaticIntField(env, clazz, fid);
printf("JNI cwj print=%d", nTemp); //這里應(yīng)該顯示23
(*env)->SetStaticIntField(env, clazz, fid, 120); //設(shè)置新的值為120,注意包含了Static,java層中定義的sAge是靜態(tài)的。
}
給出了較完整的JNI下執(zhí)行Java的源代碼第一部分,有關(guān)第二部分可以查看 Android JNI實(shí)力代碼(二)