最近在研究 Android 相机相关的东西,因为想要对相机做一个封装,于是想到要提供支持滤镜和图像动态识别相关的接口。在我找到一些资料中,它们的实现:一个是基于 OpenGL 的,一个是基于 OpenCV 的。两者都可以直接使用 Java 进行开发,受制于 Java 语言的限制,所以当对程序的性能要求很高的时候,Java 就有些心有余力不足了。所以,有些实现 OpenCV 的方式是在 Native 层进行处理的。这就需要涉及 JNI 的一些知识。
当然,JNI 并非 Android 中提出的概念,而是在 Java 中本来提供的。所以,在这篇文章中,我们先尝试在 IDEA 中使用 JNI 进行开发,以了解 JNI 运行的原理和一些基础知识。然后,再介绍下 AS 中使用更高效的开发方式。
1、声明 native 方法
1.1 静态注册
首先,声明 Java 类,
package me.shouheng.jni;
public class JNIExample {
static {
// 函数System.loadLibrary()是加载dll(windows)或so(Linux)库,只需名称即可,
// 无需加入文件名后缀(.dll或.so)
System.loadLibrary("JNIExample");
init_native();
}
private static native void init_native();
public static native void hello_world();
public static void main(String...args) {
JNIExample.hello_world();
}
}
native 的方法可以定义成 static 的和非 static 的,使用上和普通的方法没有区别。这里使用 System.loadLibrary("JNIExample")
加载 JNI 的库。在 Window 上面是 dll,在 Linux 上面是 so. 这里的 JNIExample
只是库的名称,甚至都没有包含文件类型的后缀,那么 IDEA 怎么知道到哪里加载库呢?这就需要我们在运行 JVM 的时候,通过虚拟机参数来指定。在 IDEA 中的方式是使用 Edit Configuration...
,然后在 VM options
一栏中输入 -Djava.library.path=F:\Codes\Java\Project\Java-advanced\java-advanced\lib
,这里的路径是我的库文件所在的位置。
使用 JNI 第一步是生成头文件,我们可以使用如下的指令,
javah -jni -classpath (搜寻类目录) -d (输出目录) (类名)
或者简单一些,先把 java 文件编译成 class,然后使用 class 生成 h 头文件,
javac me/shouheng/jni/JNIExample.java
javah me.shouheng.jni.JNIExample
上面的两个命令是可行的,只是要注意下文件的路径的问题。(也许