jni是java本身就支持的,现在Android如果要用原生的话,
会比较麻烦,所以Android弄了个NDK,是为了更方便使用jni的。所以我下面讲的是在Eclipse里使用NDK的案例。
一.首先,下载个NDK,解压放到合适的位置。
二. 然后我们配置下NDK的环境,
打开eclipse–>选择Window–>Preferences–>选中Android,展开—->点NDK—- >在右边NDK Location里输入解压的那个NDK的根目录
比如说:D:\android-ndk-r13b
但报错说不是一个有效的目录,这时候,我们要在解压的那个NDK的根目录下新建一个空文件,名字叫ndk-build.然后重新再输入路径就不会出错了。
三. 创建个项目,选中项目,右键—》Android Tools—》Add Native Surport。
随便起个名,这个就是动态链接库的名字,finish,这个时候在项目里就会自动添加obj文件夹和jni文件夹,我们主要关注jni文件夹,obj文件夹是存放C/C++编译出来的文件的。jni里有一个Android.mk文件,和一个默认的.cpp文件,这个文件就是用来写c++代码的。编译一下项目你会发现有多了一些莫名其妙的东西。
因为这个.cpp里的东西怎么写要看调用者是什么,所以我们从调用者那里开始理一下使用方法。
比如说:我想在MainActivity.java 这个类里求两数的和,但是因为这个求和代码非常需要效率,所以我希望用C++代码实现,然后我来调用C++里的方法。
然后我希望C++代码里有个addNum方法传两个参数。
那么,首先,我要把那个人叫过来,就是加载动态链接库
static{
System.loadLibrary("Test");
}
这个一般写在静态区,然后那个Test就是创建的那个动态链接库的名字
如果C++里有这个addNum方法,然后我直接调用它,这是不可能的,编译器找不到这个方法,所以我们要先编译器,我在其他地方有这个方法,我可以去调用。
就是这样定义一下这个方法
private native int addNum(int a,int b);
然后,你再调用这个方法,比如叫那个人帮你算1+1;
int i = addNum(1, 1);
但是这样还是没法调用C++里的方法,我们还需要让调用C++方法的Java类生成一个头文件。然后让C++那个类include这个头文件。
这个有点像信物啊!哈哈!
你拿着这块玉佩去找当今的武林盟主。然后叫他帮你算道数学题。
这个jni的机制不太懂,我乱说的。
四. 怎么生成这个头文件呢,要用到jdk里的javah.exe.。
我们打开windows的cmd
进入项目的src目录,执行
javah com.hyw.test.MainActivity
其中,com.hyw.test.MainActivity是要生成头文件的全类名,注意不用.java或.class哦。
这时候在项目的src文件目录下就会生成以.h结尾的头文件了,如果有内部类的话会生成多个。注意文件名很有意思,就要这样的哦。(全类名把点换成下划线)。
点进去发现报错,这是因为那个jni.h找不到,那么,我们就要告诉他在哪
eclipse菜单栏 —-》project—-》Properties—–》C/C++ General —–》 Paths and Symbols —-》add—-》
在弹出框的那个框框里输入ndk目录下的这个目录
android-ndk-r13b\platforms\android-24\arch-arm64\usr\include
当然,要灵活变通
可以用那个file system选,注意上面那个不是完整路径,下面这个才是
D:\android-ndk-r13b\platforms\android-24\arch-arm64\usr\include
确定再确定,错误不见了。
回到正题,为了方便那个C++文件include头文件,我们把头文件移到jni文件夹,其实生成的时候就可以指定文件夹的,不过我忘了怎么弄了
五. 我们在那个c++文件里这样导入
#include <com_hyw_test_MainActivity.h>
然后我们要写那个方法了,这里有个问题就是jni里的数据类型跟Java的是不一样的,看图
所以方法里的类型名会有一些不同,其实有很多奇怪的地方,
jint Java_com_hyw_test_MainActivity_addNum
(JNIEnv *env, jobject obj, jint a, jint b){
return a+b;
}
返回类型是jint
方法名是这样写的哦,注意前面还有个Java_
JNIEnv *env 跟 jobject obj这两个参数是默认需要的
打完收工。