根据上一篇对应的数据类型关系,从这一篇开始一种一种的对应进行测试.工程的话还是用第一篇中的那个工程:
<1> : 先介绍整型 :
在工程lib包下新建DurianJniInteger.java的类型,添加内容如下:
/** * @Title: DurianJniInteger.java * @Package com.durian.jnienv.lib * @Description: TODO * @author zhibao.liu from durian organization * @date 2015-12-24 下午05:01:36 * @version V1.0 */ package com.durian.jnienv.lib; /** * @ClassName: DurianJniInteger * @Description: TODO * @author zhibao.liu Freelancer * @email [email protected] * @date 2015-12-24 下午05:01:36 * */ public class DurianJniInteger { public native int DurianAdd(int a,int b); public native int DurianDul(int a,int b); }
做一个加号运算,做一个减号运算.
build 工程,生成class文件,然后在include.txt文件中修改,单独javah下面的一个就好了:
com.durian.jnienv.lib.DurianJniInteger
执行cmd命令:
javah -d jni -classpath bin/classes -jni @temp.txt
然后将生成.h文件名调整一下,当然建议大家不要调整,不然每次javah一次都要修改一次文件名,很逗逼的.
同时我调整了一些辅助文件到durianUtils.h中:
#include <jni.h> /* Header for class com_durian_jnienv_lib_DurianJni */ #ifndef _Included_com_durian_jnienv_lib_DurianUtils #define _Included_com_durian_jnienv_lib_DurianUtils #ifdef __cplusplus extern "C" { #endif #include <android/log.h> #define LOG_TAG "durian" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) #ifdef __cplusplus } #endif #endif
durianJniInteger.c 如下:
#include "durianJniInteger.h" #include "durianUtils.h" JNIEXPORT jint JNICALL Java_com_durian_jnienv_lib_DurianJniInteger_DurianAdd(JNIEnv *env, jobject jobj, jint a, jint b){ int sum =(int)a+(int)b; LOGI("sum : %d from jni !",sum); return (jint)sum; } JNIEXPORT jint JNICALL Java_com_durian_jnienv_lib_DurianJniInteger_DurianDul(JNIEnv *env, jobject jobj, jint a, jint b){ int dul =0; if(a>b){ dul=(int)a-(int)b; }else{ dul=(int)b-(int)a; } LOGI("dul : %d from jni !",dul); return (jint)dul; }
durianJniInteger.h如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_durian_jnienv_lib_DurianJniInteger */ #ifndef _Included_com_durian_jnienv_lib_DurianJniInteger #define _Included_com_durian_jnienv_lib_DurianJniInteger #ifdef __cplusplus extern "C" { #endif /* * Class: com_durian_jnienv_lib_DurianJniInteger * Method: DurianAdd * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_durian_jnienv_lib_DurianJniInteger_DurianAdd (JNIEnv *, jobject, jint, jint); /* * Class: com_durian_jnienv_lib_DurianJniInteger * Method: DurianDul * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_durian_jnienv_lib_DurianJniInteger_DurianDul (JNIEnv *, jobject, jint, jint); #ifdef __cplusplus } #endif #endif
Android.mk中还需要将上面的c文件添加到编译中:
LOCAL_SRC_FILES += durianJniInteger.c
基本上准备就OK了,运行结果如下:
很容易验证就OK了.
下面在介绍字符串型:
同样在工程lib包下面添加DurianJniString.java,然后类似上面的编译方式,生成头文件,修改名称后durianJniString.h,并且新建durianJniString.c文件,内容如下:
DurianJniString.java :
/** * @Title: DurianJniString.java * @Package com.durian.jnienv.lib * @Description: TODO * @author zhibao.liu from durian organization * @date 2015-12-24 下午05:02:57 * @version V1.0 */ package com.durian.jnienv.lib; /** * @ClassName: DurianJniString * @Description: TODO * @author zhibao.liu Freelancer * @email [email protected] * @date 2015-12-24 下午05:02:57 * */ public class DurianJniString { public native void setInformation(String info); public native String getInformation(); }
不过需要添加一个java string转为jstring的函数放到durianUtils.c中,如果没有这个文件新建之:
#include<stdio.h> #include<string.h> #include "durianUtils.h" char* Jstring2CStr(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = (*env)->FindClass(env, "java/lang/String"); jstring strencode = (*env)->NewStringUTF(env, "GB2312"); jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312"); jsize alen = (*env)->GetArrayLength(env, barr); jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE); if (alen > 0) { rtn = (char*) malloc(alen + 1); //new char[alen+1]; "\0" memcpy(rtn, ba, alen); rtn[alen] = 0; } (*env)->ReleaseByteArrayElements(env, barr, ba, 0); //释放内存 return rtn; }
durianJniString.c 文件内容如下:
#include "durianJniString.h" #include "durianUtils.h" #include "durianUtils.c" JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniString_setInformation(JNIEnv *env, jobject jobj, jstring msg){ char* message; message=Jstring2CStr(env,msg); LOGI("message : %s log from jni !",message); } JNIEXPORT jstring JNICALL Java_com_durian_jnienv_lib_DurianJniString_getInformation(JNIEnv *env, jobject jobj){ char* newstr = "return durian generall information from jni !"; return (*env)->NewStringUTF(env, newstr); }
并且同样在Android.mk文件中添加:
LOCAL_SRC_FILES += durianJniString.c
编译运行:
设置进去和返回都是OK的.
下面接着来扯一下布尔类型的传递.
同样新建一个DurianJniBoolean.java :
/** * @Title: DurianJniBoolean.java * @Package com.durian.jnienv.lib * @Description: TODO * @author zhibao.liu from durian organization * @date 2015-12-24 下午05:03:18 * @version V1.0 */ package com.durian.jnienv.lib; /** * @ClassName: DurianJniBoolean * @Description: TODO * @author zhibao.liu Freelancer * @email [email protected] * @date 2015-12-24 下午05:03:18 * */ public class DurianJniBoolean { public native void setBoolean(boolean lean); public native boolean getBoolean(); }
对应生成.h文件,我这里直接写出实现函数durianJniBoolean.c的文件:
#include "durianJniBoolean.h" #include "durianUtils.h" JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniBoolean_setBoolean(JNIEnv *env, jobject jobj, jboolean lean){ if(lean==JNI_TRUE){ LOGI("boolean : true log from jni !"); }else{ LOGI("boolean : false log from jni !"); } } JNIEXPORT jboolean JNICALL Java_com_durian_jnienv_lib_DurianJniBoolean_getBoolean(JNIEnv *env, jobject jobj){ LOGI("return boolean : true log from jni !"); return JNI_TRUE; }
build,运行结果:
下面是数组传递,主要介绍两种,一个整型(上一篇表单2中的其他类型一次类推),一个字符串型:
DurianJniArray.java :
/** * @Title: DurianJniArray.java * @Package com.durian.jnienv.lib * @Description: TODO * @author zhibao.liu from durian organization * @date 2015-12-25 上午09:52:02 * @version V1.0 */ package com.durian.jnienv.lib; /** * @ClassName: DurianJniArray * @Description: TODO * @author zhibao.liu Freelancer * @email [email protected] * @date 2015-12-25 上午09:52:02 * */ public class DurianJniArray { public native void setDurianStringArray(String[] array); public native String[] getDurianStringArray(); public native void setDurianBooleanArray(Boolean[] array); public native Boolean[] getDurianBooleanArray(); public native void setDurianIntegerArray(int[] array); public native int[] getDurianIntegerArray(); }
然后编译生成头文件,实现他的具体方法如下durianJniArray.c :
#include "durianJniArray.h" #include "durianUtils.h" JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniArray_setDurianStringArray(JNIEnv *env, jobject jobj, jobjectArray array) { int size=(*env)->GetArrayLength(env,array); int i=0; LOGI("array string : %d",size); for(i=0;i<size;i++) { jstring obja=(jstring)(*env)->GetObjectArrayElement(env,array,i); LOGI("array string : %s",(*env)->GetStringUTFChars(env,obja,NULL)); } } JNIEXPORT jobjectArray JNICALL Java_com_durian_jnienv_lib_DurianJniArray_getDurianStringArray( JNIEnv *env, jobject jobj) { jstring str; jobjectArray ret; jsize len = 5; char* sa[] = { "Hello,", "world!", "JNI", "is", "fun" }; int i = 0; ret = (*env)->NewObjectArray(env,len,(*env)->FindClass(env,"java/lang/String"),0); for(i=0;i<5;i++){ str = (*env)->NewStringUTF(env,sa[i]); (*env)->SetObjectArrayElement(env,ret,i,str); } return ret; } JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniArray_setDurianBooleanArray(JNIEnv *env, jobject jobj, jobjectArray array) { jsize len = (*env)->GetArrayLength(env,array); int i=0; jboolean obja; for( i=0; i < len; i++ ){ obja=(jboolean)(*env)->GetObjectArrayElement(env,array,i); if(obja==JNI_TRUE){ LOGI( "array boolean = true"); }else{ LOGI( "array boolean = false"); } } } JNIEXPORT jobjectArray JNICALL Java_com_durian_jnienv_lib_DurianJniArray_getDurianBooleanArray( JNIEnv *env, jobject jobj) { jboolean lean; jbooleanArray args; jsize len = 5; jboolean le[] = { 0, 0, 0, 0, 1 }; int i = 0; jintArray arg=(*env)->NewBooleanArray(env,5); args = (*env)->NewObjectArray(env,len, (*env)->FindClass(env,"java/lang/Boolean"), 0); (*env)->SetBooleanArrayRegion(env,arg,0,5,le); return arg; } JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniArray_setDurianIntegerArray (JNIEnv *env, jobject jobj, jintArray array) { jint *buf=(*env)->GetIntArrayElements(env,array,(jint)0); jsize len=(*env)->GetArrayLength(env,array); int i=0; for(i=0;i<len;i++) { LOGI( "array set int = %d", buf[i]); } (*env)->ReleaseIntArrayElements(env, array, buf, 0); } JNIEXPORT jintArray JNICALL Java_com_durian_jnienv_lib_DurianJniArray_getDurianIntegerArray( JNIEnv *env, jobject jobj) { jint dur; jobjectArray args; jintArray arg=(*env)->NewIntArray(env,5); jsize len = 5; jint du[5] = { 100, 101, 102, 103, 104 }; LOGI( "array set int 123"); int i = 0; args = (*env)->NewObjectArray(env,5, (*env)->FindClass(env,"[I"), NULL); LOGI( "array set int 235"); (*env)->SetIntArrayRegion(env,arg,0,5,du); return arg; }
修改Android中主类:
private DurianJniArray mDurianJniArray;
mDurianJniArray=new DurianJniArray();
运行程序:
mDurianJniArray.setDurianIntegerArray(new int[]{200,201,202,203}); int[] arrInt=mDurianJniArray.getDurianIntegerArray(); for(int i=0;i<arrInt.length;i++){ Log.i(TAG,"arrInt["+i+"]="+arrInt[i]); } mDurianJniArray.setDurianStringArray(new String[]{"zhi","bao","liu","name","company"}); String msg[]=mDurianJniArray.getDurianStringArray(); for(int i=0;i<msg.length;i++){ Log.i(TAG,"arrString["+i+"]="+msg[i]); }
很简单,然后看看运行结果:
这个程序其实就是对前面一片的实际操作.
有图有代码:
百度盘:
http://pan.baidu.com/s/1mhmiUGo