1.什么是JNI
Java Native Interface (JNI) 是一种编程框架,使运行在JVM之上的Java代码能够访问由其它语言(C,C++,汇编)编写的本地应用程序和库。
2.使用JNI的使用
2.1>编写JNI的Java文件
public class HelloWorld {
public native String displayMsg();
static {
System.loadLibrary("helloworld");
}
}
2.2>编译头文件(.h文件)
进入Android Project的目录中 :/ProjectName/bin/classes/包名/ 下:
可以看到里面后很多后缀为.class的文件,就是eclipse为我们自动编译好了的java文件,其中就有:HelloWorld.class文件。
退回到classes一级目录:/HelloWorld/bin/classes/
执行如下命令:
javah com.lucyfyr.HelloWorld
生成文件:包名_HelloWorld.h
注意:若包名是com.jni,则文件为com_jni_HelloWorld.h
2.3>头文件的介绍
可以看到自动生成对应的函数:Java_com_jni_HelloWorld_printJNI
Java_ + 包名(com.jni) + 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作;
java虚拟机就可以在com.jni.HelloWorld类调用printJNI接口的时候自动找到这个C实现的Native函数调用。
2.4>实现JNI原生函数源文件
#include <jni.h>
JNIEXPORT jstring JNICALL Java_com_jni_HelloWorld_displayMsg(JNIEnv * env, jobject obj) {
return (*env)->NewStringUTF(env, "Hello World! I am Native interface");
}
2.5>编译成so库
新建一个文件夹,比如TestJNI。再新建一个jni文件夹,将JNI原生函数源文件复制到jni文件夹内,并且配置Android.mk文件。
LOCAL_PATH:= $(call my-dir)
# 一个完整模块编译
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=com_lucyfyr_HelloWorld.c
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_MODULE := libHelloWorldJni
LOCAL_SHARED_LIBRARIES := libutils
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_TAGS :=optional
include $(BUILD_SHARED_LIBRARY)
系统变量解析:
LOCAL_PATH - 编译时的目录
$(call 目录,目录….) 目录引入操作符
如该目录下有个文件夹名称 src,则可以这样写 $(call src),那么就会得到 src 目录的完整路径
include $(CLEAR_VARS) -清除之前的一些系统变量
LOCAL_MODULE - 编译生成的目标对象
LOCAL_SRC_FILES - 编译的源文件
LOCAL_C_INCLUDES - 需要包含的头文件目录
LOCAL_SHARED_LIBRARIES - 链接时需要的外部库
LOCAL_PRELINK_MODULE - 是否需要prelink处理
include$(BUILD_SHARED_LIBRARY) - 指明要编译成动态库
注意:必须配置的有如下几个属性(Demo)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := helloworld
LOCAL_SRC_FILES := com_jni_HelloWorld.c
include $(BUILD_SHARED_LIBRARY)
编译的步骤: 1)打开cygwin
2)输入:$NDK
3)通过cd命令跳转到存放JNI的工程目录下(例如:TestJNI目录)
4)输入:$NDK/ndk-build
2.6>导入so文件
编译生成so文件时,会生成一个文件夹armeabi,该文件夹含有so文件,将整个armeabi复制到Android工程中的libs目录下即可。