AndroidStudio 进行 JNI / NDK 开发:初步配置及使用
2017-09-08 12:03
791 查看
说干就干!
简书:http://www.jianshu.com/p/b7b21e8be193
JNI:Java Native Interface(Java 本地编程接口),一套编程规范,它提供了若干的 API 实现了 Java 和其他语言的通信(主要是 C/C++)。Java 可以通过 JNI 调用本地的 C/C++ 代码,本地的 C/C++ 代码也可以调用 java 代码。Java 通过 C/C++ 使用本地的代码的一个关键性原因在于 C/C++ 代码的高效性。
NDK:Native Development Kit(本地开发工具),一系列工具的集合,提供了一系列的工具,帮助开发者快速开发 C/C++,极大地减轻了开发人员的打包工作。
NDK:这套工具集允许为 Android 使用 C 和 C++ 代码。
CMake:一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果只计划使用 ndk-build,则不需要此组件。
LLDB:一种调试程序,Android Studio 使用它来调试原生代码。
Ps:CMake 是 AS 2.2 之后加入的一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程),简单来说就是简化 JNI 开发的编译步骤,不用像以前那样要各种手动生成(http://www.jianshu.com/p/e7c2c63fa70e)
在向导的 Customize C++ Support 部分,有下列自定义项目可供选择:
C++ Standard:使用下拉列表选择使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
Exceptions Support:如果希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle文件的 cppFlags中,Gradle 会将其传递到 CMake。
Runtime Type Information Support:如果希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle文件的 cppFlags中,Gradle 会将其传递到 CMake。
cpp 文件夹:用于编写 C/C++代码
CMakeLists.txt:CMake 脚本配置文件
Ps:如果嫌编写 CMakeLists.txt 文件麻烦,就直接新建一个支持 C/C++ 的新项目,拷贝修改即可(拷贝之后可以删去文件中的注释,便于阅读)
最后是编写代码安装运行 …
(2)在 CMakeLists.txt中添加路径指示
Ps:这里要注意两个地方
① 在定义库的名字时,不要加前缀 lib 和后缀 .so,不然会报错:java.lang.UnsatisfiedLinkError: Couldn’t load xxx : findLibrary【findLibrary returned null错误: http://blog.csdn.net/treasure3334/article/details/17170927】
② ABI 文件夹上面不要再分层,直接用“jniLibs/${ANDROID_ABI}/”的格式,不然也会报错
(3)将自己编写的 C/C++源文件与第三方库进行连接
Ps:本来想在 jniLibs 中引入,但编译会出错,所以只能在 CPP 资源文件夹中引入
参考文章:
http://www.jianshu.com/p/c1a0aed93675
http://www.jianshu.com/p/5f29fd671750
http://blog.csdn.net/cuiyufeng2/article/details/64125594
简书:http://www.jianshu.com/p/b7b21e8be193
JNI:Java Native Interface(Java 本地编程接口),一套编程规范,它提供了若干的 API 实现了 Java 和其他语言的通信(主要是 C/C++)。Java 可以通过 JNI 调用本地的 C/C++ 代码,本地的 C/C++ 代码也可以调用 java 代码。Java 通过 C/C++ 使用本地的代码的一个关键性原因在于 C/C++ 代码的高效性。
NDK:Native Development Kit(本地开发工具),一系列工具的集合,提供了一系列的工具,帮助开发者快速开发 C/C++,极大地减轻了开发人员的打包工作。
一、安装所需工具
NDK:这套工具集允许为 Android 使用 C 和 C++ 代码。
CMake:一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果只计划使用 ndk-build,则不需要此组件。
LLDB:一种调试程序,Android Studio 使用它来调试原生代码。
Ps:CMake 是 AS 2.2 之后加入的一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程),简单来说就是简化 JNI 开发的编译步骤,不用像以前那样要各种手动生成(http://www.jianshu.com/p/e7c2c63fa70e)
二、创建支持 C/C++ 的新项目
1、新建支持 C/C++ 的新项目
只要在新建项目时勾上这里就行:在向导的 Customize C++ Support 部分,有下列自定义项目可供选择:
C++ Standard:使用下拉列表选择使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
Exceptions Support:如果希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle文件的 cppFlags中,Gradle 会将其传递到 CMake。
Runtime Type Information Support:如果希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle文件的 cppFlags中,Gradle 会将其传递到 CMake。
2、主要项目结构
对于开发者来说,主要关注这两个地方:cpp 文件夹:用于编写 C/C++代码
CMakeLists.txt:CMake 脚本配置文件
3、编写代码安装运行
新建支持 C/C++ 的新项目时有默认的实例代码:public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. // 加载本地库 static { System.loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method TextView tv = (TextView) findViewById(R.id.sample_text); tv.setText(stringFromJNI()); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ // 本地方法 public native String stringFromJNI(); }
#include <jni.h> #include <string> extern "C" JNIEXPORT jstring JNICALL Java_com_xq_jnidemo01_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); }
三、在原有旧项目中引入
1、新建 C/C++ 源码文件夹和文件
2、编写 CMakeLists.txt 文件
Ps:如果嫌编写 CMakeLists.txt 文件麻烦,就直接新建一个支持 C/C++ 的新项目,拷贝修改即可(拷贝之后可以删去文件中的注释,便于阅读)
# TODO 设置构建本机库文件所需的 CMake的最小版本 cmake_minimum_required(VERSION 3.4.1) # TODO 添加自己写的 C/C++源文件 add_library( demo-lib SHARED src/main/cpp/demo-lib.cpp ) # TODO 依赖 NDK中的库 find_library( log-lib log ) # TODO 将目标库与 NDK中的库进行连接 target_link_libraries( demo-lib ${log-lib} )
3、配置 build.gradle 文件
android { ... defaultConfig { ... externalNativeBuild { cmake { // 默认是 “ cppFlags "" ” // 如果要修改 Customize C++ Support 部分,可在这里加入 cppFlags "-frtti -fexceptions" } } } buildTypes { ... } externalNativeBuild { cmake { path "CMakeLists.txt" } } } dependencies { ... }
最后是编写代码安装运行 …
四、几个要注意的点
1、要在哪个类运用 JNI ,就得加载相应的动态库
// 加载动态库 static { System.loadLibrary("demo-lib"); }
2、快速生成代码:Alt + Enter
3、新建 C/C++ 源代码文件,要添加到 CMakeLists.txt 文件中
4、引入第三方 .so文件,要添加到 CMakeLists.txt 文件中
(1)新建资源文件夹 jniLibs(貌似在 libs中也行,只要在 CMakeLists.txt中添加路径指示)(2)在 CMakeLists.txt中添加路径指示
Ps:这里要注意两个地方
① 在定义库的名字时,不要加前缀 lib 和后缀 .so,不然会报错:java.lang.UnsatisfiedLinkError: Couldn’t load xxx : findLibrary【findLibrary returned null错误: http://blog.csdn.net/treasure3334/article/details/17170927】
② ABI 文件夹上面不要再分层,直接用“jniLibs/${ANDROID_ABI}/”的格式,不然也会报错
# TODO 添加第三方库 # TODO add_library(libavcodec-57 # TODO 原先生成的.so文件在编译后会自动添加上前缀lib和后缀.so, # TODO 在定义库的名字时,不要加前缀lib和后缀 .so, # TODO 不然会报错:java.lang.UnsatisfiedLinkError: Couldn't load xxx : findLibrary returned null add_library(avcodec-57 # TODO STATIC表示静态的.a的库,SHARED表示.so的库 SHARED IMPORTED) set_target_properties(avcodec-57 PROPERTIES IMPORTED_LOCATION # TODO ${CMAKE_SOURCE_DIR}:表示 CMakeLists.txt的当前文件夹路径 # TODO ${ANDROID_ABI}:编译时会自动根据 CPU架构去选择相应的库 # TODO ABI文件夹上面不要再分层,直接就 jniLibs/${ANDROID_ABI}/ # TODO ${CMAKE_SOURCE_DIR}/src/main/jniLibs/ffmpeg/${ANDROID_ABI}/libavcodec-57.so ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libavcodec-57.so) add_library(avdevice-57 SHARED IMPORTED) set_target_properties(avdevice-57 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libavdevice-57.so)
(3)将自己编写的 C/C++源文件与第三方库进行连接
5、引入第三方 .h 文件夹,要添加到 CMakeLists.txt 文件中
Ps:本来想在 jniLibs 中引入,但编译会出错,所以只能在 CPP 资源文件夹中引入
# TODO include_directories( src/main/jniLibs/${ANDROID_ABI}/include ) # TODO 路径指向上面会编译出错,指向下面的路径就没问题 include_directories( src/main/cpp/ffmpeg/include )
6、CPP 资源文件夹中的同名问题
CPP 资源文件夹下面的文件和文件夹不能重名,不然 System.loadLibrary() 时找不到,会报错:java.lang.UnsatisfiedLinkError: Native method not found7、undefined reference to ‘xxx’
// 使C与C++能够正常混编 // 指示编译器按照C语言进行编译 extern "C" { ... }
8、error: ‘xxx.so’,needed by ‘xxxx.so’,missing and no known rule to make it
不同厂商的 Android 手机支持的 CPU 架构不同【Android-ABIFilter:http://blog.csdn.net/qq_32452623/article/details/71076023】,一般引入的第三方 .so 文件有多个 ABI 的类型,Cmake会默认对下面 7 个ABI分别调试,但如果只引入一部分,那么要在 build.gradle 中设置 ndk 的 abiFilters 属性:externalNativeBuild { cmake { // 默认是 “ cppFlags "" ” // 如果要修改 Customize C++ Support 部分,可在这里加入 cppFlags "-frtti -fexceptions" } } ndk { // abiFiliter: ABI 过滤器(application binary interface,应用二进制接口) // Android 支持的 CPU 架构 abiFilters 'armeabi'//,'armeabi-v7a','arm64-v8a','x86','x86_64','mips','mips64' }
参考文章:
http://www.jianshu.com/p/c1a0aed93675
http://www.jianshu.com/p/5f29fd671750
http://blog.csdn.net/cuiyufeng2/article/details/64125594
相关文章推荐
- JNI和NDK编程-使用AndroidStudio进行NDK开发
- AndroidStudio中NDK开发环境配置和jni的简单使用(HelloWord)
- 使用AndroidStudio进行NDK开发简单配置
- AndroidStudio上使用NDK(Jni)的配置
- AS2.2使用CMake方式进行JNI/NDK开发
- AndroidStudio如何配置NDK/JNI开发环境
- Mac电脑AndroidStudio2.2使用NDK开发JNI
- AndroidStudio如何配置NDK/JNI开发环境
- android studio 配置NDK环境进行JNI开发
- AS2.2使用CMake方式进行JNI/NDK开发
- AndroidStudio如何配置NDK/JNI开发环境
- AndroidStudio进行JNI开发完整流程之环境配置
- Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法 边缘检测 范例代码
- AS2.2使用CMake方式进行JNI/NDK开发
- AndroidStudio如何配置NDK/JNI开发环境
- [转]Android通过NDK调用JNI,使用opencv做本地c++代码开发配置方法
- Android Studio使用JNI和NDK进行开发
- Eclipse NDK 配置进行jni开发
- AS2.2使用CMake方式进行JNI/NDK开发
- AndroidStudio2.2 Preview3中NDK开发之CMake和传统 JNI在目录结构和配置文件上的区别