搞了三天,终于有点眉目了,共享给大家
android调用c++代码
至于ndk环境这里不讲了(http://blog.csdn.net/yinzhengbo/article/details/7268207)
先简述一下实现的功能,增加学生,修改学生信息,查询所有学生信息,根据名字查找学生
1、首先在项目里新建Student实体类包含字段(name,sex,age),
调用Jni方法的类StudentToJNI包含方法(addStu(Student stu),upStu(Student stu),getStu(String name),getStus)
2、cmd -> javac(编译StudentToJNI.java文件) 生成字节码文件
3、生成头文件(javah) cd至项目classess目录下 执行 javah -jni 包名+类名(类名不要后缀),会在classes生成一个.h的文件
4、项目根目录下新建jni文件夹,复制 .h文件至jni文件夹下,然后找到ndk的安装目录找到android.mk,Application.mk文件夹一同放在jni目录下,注意如果使用c++里的库需要在Application.mk文件中加入(APP_STL:= stlport_shared)
至于两个文件内容其它的用法,这里就不在描述(goolgle)
5、jni文件夹下新建.cpp文件,最好名称与头文件一致,然后拷贝头文件里的所有函数至cpp文件夹内,并且导入头文件(#include<name.h>),当然也要导入jni.h头文件,其实我们主要做的是就是通过jni把java传进来的类型,转换成c++需要的类型,然后把c++返回的值通过jni转换成java所需要的类型。jni.h头文件里提供了很多转换的方法以及取值的方法,具体大家可以打开ndk安装目录(platforms\android-9\arch-arm\usr\include)目录下查看jni.h头文件
6、具体实现(文件:android.mk,Application.mk,jniTest.h,jniTest.cpp):
主要是实现jniTest.cpp文件
(1)、引用必要的头文件(jni.h,jniTest.h,vector),引入命名空间(using namespace std;)
(2)、定义一个结构,结构里的内容和java类中Student里的字段一样(struct student { char * name;int age,int sex};)(分号必须有)、定义一个向量,用来保存录入的学生信息,(由于是用户输入,长度不固定所以采用向量来保存)(vector<student>
stus)
(3)、定义JstringTosString方法用于jString类型转换成char指针类型 具体代码goolgle,jni会把java传进来的对象类型转换成jni相对应的类型。如(java
string=jni jstring 、java Student = jni jobject。。。。。。)
(4)、增加学生信息:addStu(JNIEnv *env, jobject obj, jobject valObj)
//获取jclass对象 jclass cls=env->GetObjectClass(valObj); //GetFieldID方法用到取到jclass中的name字段。参数列表(jclass对象,字段名称,字段类型),这点类似于java的反射 //GetObjectField方法从传进来的jobject对象valObj里取到指定字段的值。参数列表(jobject对象,jfieldID对象)注意类型转换; jstring name=(jstring)env->GetObjectField(valObj,env->GetFieldID(cls,"name","Ljava/lang/String;")); jint age=(jint)env->GetObjectField(valObj,env-> GetFieldID(cls,"age","I")); jint sex=(jint)env->GetObjectField(valObj,env->GetFieldID(cls,"sex","I")); //创建一个结构类型的对象 jstringToString方法用于把jstring类型转换成char * student stu={jstringTostring(env,name),(int)age,(int)sex}; //往向量的未尾增加一个对象 stus.push_back(stu);
(5)、修改学生信息:upStu(JNIEnv
*env, jobject obj, jobject valObj)
jclass cls=env->GetObjectClass(objValue); jstring name=(jstring)env->GetObjectField(objValue,env->GetFieldID(cls,"name","Ljava/lang/String;")); jint sex=(jint)env->GetObjectField(objValue,env->GetFieldID(cls,"sex","I")); jint age=(jint)env->GetObjectField(objValue,env->GetFieldID(cls,"age","I")); char * searchName=jstringTostring(env,name); for(int i=0;i<stus.size();i++) { student stu=stus.at(i); if(strcmp(stu.name,searchName)==0) { stus.at(i).sex=(int)sex; stus.at(i).age=(int)age; } }
(6)、查询学生信息:getStu(JNIEnv
* env, jobject obj, jstring str)
const char *nameStr=env->GetStringUTFChars(str,0); jclass objectClass=(env)->FindClass("com/myjni/activity/Student"); jfieldID name=env->GetFieldID(objectClass,"name","Ljava/lang/String;"); jfieldID sex=env->GetFieldID(objectClass,"sex","I"); jfieldID age=env->GetFieldID(objectClass,"age","I"); for(int i=0;i<stus.size();i++) { student stu=stus.at(i); if(strcmp(stu.name,nameStr)==0) { env->SetObjectField(obj,name,env->NewStringUTF(stus.at(i).name)); env->SetIntField(obj,sex,stus.at(i).sex); env->SetIntField(obj,age,stus.at(i).age); } } return obj;
(7)、获取所有学生信息:getStus(JNIEnv * env, jobject obj)
class objClass = (env)->FindClass("java/lang/Object"); jobjectArray args=0; jsize len=stus.size(); args=env->NewObjectArray(len,objClass,0); jclass objectClass=(env)->FindClass("com/myjni/activity/Student"); jfieldID name = (env)->GetFieldID(objectClass,"name","Ljava/lang/String;"); jfieldID age = (env)->GetFieldID(objectClass,"age","I"); jfieldID sex = (env)->GetFieldID(objectClass,"sex","I"); for(int i=0;i<len;i++) { jobject tempObj=env->AllocObject(env->GetObjectClass(obj)); student stu=stus.at(i); env->SetObjectField(tempObj,name,env->NewStringUTF(stus.at(i).name)); env->SetIntField(tempObj,age,stu.age); env->SetIntField(tempObj,sex,stu.sex); env->SetObjectArrayElement(args,i,tempObj); } return args;
7、java代码调用
static{ System.loadLibrary("stlport_shared"); System.loadLibrary("HW"); } StudentToJNI jni=new StudentToJNI(); jni.add(new Student()); jni.update(new Student()); jni.getStu("tom"); jni.getStus();