转载请标明出处:https://www.jianshu.com/p/72752c61fe79
本文出自:Jlanglang
前言
最近有个图片识别的需求.需要使用OpenCV,于是研究起了JNI,发现很多资料过旧.绕了大圈.踩了几个坑.总结一下.
什么是JNI
Java Native Interface
, 实现Java和其他语言的通信.
就是支持java与其他语言交互的,一般都是C/C++
Android studio配置
1.必须要下的两个东西:
打开SDKTools.
image.png
如图,下载CMake,NDK
2.要修改的配置文件
项目根目录
gradle.properties
中添加
android.useDeprecatedNdk=true
local.properties
中添加
ndk.dir=你的NDK路径名
//我的是ndk.dir=E\:\\sdk\\ndk-bundle
正题,如何实现JNI
1.java层怎么写接口.
创建一个java类.
package demo.hello;
public class HelloWorld {
//使用这种方法加载so库,如果你经常看framwork层的源码,就会发现很多这样的代码
static {
//这个是打包好的so库,可以先不管.
System.loadLibrary("HelloWorld");
}
//这是一个接口,通过这个接口与jni交互
public native String getString();
}
2.生成h头文件(旧)
这时build一下项目,然后在
image.png找到HelloWord.class文件.
然后通过cmd 切换路径到classes路径下.
再敲javah命令
javah -jni demo.hello.HelloWorld.class
包名生成h头文件
有人要吐槽了,你这说的啥玩意.看不懂.
哈哈,为什么只说这么一点点呢..
因为这个传统的方法真的是太操D了.我被坑了半天.有新的方法
往后看
传统的方法会碰到以下几个问题:
- java环境变量没配
- android环境变量没配
- 如果
HelloWorld
这个类中有导入其他的包,就会出现类找不到的情况.
我是Bitmap类找不到.需要把sdk目录下的
image.png 添加到环境变量里面.
或者使用命令行:
javah -classpath E:\sdk\platforms\android-26\android.jar;. -jni com.demo.HelloWorld
规则:javah -classpath 环境路径; . -HelloWordl的路径
以上这些问题都没什么,最重要的问题是,传统方法,在AS里面写C++是没有代码提示的!!!!!这还能玩????
起飞,新方式:
升级AS到2.2版本以上.最好3.0
image.png
选上!.
image.png下一步下一步,到这个页面.可以啥不改,啥不选.
有3个,1个是选择C++版本.下面两个勾选一个是异常,一个是debug功能吧.
创建完成后是这样的.
image.png我的AS版本是3.0,以上是自动生成的目录与文件.
最主要的是这个CMakeLists.txt
可以看看官方的文档说明
老项目怎么办?
可以使用老jni项目,以及使用MK文件来配置环境
比如我现在写的就是这样的:
image.png
放C++文件的目录叫什么其实并不重要
可以看到里面有2个文件.这是旧方式实现所需要的.我直接移植过来了.
android.mk
application.mk
怎么让老项目支持?简单
点击你的app目录,右键.
image.png image.png image.png
选到自定义jni目录,然后选择Android.mk文件就行了.
AS会根据里面的配置自动生成CMake文件
还可以:
在App目录下的build.gradle
里
android{
defaultConfig {
// ...
ndk {
abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64'
}
}
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
}
Android.mk内容(注意只是参考,里面内容要根据提示修改,比如LOCAL_SRC_FILES,要都改成你自己写的cpp文件名)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OpenCV_INSTALL_MODULES := on
OpenCV_CAMERA_MODULES := off
#opencv编译成静态库
OPENCV_LIB_TYPE :=STATIC
#设定OpenCV.mk文件的地址
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
include ../native/jni/OpenCV.mk#注意这里要根据自己的native地址修改
else
include $(OPENCV_MK_PATH)
endif
#自己编译出的动态库名字
LOCAL_MODULE := so库的名字
#你要打包的C++文件名,多个文件换行用\隔开
LOCAL_SRC_FILES := a.cpp \
b.cpp \
c.cpp
#要加入的C++基础库
LOCAL_LDLIBS += -lm -llog -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
Application.mk内容
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions -std=c++11 -O3 #C++编译器flag
APP_OPTIM := release #设定编译动态库的版本 debug或者release
环境配置完了,怎么写?
在新建的项目中
我随便写一个native方法.
image.png image.png
alt+enter提示.
打开native-lib.cpp,惊不惊喜,意不意外
image.png修改cpp
image.png
调用运行
image.png
结果:
image.png
生成so文件在这里
image.png
结语:
以上为昨天所有心得,早上开始找资料,基本上都是老方法.
最后用老方法配置好了(真的很麻烦..各种配置)
到了下午,发现了新方法.google老大就是体贴.哈哈
您的喜欢与提问回复是我最大的动力-_-
交流群:493180098
网友评论