Android中关于JNI 的学习(三)在JNI层訪问Java端对象

前面两篇文章简介了JNI层跟Java层的一些相应关系,包含方法名,数据类型和方法名称等,相信在理论层面。可以非常好地帮助我们去了解JNI在Native本地开发中的作用,对JNI的一些概念也有了一个初步的认识,因为表达能力或者理解还是有限,有些地方讲得不是非常清楚。假设各位朋友有认为云里雾里,欢迎大家留言一起学习。

概念上的理解有助于我们更好地认识JNI。而一些实际点的样例则可以更好地帮我们从代码上去掌握并应用JNI。

在第一篇文章,我们是从一个小样例来入门学习的,在当中,我们通过JNI层函数返回了一字符串。例如以下:

JNIEXPORT jstring JNICALL Java_com_lms_jni_HwDemo_printHello
  (JNIEnv *e, jobject j)
{
	return (**e).NewStringUTF(e,"Hello from T");
}

这是一种最简单的情况。但很多其它时候,我们须要在JNI层获得Java对象,对其进行操作。最后将结果返回到Java端。所以这个时候我们就要利用到JNI函数定义的第二个參数 jobject了。

上一篇文章,我们说过,JNIEnv *和jobejct參数都是JNI层方法加入的參数,关于JNIEnv*我们已经在前面的文章简介过。而jobject參数呢。则我们这一篇文章要操作到的參数了。

对于本地方法,即在Java中定义的native方法,有静态(static)和非静态的方法。而我们知道,静态方法它是属于这个类的方法,对象不能操作它。而非静态方法则刚好相反,所以在JNI层的方法參数中:

1)对于静态(static)方法,jobject參数表示的是相应Java类的引用。

2)对于非静态方法,jobject表示的是相应Java对象的引用。

这一点,应该不难理解。

接下来。我们通过一个小Demo来学习怎么在JNI层操作Java端的对象,而且改变当中的值。

首先,我们在Java类中定外一个static的变量testval,另一个方法changeTestVal(),用来改变testval的值,例如以下:

public class ParamTransferTest {

	public static int testval = 1;

	public native void changeTestVal();
	...
}

当然。首先,第一步,我们要在C中实现其相应的函数了,例如以下:

JNIEXPORT void JNICALL Java_com_lms_jni_ParamTransferTest_changeTestVal
  (JNIEnv * env, jobject obj){
	jclass clazz = (*env)->GetObjectClass(env,obj);
	jint val = (*env)->GetStaticIntField(env, clazz,
						(*env)->GetStaticFieldID(env, clazz,"testval","I"));
	LOGI("before change testval = %d", val);
	val = val + 1;
	LOGI("after change testval = %d", val);
	(*env)->SetStaticIntField(env, clazz,(*env)->GetStaticFieldID(env, clazz,"testval","I"),val);
}

我们在相应的c文件里来实现这个native方法,由于实现的是非静态方法,所以jobject传过来的就是对该对象的引用,所以我们须要通过GetObjectClass方法来获得该对象相应的类。

一般在JNI中,我们会利用FindClass和GetObjectClass两个方法来获得相应的类,并放到jclass类型的变量中去。只是在这里注意一点。用C实现和用C++实现的代码对于JNI的调用方法是不一样的。

在前面文章中说过。C++对JNINativeInterface定义的方法进行了一层包装,所以其參数不再须要传递env进去,而C则是须要的,比方上面*env调用的方法,假设是用C++实现的话。那么是不再须要传递env參数进去的,即 GetObjectClass(jobject)就能够了。

1)利用GetObjectClass方法获得jclass。

2)调用GetStaticIntFieldID获得相应class相应的变量,即jclass中的类型为I(即int)的静态(static)变量 testval。

3)调用GetStaticIntField获得相应变量的值 val。

4)改变val 的值,在这里,我们进行加1操作。

5)调用SetStaticIntField来设置相应变量的值。

所以。在这里我们发现。Env事实上提供了非常多的方法,对于訪问对象变量值的,分为静态非静态的,基本上就是Get<Type>Field和GetStatic<Type>Field,

而对应的,也有Set<Type>Field和SetStatic<Type>Field方法。

而假设调用方法呢,就是利用Call<Type>Method和CallStatic<Type>Method方法了,这些大家能够自己去jni.h文件里自己看一下。就大概知道怎么做了。

JNI层这边实现好了之后,我们利用ndk-build工具又一次生成一个so库。载入到Android中,在Activity中直接调用方法,例如以下:

		TextView tvChangeTestVal = (TextView)findViewById(R.id.tvChangeTestVal);
		ParamTransferTest ptt = new ParamTransferTest();
		ptt.changeTestVal();
		tvChangeTestVal.setText("" + ptt.testval);

