JNI由浅入深_6_简单对象的应用

1、声明native方法

public class ComplexObject {

	/**
	 * 返回一个对象数组
	 * @param val
	 * @return
	 */
	public native Person[] receiverBeanArray(String val);

	/**
	 * 获取对象
	 * @return
	 */
	public native Person getPerson();

	/**
	 * 获取对象的集合
	 * @return
	 */
	public native ArrayList<Person> getPersonList();

}

2、Person类对象

有两个构造函数,主要是为了在jni中通过不同的构造函数来创建Person对象。

public class Person {

	public String name;
	private int age;

	public Person() {
		super();
	}

	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

}

3、jni操作实现

JNI中,构造函数可以和实例方法一样被调用,调用方式也相似。传入“<init>”作为方法名,“V”作为返回类型。你可以通过向JNI函数NewObject传入方法来调用构造函数。

/**
 * 拼接字符串
 */
char* strJoin(char *s1, char *s2) {
	char *result = malloc(strlen(s1) + strlen(s2) + 1);
	if (result == NULL)
		exit(1);
	strcpy(result, s1);
	strcat(result, s2);
	return result;
}
/**
 * 返回一个数组类型到Java
 */
JNIEXPORT jobjectArray JNICALL Java_com_example_jniandroid_service_ComplexObject_receiverBeanArray
  (JNIEnv * env, jobject obj , jstring string) {
	jclass objClass = (*env)->FindClass(env, "java/lang/Object");
	jobjectArray mails = (*env)->NewObjectArray(env, (jsize) ARRAY_LENGTH,objClass, 0);
	jclass personClass = (*env)->FindClass(env,"com/example/jniandroid/bean/Person");

	jfieldID field_name = (*env)->GetFieldID(env, personClass, "name","Ljava/lang/String;");
	jmethodID construction_id = (*env)->GetMethodID(env, personClass, "<init>","()V");
	jfieldID field_age = (*env)->GetFieldID(env,personClass, "age", "I");
	jclass mPerson = (*env)->NewObject(env, personClass, construction_id);

	int i = 0;
	//将jstring类型转成char*
	char* nameStr = (char*)(*env)->GetStringUTFChars(env,string, 0);
	//拼接字符串
	const char* name = strJoin(nameStr,"-join jni");
	LOGD("数组总和 =%s", name);
	for (; i < ARRAY_LENGTH; i++) {
		int age = 20+i;
		//将Java的字符串和c的字符串进行拼接后赋值给name属性
		(*env)->SetObjectField(env, mPerson, field_name, (*env)->NewStringUTF(env,name));
		(*env)->SetIntField(env,mPerson, field_age,age);
		(*env)->SetObjectArrayElement(env, mails, (jsize)i, mPerson);
	}
	return mails;
}

/**
 * 在jni中给Java对象设置值并返回
 */
JNIEXPORT jobject JNICALL Java_com_example_jniandroid_service_ComplexObject_getPerson
  (JNIEnv * env, jclass obj) {
	//找到Person类
	jclass m_cls = (*env)->FindClass(env,"com/example/jniandroid/bean/Person");
	//无参数的构造方法
	jmethodID m_mid = (*env)->GetMethodID(env,m_cls, "<init>", "()V");
	//获取Java中复杂类型以L开始;结尾,中间是类型将.改成/
	jfieldID m_fid_name = (*env)->GetFieldID(env,m_cls, "name", "Ljava/lang/String;");
	//基本类型,I表示Java中的int
	jfieldID m_fid_age = (*env)->GetFieldID(env,m_cls, "age", "I");

	if(m_fid_name==NULL){
		printf("m_fid_name is null ");
		return;
	}
	if(m_fid_age==NULL){
		printf("m_fid_age is null ");
		return;
	}

	jobject m_obj = (*env)->NewObject(env,m_cls, m_mid);

	(*env)->SetObjectField(env,m_obj, m_fid_name, (*env)->NewStringUTF(env,"Set the name Person object in the JNI value"));
	(*env)->SetIntField(env,m_obj, m_fid_age,96);

	return m_obj;
}

/**
 * 返回ArrayList集合
 */
JNIEXPORT jobject JNICALL Java_com_example_jniandroid_service_ComplexObject_getPersonList(
		JNIEnv * env, jobject obj) {
	jclass list_cls = (*env)->FindClass(env, "java/util/ArrayList"); //获得ArrayList类引用

	jmethodID list_costruct = (*env)->GetMethodID(env, list_cls, "<init>","()V"); //获得得构造函数Id
	jobject list_obj = (*env)->NewObject(env, list_cls, list_costruct); //创建一个Arraylist集合对象
	//Arraylist类中的 add()方法ID,其方法原型为: boolean add(Object object) ,boolean类型对应的是Z;
	jmethodID list_add = (*env)->GetMethodID(env, list_cls, "add","(Ljava/lang/Object;)Z");

	jclass personClass = (*env)->FindClass(env,"com/example/jniandroid/bean/Person"); //获得Person类引用
	//获得该类型的构造函数  函数名为 <init> 返回类型必须为 void 即 V
	jmethodID person_costruct = (*env)->GetMethodID(env, personClass, "<init>","(ILjava/lang/String;)V");
	int i=0;
	for (; i < 5; i++) {
		jstring str = (*env)->NewStringUTF(env, "jni Native");
		//通过调用该对象的构造函数来new 一个 Student实例
		jobject person_obj = (*env)->NewObject(env, personClass,person_costruct, i, str); //构造一个对象
		//执行Arraylist类实例的add方法,添加一个Person对象
		(*env)->CallBooleanMethod(env,list_obj, list_add, person_obj);
	}
	return list_obj;
}
时间: 2024-10-27 08:08:25

