JNI/NDK

参考链接:

http://blog.csdn.net/xyang81/article/details/41759643

http://blog.csdn.net/banketree/article/details/12167145


JNI  java native interface java中定义的连接C好C++ 的接口的一种实现方式

相信很多做过 Java 或 Android 开发的朋友经常会接触到 JNI 方面的技术,尤其做过 Android 的朋友,为了应用的安全性,会将一些复杂的逻辑和算法通过本地代码(C或C++)来实现,然后打包成.so动态库文件,并提供 Java 接口供应用层调用,这么做的目的主要就是为了提供应用的安全性,防止被反编译后被不法分子分析应用的逻辑。当然打包成.so也不能说完全安全了,只是相对反编译 Java 的 class 字节码文件来说,反汇编.so动态库来分析程序的逻辑要复杂得多,没那么容易被破解。比如百度开放平台提供的定位服务、搜索服务、LBS 服务、推送服务的Android SDK,除了Java接口的jar包之外,还有一个.so文件,这个.so就是实现了Java层定义的native接口的动态库。

以前公司有一个 JavaWeb 的项目,其中有一个用户注册的模块,需要验证用户的手机号(流程大家都懂的),由于这个项目的用户量不大,没用采用运营商的短信网关接口,直接采购了一台 16 口的短信猫设备和 SIM 卡来解决这个事情。由于短信猫设备只提供了 C 的接口,而 Java 是不能直接与 C 语言进行交互的,所以 JNI 就派上用场了,先在 Java 层定义好发送短信、接收短信、短信发送队列等相关 native 方法,然后用 javah 命令将定义 Java native 接口的 class 字节码文件生成.h头文件(这个后面会讲到),最后用设备场商提供的 C 接口来实现 java 的 native 方法,完了之后编译成.dll或.so动态库,提供给 Java 程序使用即可。

JNI在Cocos2d-x游戏引擎中也经常用到,该引擎是用纯C++开发的,而且是跨平台的,依托C++的跨平台特性,只需用C++编写一次逻辑,就可以将游戏打包发布到不同的平台(iOS、Android、WinPhone、黑莓、Linux、Windows),打包发布的细节就不在这里讨论了。如果游戏要发布到Android平台,开发过程当中,少不了C++层和Java层进行交互,比如游戏当中要打开一个网页、播放一段视频或打开一个新的窗口等,这些在C++层实现是非常麻烦的,如果用Android应用层提供的API就变得相当容易。所以这时就不得不写JNI来完成这些功能的需求。当然这些常用的JNI操作,Cocos2d-x引擎进行了封装,相关的接口定义在JniHelper.cpp这个类中,可以拿来直接使用。(后面会有例子详细介绍)
虽然现在的物联网和智能家居行业还处于萌芽状态,但随着这个时代在技术的创新与不断改进的发展下,想象5年后,物联网和智能家居行业真正成熟起来,由于Android系统的开源,自然会被各大硬件场商所采用,相当于这几年Android智能手机的市场一样,仍然可能会处于移动智能终端的霸主地位。你可能会问,但这和JNI和有什么关系呢?当各种设备接入互联网的同时,自然少不了人机交互的应用程序,当应用程序需要调用硬件特定的功能时,此时只能通过C或C++封装对应功能的JNI接口来供上层应用使用。比如要用手机中的app控制家里的电灯、窗帘、冰箱、空调等一切智能的电子设备时,自然少不了应用要和底层硬件进行通讯,至于各种智能设备的运行控制,自然是由厂商来实现,他们只需提供操作设备相关功能的接口即可。虽然厂商会封装好JNI接口,但我们也要了解下jni与java通讯的原理,以便我们在开发过程当中遇到问题时,能够快速定位到问题。这只是我对未来物联网或智能家居发展的一些猜测,欢迎大家一起讨论!

NDK native development kit 开发JNI调试工具

使用JNI需要挂载NDK工具

谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwin才能使用NDK。而在NDKr7开始,Google的Windows版的NDK提供了一个ndk-build.cmd的脚本,这样,就可以直接利用这个脚本编译,而不需要使用Cygwin了。只需要为Eclipse Android工程添加一个Builders,而为Eclipse配置的builder,其实就是在执行Cygwin,然后传递ndk-build作为参数,这样就能让Eclipse自动编译NDK了。

NDK是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。它集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。它可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

Java通过JNI机制和C/C++沟通的具体步骤

1、编写包含native本地方法的java类
2、通过javah工具生成C/C++语言的头文件
3、使用C/C++语言实现头文件
4、使用交叉编译工具对C/C++本地代码进行编译,最后通过链接生成*.so可执行的C/C++库
5、实际执行Java代码去和本地的C/C++代码互相沟通

当java需要C/C++代码时,在DalvikVM虚拟机中加载动态链接库时,会先调用JNI_Onload()函数,此时就会把javaVM对象的指针存储于C层JNI组建的全局环境中,在JAVA层调用C层的本地库函数时,调用C本地函数线程必然通过Dalvik VM来调用C本地函数,测试Dalvik虚拟机会为本地的C组建实例化一个JNIEnv指针,该指针指向Dalvik虚拟机的具体函数列表,当JNI的C组件调用java层方法和属性时,需要通过JNIEnv指针来进行调用。

当C++组件主动调用Java层方法时,需要通过JNI的C组件把JNIEnv指针传递给C++组件,此后,c++组件即可通过JNIEnv指针来掌控Java层代码。

总结:

对于JNI和NDK很多Android开发初学者没有搞明白这个问题,JNI是Java调用Native机制,是Java语言自己的特性全称为Java Native Interface,类似的还有微软.Net Framework上的p/invoke,可以让C#或Visual Basic.NET可以调用C/C++的API,所以说JNI和Android没有关系,在PC上开发Java的应用,如果运行在Windows平台使用JNI是是经常的,比如说读写Windows的注册表。而NDK是Google公司推出的帮助Android开发者通过C/C++本地语言编写应用的开发包,包含了C/C++的头文件、库文件、说明文档和示例代码,我们可以理解为Windows Platform SDK一样,是纯C/C++编写的,但是Android并不支持纯C/C++编写的应用,同时NDK提供的库和函数功能很有限,仅仅处理些算法效率敏感的问题,所以Android123推荐初学者学好Java后再学习JNI。

简单点说,用C语言生成一个库文件,在java中调用这个库文件的函数。JNI的过程比较复杂,生成.so需要大量操作,而NDK就是简化了这个过程。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值