JNI相关配置javah,ndk-build和指令集以及.mk文件详细讲解(亲测可用)
2016-12-29 19:07
786 查看
关于JNI,相比大家都不陌生,主要是最近工作用到了很多JNI相关的内容,踩了很多坑,记录下为了以后的学习者少走弯路.
一.先写一下Android studio NDK的下载和配置方式.
1.Ctrl+alt+S打开Settings面板
2.搜索界面输入SDK,之后选择SDK Tools
3.选择NDK工具点击OK下载即可.
点击NDK选中即可下载,建议把CMake一同下载
下载完需要配置NDK的路径
按住Ctrl+Shift+Alt+S打开Project Structure,选择SDK Location,选择下载的NDK-bundle的位置,如下图所示
二.javah和ndk-build的作用以及Android studio配置方式和linus指令集生成
1.javah命令的作用:生成java调用c++文件所需的.h头文件,头文件要符合JNI的规范 JAVA_包名类名方法名,具体实例如下
2.Android External Tools工具中配置javah命令和ndk-build命令
javah命令的配置方式及相关参数
打开Settings界面,选择ExternalTools工具,点击+号,如下图所示
Program: JDKPath\bin\javah.exe
Parameters: -classpath . -jni -o ModuleFileDir/src/main/jni/Prompt FileClass
Working Directory: ModuleFileDir\src\main\Java
使用方式,在生成之前先选择build—make project编译下代码生成对应的.class字节码文件,选中要生成.h头文件的类,右键External Tools—javah 会弹出一个需要输入生成的文件的名字
生成之后的.h文件在jni目录下
之后就会在和java同级的目录下生成jni的文件夹,里面存放着.h头文件.
Android studio ndk-build指令生成.so文件的配置方式
Program配置的是ndk-build.cmd的安装目录
Working Directory指的是工作空间的目录
三.JNI中.mk文件的格式和作用.
在jni的目录下新建一个Android.mk文件,内容如下
LOCAL_PATH := (callmy−dir)include(CLEAR_VARS)
LOCAL_MODULE := nativeTest
LOCAL_SRC_FILES := nativeTest.cpp
include (BUILDSHAREDLIBRARY)LOCALMODULE指的是要生成的.so文件的名字LOCALSRCFILES指的是c或者c++的源代码.之后再创建一个Application.mk文件APPPROJECTPATH:=(call my-dir)
APP_MODULES := nativeTest
APP_ABI:= all
APP_ABI指的是生成的.so文件支持的CPU架构,指定All就是指生成所有的类型的CPU架构
生成后的libs文件如图所示
然后再写一下Android studio中调用.so,so文件的存放方式.可以调用成功的有两种配置方式
第一种就是在main目录下和java平级创建jniLibs文件夹,创建不同的CPU架构的文件夹,如下图所示:
第二种方式是把.so放入和src平级的libs目录下,但是要在gradle文件夹下配置一些命令,如图所示
gradule文件如下图所示
注意代码是添加在Android节点下面
代码如下:
sourceSets.main{
jni.srcDirs = []
jniLibs.srcDir “src/main/libs”
}
或者
sourceSets.main{
jniLIbs.srcDirs = [‘libs’]
}
这个代码配置的作用就是更改jniLibs目录指向libs.
主要是因为Android studio和之前的eclipse的目录结构的不同造成的.
javah指令集的调用方式,简单来说就是进入到java目录,找到确切的类执行javah命令具体如下
-d ../jni testjni.jnidemo.AndroidJNI(包名.类名)
下面讲解一个jni调用的完整demo,附带源码
1.先创建一个带有native方法的类 HelloWorld.class
然后用刚才配置的javah命令工具或者javah linux指令集生成.h头文件
build–make project 之后再运行javah命令,生成的HelloWorld.h如下
注意生成的.h文件 方法名命名方式java–包名–类名–方法名的形式
本地方法的实现HelloWorld.cpp代码如下:
Android.mk代码
Application.mk代码
注意.cpp文件要把.h包含进去,然后还要遵循JNI的规范,注意传入的数据类型,native方法是没有参数的,但是JNI的实现方法带有两个参数,第一个是个JNI引用的指针,第二个要注意是jclass还是jobject,之前我执行ndk.builid的时候一直报错,就是因为.h文件和.cpp文件的数据类型不一致造成的.
然后进入项目的jni文件夹下,如图所示
之后执行ndk-build指令,前提是你配置了ndk的环境变量,配置方式我就不多做阐述了.执行之后的效果如下
之后刷新下,会发现多了两个目录,libs和obj
然后把libs目录下的所有文件夹复制到jniLIbs文件夹下就可以了
java代码的调用代码如下
在activity中 通过静态代码块加载.so文件,之后就可以把c++的字符串通过jni调用显示到一个textview上面了
static {
System.loadLibrary(“test”);
}
tv1.setText(HelloWorld.stringFromJNI1());
Android相关部分比较简单就不过多阐述了.
希望我的demo对你有所提高.
不足之处请指教!直接在评论区提出你的问题即可,我们共同研讨
一.先写一下Android studio NDK的下载和配置方式.
1.Ctrl+alt+S打开Settings面板
2.搜索界面输入SDK,之后选择SDK Tools
3.选择NDK工具点击OK下载即可.
点击NDK选中即可下载,建议把CMake一同下载
下载完需要配置NDK的路径
按住Ctrl+Shift+Alt+S打开Project Structure,选择SDK Location,选择下载的NDK-bundle的位置,如下图所示
二.javah和ndk-build的作用以及Android studio配置方式和linus指令集生成
1.javah命令的作用:生成java调用c++文件所需的.h头文件,头文件要符合JNI的规范 JAVA_包名类名方法名,具体实例如下
2.Android External Tools工具中配置javah命令和ndk-build命令
javah命令的配置方式及相关参数
打开Settings界面,选择ExternalTools工具,点击+号,如下图所示
Program: JDKPath\bin\javah.exe
Parameters: -classpath . -jni -o ModuleFileDir/src/main/jni/Prompt FileClass
Working Directory: ModuleFileDir\src\main\Java
使用方式,在生成之前先选择build—make project编译下代码生成对应的.class字节码文件,选中要生成.h头文件的类,右键External Tools—javah 会弹出一个需要输入生成的文件的名字
生成之后的.h文件在jni目录下
之后就会在和java同级的目录下生成jni的文件夹,里面存放着.h头文件.
Android studio ndk-build指令生成.so文件的配置方式
Program配置的是ndk-build.cmd的安装目录
Working Directory指的是工作空间的目录
三.JNI中.mk文件的格式和作用.
在jni的目录下新建一个Android.mk文件,内容如下
LOCAL_PATH := (callmy−dir)include(CLEAR_VARS)
LOCAL_MODULE := nativeTest
LOCAL_SRC_FILES := nativeTest.cpp
include (BUILDSHAREDLIBRARY)LOCALMODULE指的是要生成的.so文件的名字LOCALSRCFILES指的是c或者c++的源代码.之后再创建一个Application.mk文件APPPROJECTPATH:=(call my-dir)
APP_MODULES := nativeTest
APP_ABI:= all
APP_ABI指的是生成的.so文件支持的CPU架构,指定All就是指生成所有的类型的CPU架构
生成后的libs文件如图所示
然后再写一下Android studio中调用.so,so文件的存放方式.可以调用成功的有两种配置方式
第一种就是在main目录下和java平级创建jniLibs文件夹,创建不同的CPU架构的文件夹,如下图所示:
第二种方式是把.so放入和src平级的libs目录下,但是要在gradle文件夹下配置一些命令,如图所示
gradule文件如下图所示
注意代码是添加在Android节点下面
代码如下:
sourceSets.main{
jni.srcDirs = []
jniLibs.srcDir “src/main/libs”
}
或者
sourceSets.main{
jniLIbs.srcDirs = [‘libs’]
}
这个代码配置的作用就是更改jniLibs目录指向libs.
主要是因为Android studio和之前的eclipse的目录结构的不同造成的.
javah指令集的调用方式,简单来说就是进入到java目录,找到确切的类执行javah命令具体如下
-d ../jni testjni.jnidemo.AndroidJNI(包名.类名)
下面讲解一个jni调用的完整demo,附带源码
1.先创建一个带有native方法的类 HelloWorld.class
package com.geocompass.sdk.map.jni; /** * Created by liuxu on 2016/12/28. */ public class HelloWorld { public static native String stringFromJNI1(); }
然后用刚才配置的javah命令工具或者javah linux指令集生成.h头文件
build–make project 之后再运行javah命令,生成的HelloWorld.h如下
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_geocompass_sdk_map_jni_HelloWorld */ #ifndef _Included_com_geocompass_sdk_map_jni_HelloWorld #define _Included_com_geocompass_sdk_map_jni_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: com_geocompass_sdk_map_jni_HelloWorld * Method: stringFromJNI1 * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_geocompass_sdk_map_jni_HelloWorld_stringFromJNI1 (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
注意生成的.h文件 方法名命名方式java–包名–类名–方法名的形式
本地方法的实现HelloWorld.cpp代码如下:
// // Created by liuxu on 2016/12/28. // #include "HelloWorld.h" #include <string.h> extern "C" JNIEXPORT jstring JNICALL Java_com_geocompass_sdk_map_jni_HelloWorld_stringFromJNI1( JNIEnv *env, jobject obj) { // std::string hello = "Hello from C++"; return env->NewStringUTF("Hello from C++"); }
Android.mk代码
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := test LOCAL_SRC_FILES := HelloWorld.cpp include $(BUILD_SHARED_LIBRARY)
Application.mk代码
APP_ABI:= all
注意.cpp文件要把.h包含进去,然后还要遵循JNI的规范,注意传入的数据类型,native方法是没有参数的,但是JNI的实现方法带有两个参数,第一个是个JNI引用的指针,第二个要注意是jclass还是jobject,之前我执行ndk.builid的时候一直报错,就是因为.h文件和.cpp文件的数据类型不一致造成的.
然后进入项目的jni文件夹下,如图所示
之后执行ndk-build指令,前提是你配置了ndk的环境变量,配置方式我就不多做阐述了.执行之后的效果如下
之后刷新下,会发现多了两个目录,libs和obj
然后把libs目录下的所有文件夹复制到jniLIbs文件夹下就可以了
java代码的调用代码如下
在activity中 通过静态代码块加载.so文件,之后就可以把c++的字符串通过jni调用显示到一个textview上面了
static {
System.loadLibrary(“test”);
}
tv1.setText(HelloWorld.stringFromJNI1());
Android相关部分比较简单就不过多阐述了.
希望我的demo对你有所提高.
不足之处请指教!直接在评论区提出你的问题即可,我们共同研讨
相关文章推荐
- Jni中执行ndk-build,编译第三方静态库(.a)和动态库(.so)的Android.mk文件写法
- NDk环境变量的配置、AS中配置javah-jni、ndk-build
- Android.mk文件编写以及import-module的注意事项与NDK_MODULE_PATH的配置
- spring mvc需要的 配置文件(以及相关类和接口的详细解释):
- Struts配置文件详细讲解
- 访问控制列表(ACL)基本的配置以及详细讲解
- NDK开发Javah生成Jni 头文件
- NAT网络地址转换大型服务配置以及详细讲解
- 访问控制列表(ACL)基本的配置以及详细讲解
- 史上最详细的vsftpd配置文件讲解
- (转)最详细的vsftpd配置文件讲解
- WCF配置文件应用技巧详细讲解
- Struts中配置文件的详细讲解.doc
- NAT网络地址转换大型服务配置以及详细讲解 推荐
- MDT部署时出现问题!请知道的人详细给我写下 diskpart以及相关配置,MDT分区只能分主分区,不能扩展逻辑
- apache的主配置文件httpd.conf解析以及相关例题
- 史上最详细的vsftpd配置文件讲解(1)
- 访问控制列表(ACL)基本的配置以及详细讲解
- 访问控制列表(ACL)基本的配置以及详细讲解
- asp.net中在web.config配置access 相关详细讲解