什么是JNI:
JNI java本地开发接口
JNI 是一个协议
这个协议用来沟通java代码和外部的本地代码(c/c++).
通过这个协议,java代码就可以调用外部的c/c++代码
外部的c/c++代码也可以调用java代码
1.配置ndk环境,windows -->Preferences -->Android -->NDK -->NDK Location,这在个输入栏中添加android-ndk-r9在硬盘上的路径.
如图:
2.在Java代码中写上带有native关键字的方法:public native int add(int a,int b);
3.利用ndk工具生成jni文件夹
右键工程Android Tools -->
Add Android Native Support -->library name 在输入栏中输入动态链接库文件名,后缀名默认为.so ,这里输入为third.
因为在Android下
的Linux环境下的动态链接库文件为.so,而在windows下为.dal文件. 操作成功后会在工程目录下生成jni文件夹,文件夹下有Android.mk文件和刚才输入third
.cpp,若是通
过jni调用c代码的就将后缀名改为c即可,同时Android.mk文件中的
LOCAL_SRC_FILES :
= third.cpp也更改为
LOCAL_SRC_FILES :
= third.c,该文件中还有一个宏定
义
LOCAL_MODULE :
= third,就是动态链接库.so文件的名字为third.而在third文件中自动包含一个头文件include<jni.h>,该头文件是一些Java与C/C++之间数据类
型转换的C函数.
如图所示:
4.由于在JAva代码中已经写了
public native int add(int a,int b);方法
若是jdk1.6(包含)一下的环境,则需在工程目录下的classes文件下用命令行的方式输入 javah 包名和类名
若是1.6以上的环境则在工程源文件src目录下输入 javah 包名 和类名
如图所示;
在eclips下刷新刚才的工程目录就会在src目录下看见
com_itheima_thirdjni_MainActivity.h头文件
如图所示:
然后将该文件移动到jni文件夹下,并在.c文件中拷贝
JNIEXPORT
jint
JNICALL
Java_com_itheima_thirdjni_MainActivity_add
(JNIEnv *, jobject, jint, jint);
该方法,删除
JNIEXPORT与
JNICALL(也可以不删),最后就是
jint
Java_com_itheima_thirdjni_MainActivity_add
(
JNIEnv
*,
jobject
,
jint
,
jint
)
{
}
添加四个变量名 JNIEnv *env, jobject obj , jint a , jint b,第一个env是jni.h头文件中的结构体指针变量,可以通过该指针调用结构体里面的函数指针进而调用 C/C++中相应的方法.第二个obj就是刚才src目录下通过javah命令中的类名所对应的对象,这两个参数必须有,是系统自动就带的,而后面两个参数是在java中用native关 键字申明的方法中的参数变量.Jint是返回类型,与native方法所对应
jint
Java_com_itheima_thirdjni_MainActivity_add
(
JNIEnv
*env,
jobject
obj,
jint
a,
jint
b
){
然后在{}中写入c代码,并且可以调用jni.h中的函数,为了防止jni.h头文件找不到可以再
配置 右键工程 properties c/c++ general path and symbols incluse 输入D:\android-ndk-r9\platforms\android-9\arch-arm\usr\include(ndk文件中的路径)
如图所示:只有在第4个步奏完了之后才可以做该操作,否则右键工程属性是没有C/C++General这个目录的,该操作完之后会在jni文件夹下走动包含jni.h头文件
5.然后在jni文件夹下的.c/cpp文件中就可以调用c/c++的代码了.
6.最后在java代码中用static代码快写入System.loadLibrary(类库名.so),类库名就是在第3步中图片所指的内容,就可以加载.so类库了,该文件在libs/armeabi目录下,也是在
第4个操作后生成的.
由第4步操作生成的类库文件是在Arm CPU和Linux操作系统下运行的,在其它平台下还有mips CPU和
intel的x86 CPU,在不同平台下需要的.os文件也是不同的,
因此可以再jni文件夹下创建Application.mk文件,必须是该名字,里面写入APP_ABI := all 即可
7.运行Android程序,会自动在libs目录下生成如下.so文件,是在不同平台下生成的.so文件,这就是所谓的交叉编译
8.
常见错误
1, 01-26 06:26:21.308: E/AndroidRuntime(1417): Caused by: java.lang.UnsatisfiedLinkError: Couldn't load check: findLibrary returned null
1.忘记写 System.loadLibrary(“xxx”); 注:libxxx.so
2. 找不到对应cpu型号的.so文件
9.程序运行顺序:
1.加载.so文件通过System.loadLibrary("类库名.so"),通过libs下的不同版本并根据不同平台加载.so文件
2.调用java中native方法
3.由native方法去掉用jni文件夹中的C/C++文件中与native方法相对应的函数,然后执行函数中的JNI代码返回结果