android如何配置jni,AndroidStudio 进行 JNI / NDK 开发:初步配置及使用

说干就干!java

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

NDK:Native Development Kit(本地开发工具),一系列工具的集合,提供了一系列的工具,帮助开发者快速开发 C/C++,极大地减轻了开发人员的打包工做。android

1、安装所需工具

608da71f41d956a2a23999b184d32ede.png

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

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

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

Ps:CMake 是 AS 2.2 以后加入的一个跨平台的安装(编译)工具,能够用简单的语句来描述全部平台的安装(编译过程),简单来讲就是简化 JNI 开发的编译步骤,不用像之前那样要各类手动生成(http://www.jianshu.com/p/e7c2c63fa70e)web

2、建立支持 C/C++ 的新项目

一、新建支持 C/C++ 的新项目

只要在新建项目时勾上这里就行:编程

87655126588407d217d837020906cbfc.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。

6be4ec6a8a692e385326205c147c083a.png

二、主要项目结构

对于开发者来讲,主要关注这两个地方:app

3384edcad218b9944f05798842e0f26d.png

cpp 文件夹:用于编写 C/C++代码

CMakeLists.txt:CMake 脚本配置文件

三、编写代码安装运行

新建支持 C/C++ 的新项目时有默认的实例代码:ide

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

#include

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());

}

e677f85fc633bd6d26f8598da7b89d60.png

3、在原有旧项目中引入

一、新建 C/C++ 源码文件夹和文件

cf208d57f44fe53cfaba875204336e06.png

二、编写 CMakeLists.txt 文件

c80bdfa01eeb0a5407b9a0202b0b6bcc.png

Ps:若是嫌编写 CMakeLists.txt 文件麻烦,就直接新建一个支持 C/C++ 的新项目,拷贝修改便可(拷贝以后能够删去文件中的注释,便于阅读)svg

923fbf4a0c16752cc67d0af257de47f3.png

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

三、配置 build.gradle 文件

d97bed71113839e3394b01a868ce279e.png

android {

...

defaultConfig {

...

externalNativeBuild {

cmake {

// 默认是 “ cppFlags "" ”

// 若是要修改 Customize C++ Support 部分,可在这里加入

cppFlags "-frtti -fexceptions"

}

}

}

buildTypes {

...

}

externalNativeBuild {

cmake {

path "CMakeLists.txt"

}

}

}

dependencies {

...

}

最后是编写代码安装运行 …工具

4、几个要注意的点

一、要在哪一个类运用 JNI ,就得加载相应的动态库

// 加载动态库

static {

System.loadLibrary("demo-lib");

}

二、快速生成代码:Alt + Enter

807b7f9ef1a49201b46f47c5670c854c.png

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

0231daa9309dff4f1110639991b358e0.png

1a2dd344646ec5a31de5483956cad32e.png

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

(1)新建资源文件夹 jniLibs(貌似在 libs中也行,只要在 CMakeLists.txt中添加路径指示)

f678bd233c7a7d8aae105d8003d70338.png

(2)在 CMakeLists.txt中添加路径指示

fc8d5b5a362ed9618ac900d674c95fd2.png

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++源文件与第三方库进行链接

66691a98828ffab26c6d9e199c0d8a80.png

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

2eb7d2f7772a733141ca45e213e33239.png

Ps:原本想在 jniLibs 中引入,但编译会出错,因此只能在 CPP 资源文件夹中引入

# TODO include_directories( src/main/jniLibs/${ANDROID_ABI}/include )

# TODO 路径指向上面会编译出错,指向下面的路径就没问题

include_directories( src/main/cpp/ffmpeg/include )

2811390709cd48c885f91063.html

六、CPP 资源文件夹中的同名问题

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

cd361c5e085aa69cecd93cc98dded173.png

七、undefined reference to ‘xxx’

// 使C与C++可以正常混编

// 指示编译器按照C语言进行编译

extern "C"

{

...

}

4a62eaed0125939f9db116bf8c72c75f.png

八、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'

}

bae711fff867da72a076166f89936a6b.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值