为什么要使用JNI
JavaNative Interface (JNI)标准是Java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C、C++ 和汇编语言)编写的应用程序和库进行交互操作。
我们先来看Android源码的使用,Android框架里所提供的MediaPlayer.java类,含指令:
public class MediaPlayer{
static {
System.loadLibrary("media_jni");
}
}
这要求VM去载入Android的/system/lib/libmedia_jni.so档案。载入.so之后,Java类与.so档案就汇合起来,一起执行了。
NDk的介绍如下:
NDK是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。它集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。它可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。
接下来我们就尝试开发我们第一个简单的NDK工程
1.NDK环境配置
- Android Stdio 2.3.2
- Android NDK 14
- Java version 1.7
- Mac os 10.12.3
Android Studio—>Appearance&Behavior–>System Setting –>Android SDK–>SDK Tools
此时在local.properties文件中可以看到NDK的路径:
ndk.dir=/Users/beifeng/Library/Android/sdk/ndk-bundle
sdk.dir=/Users/beifeng/Library/Android/sdk
2.环境配置好后我们新建一个项目,然后新建一个类JniHello
public class JniHello {
//使用静态代码块来加载相应的so文件
static {
System.loadLibrary("hello");
}
//声明一个native方法
public native String sayHelloWorld();
}
接下来我们使用build中的make Project构建项目,构建项目成功后。注意Test\app\build\intermediates\classes\debug 目录。
3.构建项目成功后,根据生成的class文件,利用javah生成对应的 .h头文件。
然后接下来的步骤就是根据生成的class文件,利用javah生成对应的 .h头文件。在AS的Terminal中:
cd命令进入到该/Users/beifeng/Downloads/GitHub/MyNDK/app/src/main/java
然后执行命令:javah -d jni com.beifeng.myndk.JniHello
-d jni
表示将在当前目录下生成一个header文件夹,产生的头文件就在这里面了。
之后我们就可以在项目目录中看到编译完成的jni文件以及里面的.h的头文件。必须要将jni文件移至main文件目录下,与java文件同级目录(不然在运行时无法生成.so文件)
4.在jni文件下新建一个c文件(本文中定义为JniHello.c),并且在该c文件中实现上图右侧中所标记的函数,相应代码如下:
#include "com_beifeng_myndk_JniHello.h"
JNIEXPORT jstring JNICALL Java_com_beifeng_myndk_JniHello_sayHelloWorld
(JNIEnv *evn, jobject obj){
// 要执行的代码
// 输出Helloworld
char *hello= "hello world jni";
(*evn)->NewStringUTF(evn,hello);
}
5.配置Android studio gradle中关于ndk的支持
- 在gradle.properties文件中添加如下一行代码:android.useDeprecatedNdk=true
- app的build.gradle文件,在defaultConfig节点里添加如下:
ndk {
//需要生成的so文件名称
moduleName "hello"
//适配各种架构的cpu
abiFilters "armeabi", "armeabi-v7a", "x86"
}
6 .以上设置完成之后,点击Build的Rebuild Project进行重新构造,就可以生成我们自己的的.so文件了。
7.最后在我们的Activity中进行调用
public class MainActivity extends AppCompatActivity {
private TextView text_tv;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//调用native方法的类
JniHello jniHello = new JniHello();
text_tv = (TextView) findViewById(R.id.textview);
text_tv.setText(jniHello.sayHelloWorld());
Toast.makeText(this, jniHello.sayHelloWorld(), Toast.LENGTH_SHORT).show();
}
}
至此我们完成了最简单的NDK工程开发。