NDK和JNI基础
NDK
Native Development Kit是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C/C++的动态库,并能自动将so和java一起打包成apk。
JNI
Java Native Interface标准是java平台的一部分,JNI是Java语言提供的Java和C/C++相互沟通的机制,Java可以通过JNI调用C/C++代码,C/C++的代码也可以调用java代码。
NDK可以为我们生成了C/C++的动态链接库,JNI是java和C/C++沟通的接口,两者与Android没有半毛钱关系,只因为Android是java程序语言开发,然后通过JNI又能与C/C++沟通,所以我们可以使用NDK+JNI来实现Java + C的开发方式
JNI是一种协议,NDK是Android开发JNI的工具包。
JNI:java native interface : java本地开发接口
通过jni就可以让java与C/C++代码实现互调。
为什么使用JNI?
-
native coder执行高效:大量的运算(极品飞车),万能解码(ffmpeg),Opengl(3D渲染)。 - 通过
jni技术,可以拓展Android手机的功能-WiFi热点 - 代码的复用:
ffmpeg,opencv(人脸识别库),7-zip - 使用场景:考虑特殊情况(效率/操作硬件)
NDK
Native Develop Kits:本地开发工具包
Android提供的用来做JNI开发的工具包
为什么使用NDK?
- 提高
JNI开发的效率 - 生成代码
- 代码提示
- 多平台交叉编译
环境配置可以参考这个文章https://blog.csdn.net/yao_94/article/details/79151804
1. Android NDK开发
先介绍一下我的软件版本
- JDK 1.8
- Android Studio 3.1
在使用NDK开发的时候,先要把几样工具下好。
- NDK
- CMake
- LLDB
下图中箭头所指的三个就是我们需要下载的。

在这个图中我们可以查看
NDK下载的位置。我的下载位置是
D:\Android\Sdk\ndk-bundle
1. 创建项目
这里创建的是JNI_NDK
2. 创建jni文件夹
右键 ---> src ---> new ---> Folder ---> JNI Folder

jni文件夹的路径

可以看到jni文件夹与java文件夹是同一级的
3.创建JNI类
public class JNITest {
static {
System.loadLibrary("JniLib");
}
public native String getString();
}
4. 生成头文件
点击 File ---> Settings ---> Tools ---> External Toosl
如下图所示:

如果没有配置过将不会显示,我的是配置过的,所以显示有两个。
点击加号,出现下面的界面


配置好这两个以后,就可以生成.h头文件了。按照下图的操作,

完成后,就可以在JNI目录下看到生成的.h头文件了

4.创建JniLib.cpp,Android.mk,Application.mk文件

复制.h文件内容到JniLib.cpp并修改,如下: 此文件为JNI内容文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <com_study_wumeng_jni_ndk_JNITest.h>
/* Header for class com_study_wumeng_jni_ndk_JNITest */
/*
* Class: com_study_wumeng_jni_ndk_JNITest
* Method: getString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_study_wumeng_jni_1ndk_JNITest_getString
(JNIEnv * env, jobject jobject){
return (*env).NewStringUTF("成功调用JNI内容");
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JniLib
LOCAL_SRC_FILES =: JniLib.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_MODULES := JniLib
APP_ABI := all
5. 修改app下的build.gradle文件,如下图:

ndk{
moduleName "JniLib"
// abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定的三种abi体系下的so库
}
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir "src/main/libs"
}
6. 在项目下的gradle.properties中加上下面这条语句:
#兼容老的NDK
android.useDeprecatedNdk=true
7. 执行ndk-build:
前面我们已经配置过了,选中JNI类的右键---> New ---> External Tools ---> ndk-build,如下图所示:

8. 调用so文件
public class MainActivity extends AppCompatActivity {
private Button btn;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.button);
textView = findViewById(R.id.text);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText("结果: " + new JNITest().getString() );
}
});
}
}