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。对吧,看以下结果:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlubWlhbnNoZW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="font-size:12px">
的确如我们所想像的,它的值已经变化成2了,对吧,说明我们的确是通过native方法在JNI层改变了其值。
我们刚才也在JNI中加入了log,来展示其改变前后的值,例如以下:
通过这样一个简单的小样例,相信大家应该就知道了怎么样在JNI层来操作Java端的数据了。对吧。
结束!
Android中关于JNI 的学习(三)在JNI层訪问Java端对象的更多相关文章
- Android中的SQLite使用学习
Android中的SQLite使用学习 SQLite是非常流行的嵌入式关系型数据库,轻载, 速度快,而且是开源.在Android中,runtime提供SQLite,所以我们可以使用SQLite,而且是 ...
- Android JNI入门第三篇——jni头文件分析
一. 首先写了java文件: public class HeaderFile { private native void doVoid(); native int doShort(); native ...
- Android学习记录(3)—Android中ContentProvider的基本原理学习总结
一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.虽然使用其他方法也可以对外共享数据 ...
- android中的线程池学习笔记
阅读书籍: Android开发艺术探索 Android开发进阶从小工到专家 对线程池原理的简单理解: 创建多个线程并且进行管理,提交的任务会被线程池指派给其中的线程进行执行,通过线程池的统一调度和管理 ...
- android NDK 实用学习(二)-java端对象成员赋值和获取对象成员值
1,关于java端类及接口定义请参考: android NDK 实用学习-获取java端类及其类变量 2,对传过来的参数进行赋值: 对bool类型成员进行赋值 env->SetBooleanF ...
- Android JNI 学习(三):JNI 数据类型和数据结构
本文我们来讨论一下JNI如何将Java类型映射到本机C类型. 一.基本数据类型 如下图表整理了Java基本类型和native对应的关系: Java类型 Native类型 描述 boolean jboo ...
- 详细解读Android中的搜索框(三)—— SearchView
本篇讲的是如何用searchView实现搜索框,其实原理和之前的没啥差别,也算是个复习吧. 一.Manifest.xml 这里我用一个activity进行信息的输入和展示,配置方式还是老样子,写一个输 ...
- Android中的AlertDialog使用示例三(单向选择确定对话框)
在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框,AlertDialog实现方法为建造者模式. ...
- Android 中onSaveInstanceState和onRestoreInstanceState学习
1. 基本作用: Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate().onPaus ...
随机推荐
- js数组遍历some,foreach,map,filter,every对比
1. [...].some(ck)函数 ---- 某个一个为true,则为true 对数组中每个元素执行一次ck函数,知道某个元素返回true,则直接返回true.如果都返回f ...
- Vim常用操作-Nginx配置文件批量加注释。
刚接触 Vim 会觉得它的学习曲线非常陡峭,要记住很多命令.所以这个系列的分享,不会教你怎么配置它,而是教你怎么快速的使用它. 本期我们要实现给 Nginx 配置文件批量注释的功能,先来看效果: 操作 ...
- ASP.NET Core 依赖注入(DI)简介
ASP.NET Core是从根本上设计来支持和利用依赖注入. ASP.NET Core应用程序可以通过将其注入到Startup类中的方法中来利用内置的框架服务,并且应用程序服务也可以配置为注入. AS ...
- [转载] java多线程学习-java.util.concurrent详解(四) BlockingQueue
转载自http://janeky.iteye.com/blog/770671 ------------------------------------------------------------- ...
- Cordic算法——圆周系统之旋转模式
三角函数的计算是个复杂的主题,有计算机之前,人们通常通过查找三角函数表来计算任意角度的三角函数的值.这种表格在人们刚刚产生三角函数的概念的时候就已经有了,它们通常是通过从已知值(比如sin(π/2)= ...
- 25个Java机器学习工具和库
本列表总结了25个Java机器学习工具&库: 1. Weka集成了数据挖掘工作的机器学习算法.这些算法可以直接应用于一个数据集上或者你可以自己编写代码来调用.Weka包括一系列的工具,如数据预 ...
- C语言的scanf函数
一. 变量的内存分析 1. 字节和地址 1> 内存以“字节为单位”,Oxffc1,Oxffc2,Oxffc3,Oxffc4....都是字节 ,0x表示的是十六进制 2> 不同类型占用的字节 ...
- 机器学习实验一SVM分类实验
一.实验目的和内容 (一)实验目的 1.熟悉支持向量机SVM(Support Vector Machine)模型分类算法的使用. 2.用svm-train中提供的代码框架(填入SVM分类器代码)用tr ...
- 谈谈微服务中的 API 网关(API Gateway)
前言 又是很久没写博客了,最近一段时间换了新工作,比较忙,所以没有抽出来太多的时间写给关注我的粉丝写一些干货了,就有人问我怎么最近没有更新博客了,在这里给大家抱歉. 那么,在本篇文章中,我们就一起来探 ...
- dij洛谷电车
//Gang #include<iostream> #include<cstring> #include<algorithm> #include<cstdio ...