JNI开发环境和基础配置

简介: JNI开发环境和基础配置

JNI开发环境和基础配置


开发环境


JNI:Java Native Interface(Java 本地编程接口),一套编程规范,它提供了若干的 API 实现了 Java 和其他语言的通信(主要是 C/C++)。Java 可以通过 JNI 调用本地的 C/C++ 代码,本地的 C/C++ 代码也可以调用 java 代码。Java 通过 C/C++ 使用本地的代码的一个关键性原因在于 C/C++ 代码的高效性。


在 Android Studio 下,进行JNI的开发,需要准备以下内容:


Android Studio 2.2以上。


NDK:这套工具集允许为 Android 使用 C 和 C++ 代码。


CMake:一款外部构建工具,可与 Gradle 搭配使用来构建原生库。如果只计划使用 ndk-build,则不需要此组件。


LLDB:一种调试程序,Android Studio 使用它来调试原生代码。


20181017180656426.png


创建支持C++的项目


新建支持C++的项目


在新建项目时,勾上Include C++ support就行了:


20181017180705693.png


在向导的 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。


20181017180715348.png


支持C++的项目目录


20181017180725141.png


  • src/main/cpp下存放的我们编写供JNI调用的C++源码。


  • CMakeLists.txt文件是CMake的配置文件,通常他包含的内容如下:


# TODO 设置构建本机库文件所需的 CMake的最小版本
cmake_minimum_required(VERSION 3.4.1)
# TODO 添加自己写的 C/C++源文件
add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp )
# TODO 依赖 NDK中的库
find_library( log-lib
              log )
# TODO 将目标库与 NDK中的库进行连接
target_link_libraries( native-lib
                       ${log-lib} )


build.gradle的配置


android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                // 默认是 “ cppFlags "" ”
                // 如果要修改 Customize C++ Support 部分,可在这里加入
                cppFlags "-frtti -fexceptions"
            }
        }
        ndk {
            // abiFiliter: ABI 过滤器(application binary interface,应用二进制接口)
            // Android 支持的 CPU 架构
            abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'//, 'armeabi' 不支持了
        }
    }
    buildTypes {
        ...
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}


注意事项


1.在使用JNI前,需要加载so库


static {
    System.loadLibrary("native-lib");
}


2.快速生成C++代码:先在java中定义native方法,然后使用Alt + Enter快捷键自动生成C++方法体。


20181017180738960.jpg


3.CPP 资源文件夹下面的文件和文件夹不能重名,不然 System.loadLibrary() 时找不到,会报错:java.lang.UnsatisfiedLinkError: Native method not found.


4.在定义库的名字时,不要加前缀 lib 和后缀 .so,不然会报错:

java.lang.UnsatisfiedLinkError: Couldn’t load xxx : findLibrary【findLibrary returned null错误.


5.新建 C/C++ 源代码文件,要添加到 CMakeLists.txt 文件中。


# 增加c++源代码
add_library( # library的名称.
             native-lib
             # 标志库共享.
             SHARED
             # C++源码文件的相对路径.
             src/main/cpp/native-lib.cpp )
# 将目标库与 NDK中的库进行连接
target_link_libraries( # 目标library的名称.
                    native-lib
                    ${log-lib} )


6.引入第三方 .so文件,要添加到 CMakeLists.txt 文件中。


# 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)


7.引入第三方 .h 文件夹,也要添加到 CMakeLists.txt 文件中


# TODO include_directories( src/main/jniLibs/${ANDROID_ABI}/include )
# TODO 路径指向上面会编译出错(无法在jniLibs中引入),指向下面的路径就没问题
include_directories( src/main/cpp/ffmpeg/include )


8.C++ library编译生成的so文件,在 build/intermediates/cmake


20181017180755111.png


相关文章
|
5月前
|
Oracle Java 关系型数据库
Java入门——开发环境、入门程序(搭建Java开发环境、安装JDK 验证、JDK、编写代码、编译代码、运行代码)
Java入门——开发环境、入门程序(搭建Java开发环境、安装JDK 验证、JDK、编写代码、编译代码、运行代码)
63 3
|
Android开发 C语言
Android Studio NDK 代码 Source Insight调试 (NDK 目前开发方案 | NDK 编译 | 导入 so 库 | 项目编码转换)(一)
Android Studio NDK 代码 Source Insight调试 (NDK 目前开发方案 | NDK 编译 | 导入 so 库 | 项目编码转换)(一)
366 0
Android Studio NDK 代码 Source Insight调试 (NDK 目前开发方案 | NDK 编译 | 导入 so 库 | 项目编码转换)(一)
|
IDE 开发工具 C++
MDK5软件入门之——基础工程创建及下载和调试
MDK5软件入门之——基础工程创建及下载和调试
421 0
MDK5软件入门之——基础工程创建及下载和调试
|
缓存 Java 编译器
JNI基础简介
JNI系列入门连载,开启JNI学习之旅吧。
107 0
|
Swift iOS开发
iOS开发 - 适合工程多环境切换(swift环境),适合经常打很多不同环境包的人
iOS开发 - 适合工程多环境切换(swift环境),适合经常打很多不同环境包的人
291 0
iOS开发 - 适合工程多环境切换(swift环境),适合经常打很多不同环境包的人
|
Java C语言
IntelliJ IDEA平台下JNI编程(二)—类型映射
IntelliJ IDEA平台下JNI编程(二)—类型映射
IntelliJ IDEA平台下JNI编程(二)—类型映射
|
Java Linux 开发工具
RK3399平台开发系列讲解(系统编译篇)8.6、安卓开发环境的搭建及编译
RK3399平台开发系列讲解(系统编译篇)8.6、安卓开发环境的搭建及编译
219 0
|
XML Android开发 数据格式
|
网络协议 Linux Windows
LibModbus库开发笔记(一):libmodbus库介绍、编译和基础工程模板
LibModbus库开发笔记(一):libmodbus库介绍、编译和基础工程模板
LibModbus库开发笔记(一):libmodbus库介绍、编译和基础工程模板
|
Android开发
Android Studio NDK 代码 Source Insight调试 (NDK 目前开发方案 | NDK 编译 | 导入 so 库 | 项目编码转换)(二)
Android Studio NDK 代码 Source Insight调试 (NDK 目前开发方案 | NDK 编译 | 导入 so 库 | 项目编码转换)(二)
245 0
Android Studio NDK 代码 Source Insight调试 (NDK 目前开发方案 | NDK 编译 | 导入 so 库 | 项目编码转换)(二)