我们调用方法之后,在屏幕上将调用方法后的值。显示出来,结果应该是1+1=2。对吧,看以下结果:

的确如我们所想像的,它的值已经变化成2了,对吧,说明我们的确是通过native方法在JNI层改变了其值。

我们刚才也在JNI中加入了log,来展示其改变前后的值,例如以下:

通过这样一个简单的小样例,相信大家应该就知道了怎么样在JNI层来操作Java端的数据了。对吧。

结束!

时间: 2025-01-01 00:30:55

Android中关于JNI 的学习(三)在JNI层訪问Java端对象的相关文章

Android中关于JNI 的学习(三)在JNI层访问Java端对象

前面两篇文章简单介绍了JNI层跟Java层的一些对应关系,包括方法名,数据类型和方法名称等,相信在理论层面,能够很好地帮助我们去了解JNI在Native本地开发中的作用,对JNI的一些概念也有了一个初步的认识,由于表达能力或者理解还是有限,有些地方讲得不是很清楚,如果各位朋友有觉得云里雾里,欢迎大家留言一起学习. 概念上的理解有助于我们更好地认识JNI,而一些实际点的例子则能够更好地帮我们从代码上去掌握并应用JNI. 在第一篇文章,我们是从一个小例子来入门学习的,在其中,我们通过JNI层函数返回

Android中设置文本颜色的三种方法及颜色大全

原文:Android中设置文本颜色的三种方法及颜色大全 源代码下载地址:http://www.zuidaima.com/share/1550463694572544.htm 1.利于系统自带的颜色类 如TextView1.setTextColor(Android.graphics.Color.RED); 2.数字颜色表示法 TextView1.setTextColor(0xffff00ff); 3.自定义颜色 TextView1.setTextColor(this.getResources().

Android中的context的学习理解

Android中Context的学习理解Context是一个抽象基类,通过它getResuources.getAssets and start 其他组件(Activity,Service,broadCast,getSystemService),可以这样理解:Context提供了一个运行环境for App, then app 可以访问资源,才能完成与其他组件,服务的交互,Context定义了一套基本的功能接口or一套规范 //todo

android NDK 实用学习-java端对象成员赋值和获取对象成员值

1,关于java端类及接口定义请参考: android NDK 实用学习-获取java端类及其类变量 2,对传过来的参数进行赋值: 对bool类型成员进行赋值  env->SetBooleanField(jobj, jfbdata, false); 对double类型成员进行赋值 env->SetDoubleField(jobj, jfddata, 209.22); 对int类型成员进行赋值 env->SetIntField(jobj, jfidata, 3653); 对byte类型成员

Android JNI 学习(三):JNI 数据类型和数据结构

本文我们来讨论一下JNI如何将Java类型映射到本机C类型. 一.基本数据类型 如下图表整理了Java基本类型和native对应的关系: Java类型 Native类型 描述 boolean jboolean unsigned 8 bits byte jbyte signed 8 bits char jchar unsigned 16 bits short jshort signed 16 bits int jint signed 32 bits long jlong signed 64 bit

Android中使用ShareSDK功能学习

前言:由于最近做了个项目用到了社会化分享的功能,之前从来没有碰到过这类功能,然后自己就一边查看资料,一边在项目中加入,慢慢摸索,这边文章算是自己对ShareSDK的学习笔记,有错误的地方,欢迎大家给予提出意见. 一.基本的步骤 一.首先,我们在mob官网上获取App Key和App Secret. 我就简略的上传一些图了.这边有一个官方提供的链接大家可以看看–http://bbs.mob.com/forum.php?mod=viewthread&tid=8212&extra=page%3D

详细解读Android中的搜索框(三)—— SearchView

本篇讲的是如何用searchView实现搜索框,其实原理和之前的没啥差别,也算是个复习吧. 一.Manifest.xml 这里我用一个activity进行信息的输入和展示,配置方式还是老样子,写一个输入框的配置文件,然后写定一个action <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/a

Android 中onSaveInstanceState和onRestoreInstanceState学习

1. 基本作用: Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate().onPause()等生命周期方法,它们并不一定会被触发.当应用遇到意外情况(如:内存不足.用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用. 但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就

Android笔记(三十一) Android中的异步更新(三) Handler (二)

先看简单示例:点击按钮,2s之后,TextView改变内容. package cn.lixyz.handlertest; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.Te