1.概述
NDK(Native Development Kit)是一组允许我们在Android应用中利用C/C++代码的工具。通过NDK我们可以构建自己的的源代码,也可以使用现有的一些库。
JNI(Java Native Interface)是java提供的一种和c/c++相互调用的机制。
NDK/JNI适用的场景:
- 提升需要大量计算的应用程序的性能,比如游戏。
- 重用C或C++的库。
获得更高的安全性。
多看NDK官方文档,需要翻墙。
2.基本配置
(1)下载
由于官网需要翻墙,所以可以到Android Studio中文站下载。下载后放到任意目录,我这里放到了
sdk的目录下。
(2)配置
打开Android Studio,大家SDK配置窗口。
选择NDK目录,如图:
点击ok,保存,到这里NDK的配置就完成了,接下来就可以开始我们的我们的NDK之旅。
3.Hello JNI
(1)创建项目,在需要调用native的类中声明native的方法。比如在MainActivity声明一个方法:
public native String sayHello();
(2)生成头文件.h。在Android Studio terminal中进入到app/src/main/java目录,使用命令javah -d ../jni 包名.MainActivity生成头文件。
生成成功后在main目录下会自动生成一个jni目录,里面有生成的头文件,如下图:
(3)在app的build.gradle中配置lib。moduleName是我们的c/c++ lib的名称,可以随便指定,abiFilters确定我们要生成哪些平台的lib,使用过第三方SDK的同学一定很熟悉,因为经常需要我们把第三方的lib拷贝到我们的libs对应目录下。这步和eclipse中配置.mk文件类似。
defaultConfig {
applicationId "com.example.tziyao.ndkdemo"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
ndk{
moduleName "testLib"
abiFilters "armeabi","armeabi-v7a","x86"
}
}
(4)在需要使用native的类中导入c/c++ lib。这里我需要在MainActivity中导入。名字需要和在build.gradle中声明的一样。
static {
System.loadLibrary("testLib");
}
(5)在c中实现sayHello方法。首先需要在jni目录下创建一个.c或.cpp文件,文件名随意,我这里就叫main。
(6)在main.cpp中实现sayHello方法,如果是.c写法略有不同。
#include "com_example_tziyao_ndkdemo_MainActivity.h"
/*
* Class: com_example_tziyao_ndkdemo_MainActivity
* Method: sayHello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_tziyao_ndkdemo_MainActivity_sayHello
(JNIEnv * env, jobject obj){
return env -> NewStringUTF("hello jni");
}
(7)编译c/c++代码,在build中选择make project。
编译完成后会在app/build/intermediates/ndk/debug/lib下生成对应相应平台的so库。如图:
(8)在MainActvity中调用native的方法,当点击按钮时,调用sayHello,Toast返回结果。
public void click(View v) {
Toast.makeText(MainActivity.this, sayHello(), Toast.LENGTH_SHORT).show();
}
(9)安装应用查看结果,至此NDK/JNI开发流程结束。大家可以开始尽情的使用c/c++来实现与Android的交互啦。
4.可能出现的问题
(1)abiFilters中输入错误,导致生成so库失败。如现有如下配置:
ndk{
moduleName "testLib"
abiFilters "armeabi","armeabi-v7a","x86","x"
}
在编译时会报错,所以我们应该要注意千万不要写错,或者加入不存在的平台。
(2)grade.properties未添加android.useDeprecatedNdk=true导致编译不通过。这句意思是允许使用过时的NDK,不配置可能因为NDK的版本导致编译不过。
本文源码NDKDemo。