根据上一篇对应的数据类型关系,从这一篇开始一种一种的对应进行测试.工程的话还是用第一篇中的那个工程:
<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 warden_sprite@foxmail.com
* @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 warden_sprite@foxmail.com
* @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 warden_sprite@foxmail.com
* @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 warden_sprite@foxmail.com
* @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