Android
的一个工具开发包,NDK是属于 Android
的,与java
并无直接关系作用:
C
、 C++
的动态库,并自动将.so
和应用一起打包成 APK
NDK
在 Android
中 使用 JNI
与本地代码(如C、C++)交互jni是实现最终目的 , 而 ndk 是实现 jni的功能调用。
是java native interface , java本地接口。如果java代码需要调用底层的c/c++代码,就需要通过jni来实现。android的底层是linux,linux之上是c/c++代码,而我们app是java代码。有些需要高效率的事情,比如音视频编解码,比如3d绘图等就需要用c/c++来实现了。
JNI实现步骤
以下操作都是在AndroidStudio中进行。
https://blog.csdn.net/qq_38261174/article/details/83210458 这里讲了如何下载及配置ndk。
然后在androidstudio中配置ndk:
我建的工程名字是 MyJniStudy
包名是 com.liuyan.myjnistudy
上面图片中没有打钩的,别慌,可以在 build.gralde中配置:
apply plugin: 'com.android.application'
android {
...
defaultConfig {
...
}
buildTypes {
...
}
//这里配置
sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jni/'] } }
}
dependencies {
...
}
我的包名是 my
我的java文件名字是 NdkJniTest
方法名字是 mytest
package my;
public class NdkJniTest {
//要先加载so库,才能调用native方法
//so库的名字(NdkJniSoName)
//下面步骤会在 build.gralde中配置so库的名字是这个
static {
System.loadLibrary("NdkJniSoName");
}
public native String mytest();
}
方法名字是红色的,不要管,接下来可能方法一直是红色的,不要管,按照步骤来就行了。
执行命令 : javac NdkJniTest.java (编译 .java 产生 .class)
这里我产生了一个错误:
D:\androidstudio-xiangmu\MyJniStudy\app\src\main\java\my>javac NdkJniTest.java
NdkJniTest.java:7: 错误: 编码GBK的不可映射字符
//涓嬮潰姝ラ浼氬湪 build.gralde涓厤缃畇o搴撶殑鍚嶅瓧鏄繖涓?
^
1 个错误
我把注释全删 ,然后重新执行一次命令就好了。
这时会在my包下面多出一个文件
执行命令 javah -jni my.NdkJniTest ( .class产生 .h文件)
这时会在java目录下产生一个 my_NdkJniTest.h 文件。
.h 文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class my_NdkJniTest */
#ifndef _Included_my_NdkJniTest
#define _Included_my_NdkJniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: my_NdkJniTest
* Method: mytest
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_my_NdkJniTest_mytest
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
名字自己取。
我的 c文件名字是 jnitest.c
创建好 .c文件之后,编写这个 .c文件。
.c文件 要引入之前的 .h头文件,并实现头文件其中的方法。
我的 .c文件其中的代码:
#include "my_NdkJniTest.h"
JNIEXPORT jstring JNICALL Java_my_NdkJniTest_mytest
(JNIEnv *env, jobject obj) {
return (*env)->NewStringUTF(env, "This is my Jni test!!!");
}
接下来
配置 gradle.properties 文件,在末尾加入:
android.useDeprecatedNdk=true
配置ndk 修改app模块的 build.gradle文件,如下:
apply plugin: 'com.android.application'
android {
...
defaultConfig {
...
ndk {
moduleName "NdkJniSoName" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。
}
}
buildTypes {
...
}
sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jni/'] } }
}
dependencies {
...
}
sync project
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NdkJniTest ndkJniTest = new NdkJniTest();
String s = ndkJniTest.mytest(); //native方法
Log.i("TAG",s);
}
}
我们产生的.so库在哪儿呢?自动生成的哦!!!
想要了解更多的,可以自己研究下 Android.mk文件,其实就是我们在 build.gradle 中配置的 ndk。
按照上面的流程,相信你已经成功了!
是不是还不过瘾?好,我们接着来
我们在 NdkJniTest.java 中,再加入一个 native 方法。
package my;
public class NdkJniTest {
static {
System.loadLibrary("NdkJniSoName");
}
public native String mytest();
//新加入的方法
public native int AddAB(int a , int b);
}
这个native方法将要 实现两数之和 ,并将这个和返回。
重新 生成 .class 文件,重新生成 .h文件。
如果你不想要重新生成,你可以自己直接修改 .h文件,在其中加入:
JNIEXPORT jint JNICALL Java_my_NdkJniTest_AddAB
(JNIEnv *, jobject, jint, jint);
如果你的包名和我的不一样,自己根据情况修改上面的代码内容。
所以现在的.h文件所有内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class my_NdkJniTest */
#ifndef _Included_my_NdkJniTest
#define _Included_my_NdkJniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: my_NdkJniTest
* Method: mytest
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_my_NdkJniTest_mytest
(JNIEnv *, jobject);
JNIEXPORT jint JNICALL Java_my_NdkJniTest_AddAB
(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
编写 .c文件,一定要引入 .h头文件。
之前我们实现了头文件的方法,新加入的方法还没有实现,所以我们要去实现新加入的方法。
所以.c文件所有内容如下:
#include "my_NdkJniTest.h"
JNIEXPORT jstring JNICALL Java_my_NdkJniTest_mytest
(JNIEnv *env, jobject obj) {
return (*env)->NewStringUTF(env, "This is my Jni test!!!");
}
//实现新的方法
JNIEXPORT jint JNICALL Java_my_NdkJniTest_AddAB
(JNIEnv *env, jobject obj, jint a, jint b) {
return (a+b);
}
sync project
开始使用新方法,并查看结果:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NdkJniTest ndkJniTest = new NdkJniTest();
String s = ndkJniTest.mytest(); //native方法
Log.i("TAG",s);
//测试新方法
int result = ndkJniTest.AddAB(2018,10);
Log.i("TAG",""+result);
}
}
到此为止了!!!