NDK和JNI解析与应用

目前有很多的招聘公司,在招聘android程序工程师的时候,在应聘要求中明确的提出了要熟悉NDK开发,或者是了解JNI开发,甚至是精通NDK和JNI开发,很多小伙伴对JNI都有所耳闻,特别是研究过java虚拟机的同学,但是这种对jni的了解,并没有使他们拥有精通jni的勇气,反而使他们感觉jni很难,反而不想去学,产生了畏难的心理,对于一些没有接触过jni的同学来说呢,刚开始是报着必胜的心态去学习JN的,但是因为一直学习的是java,一看现在jni还要牵涉到C语言,顿时感觉jni无比的高深,在心理上就首先投降了JNI。

JNI真的很难吗?

android工程师必须要学习JNI吗?

应该怎么学习JNI?

接下来,我通我对jni的学习来阐述一下我的观点:

首先:说一句,jni不简单,但是作为android工程师,我们没有必要精通jni;

什么是JNI(Java Native Interface)?

其实JNI就是java接口语言(不是等于没说吗???),那什么又是java接口语言呢?说白了,就是我们的java程序调用C程序的一个过度,一个翻译,在此有很多人有一个误解,就是一直以为jni是android的技术,其实这种想法是错误的,jni是java中的技术,例如当我们用java在windows上开发程序,用jin调用系统的C代码是很经常的,我们的运行在windows上的JVM也是依靠JNI和windows来进行沟通的。

  什么是NDK?

NDK是google为方便Android开发者通过C/C++本地语言编写应用的开发包,其中有很多工具,比如我们在windows环境上写好C代码,我们可以用其中的ndk-build把C代码打包成.so文件(.so文件是运行在linux上的函数库文件)。

解压后的NDK文件目录:

jni和ndk的具体概念我们已经了解了,接下来我们就来看看如何开发jni程序:

首先还有讲解一下,C代码在windows上和在linux上的一些不同

Windows:

C -> .O -> .exe    .dll(wendow下的函数库)

Linux

C-> .O ->.elf      .so(Linux下的函数库)  .a(linux下的静态函数库)

我们在android项目中,就是要把我们写的c代码打包成.so文件库,供java调用


开发步骤:

一:在java代码中创建一个native方法:

public native String helloWorldFromC();

二:android工程这中创建一个jni文件夹

三:在jni文件夹中写c代码,c代码中要有include<jni.h>

c代码中的方法名,应该是Java_加上全类名(把全类名的“.”变为“_”)加上java native的方法名

方法名也可以不用手写,当定义好javanative方法后,在控制台输入 javah [类的全类名],此时可以得到c语言实现java代码的头文件,把头文件导入jni文件夹中,并且在实现的c代码中导入该头文件,方法名从头文件中复制即可;


四:把c代码打包成函数库:在控制台进入到工程目录,然后ndk-build;

注意:在ndk-build之前,jni文件夹中还需要有一个Android.mk文件;

Android.mk:告诉编译器如何把C代码打包成函数库,此文件也在jni文件夹


五:在java代码中引入函数库


注意:引入函数库的时候,不要看见xxxx.so,就把前面的名字引入,而是写自己在android.mk文件中定义的要打包的函数库的名字,此时应该是hello;

六:java中调用方法

在此打印一个Toast:


最后目录结构为:


以上就是比较简单但是非常全面的在android中开发jni的步骤。

接下来我们来看一下怎么在java调用c代码的时候,向其传递参数:

在此只贴出代码,其原理都是一样的,只是一些规则和细节,需要查阅相关资料:

java本地代码:

C代码:

注意:当我们传递java字符串时,在jni中,我们应该把java字符串转换为C代码中的字符数组,用如下方法即可:

Sdk开发常见错误:

1.java Native 不能是private的;

2.Jni文件夹命名错误;

3.方法名称写错(因为比较长,所以要注意)

4.直接工程异常,没有日志打印,一般是c代码运行错误;

5.Android.mk文件中不要用中文的回车和空格

6.引用别人的函数库(.so文件),需要自己的含有native方法的包名和函数库的方法名中的包名一致;


通过以上的讲解,我再来回到在文章开头提问的几个问题:

JNI难吗?

JNI本身并不简单,只是根据自己所处的领域,和自己的实际情况来决定学习的深度,当然如果对这方面比较有兴趣,多学习一些东西总是好的。

android工程师有必要学习JNI吗?

在android开发中,比如加密,计算等一些问题,我们为了提高效率或者安全方面的考虑,JNI确实是一个很好的选择,但是在android开发中一个项目中并不会大量的使用,所以,我们学习的时候,没有必要去钻牛角尖。

应该怎么学习JNI?

看文档,看NDK中的头文件。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章