JNI由浅入深_6_简单对象的应用的相关文章

JNI由浅入深_3_Hello World

1.需要准备的工具,eclipse,cdt(c++)插件,cygwin(unix)和 android ndk. 在cygwin的etc目录下将ndk的路径引入到profile文件中,可以在cygwin的任何目录都可以访问到ndk,不同的ndk路径PATH的写法不同. : ${ORIGINAL_PATH=${PATH}} if [ ${CYGWIN_NOWINPATH-addwinpath} = "addwinpath" ] ; then PATH="/usr/local/bi

JNI由浅入深_9_JNI 异常处理

1 .本地代码中如何缓存和抛出异常 下面的代码中演示了如何声明一个会抛出异常的本地方法.CatchThrow这个类声明了一个会抛出IllegalArgumentException异常的名叫doit的本地方法. <span style="font-family:Comic Sans MS;font-size:14px;">class CatchThrow { private native void doit() throws IllegalArgumentException;

JNI由浅入深_7_c调用Java方法一

1.在Java中声明方法 <span style="font-size:14px;">/** * javah -encoding utf-8 -jni com.example.jniandroid.service.CFunction * 当java中有中文时,会报编码GBK不可映射字符 方法的调用,加上-encoding utf-8 * * @author libin * */ public class CFunction { /** * 实现在c里面回调callback方

JNI由浅入深_5_基本类型应用

1.基本类型应用 对于JNI处理基本类型还是比较简单的,下面是Java代码: <span style="font-size:14px;"> public native int intMethod(int n); public native boolean booleanMethod(boolean bool);</span> 上面的方法是在Java中写的,注意要加native关键字,这两个方法都比较简单,分别传入int ,boolean类型到jni中,经过处理返

JNI由浅入深_8_JNI缓存字段和方法ID

获取字段ID和方法ID时,需要用字段.方法的名字和描述符进行一个检索.检索过程相对比较费时,因此本节讨论用缓存技术来减少这个过程带来的消耗.缓存字段ID和方法ID的方法主要有两种.两种区别主要在于缓存发生的时刻,是在字段ID和方法ID被使用的时候,还是定义字段和方法的类静态初始化的时候. 1.使用时缓存 字段ID和方法ID可以在字段的值被访问或者方法被回调的时候缓存起来.下面的代码中把字段ID存储在静态变量当中,这样当本地方法被重复调用时,不必重新搜索字段ID. JNIEXPORT void J

JNI由浅入深_10_JNI 综合开发

1.使用ndk-build时如果找不到某个类,可以使用下面两种方法解决: 1.1 进入src目录 D:\project3\JNIAndroid\src>set classpath=D:\project3\JNIAndroid\src 1.2 设置classpath classpath    .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\tools.jar;E:\developLib\android\platforms\android-8\android.jar 2.基

JNI由浅入深_2_C语言基础

*含义 1.乘法 3*5 2.定义指针变量 int * p://定义了一个名字叫p的变量,能够存放int数据类型的地址 3.指针运算符, //如果p是一个已经定义好的指针变量则*p表示以p的内容为地址的变量 打印数据类型 %d - int %ld – long int %c - char %f - float %lf – double %x – 十六进制输出 int或者long int或者short int %o - 八进制输出 %s – 字符串 3.指针 指针就是地址. 热身小程序 介绍指针

Java JNI 编程进阶

原文:http://www.iteye.com/topic/295776 JNI一直以来都很少去关注,但却是我心中的一个结,最近这几天刚好手头有点时间,因此抽空看了一下这方面的东西,整理了一份文档,JNI技术的出现主要是基于三个方面的应用需求: 1. 解决性能问题Java具有平台无关性,这使人们在开发企业级应用的时候总是把它作为主要候选方案之一,但是性能方面的因素又大大削弱了它的竞争力.为此,提高Java的性能就显得十分重要.Sun公司及Java的支持者们为提高Java的运行速度已经做出了许多努

Delphi使用android的NDK是通过JNI接口,封装好了,不用自己写本地代码,直接调用

一.Android平台编程方式:      1.基于Android SDK进行开发的第三方应用都必须使用Java语言(Android的SDK基于Java实现)      2.自从ndk r5发布以后,已经允许完全用C/C++ 来开发应用或者游戏,而不再需要编写任何Java 的代码   Android程序运行在Dalvik虚拟机中,NDK允许用户使用类似C / C++之类的原生代码语言执行部分程序. 二.跨平台移动开发   Delphi使用android的NDK是通过JNI接口,封装好了,不用自己