Android NDK是一套允许开发人员将本地代码嵌入到Android应用程序的开发包,众所周知,Android应用程序运行在Dalvik虚拟机上,而NDK允许开发人员将Android应用程序中的部分功能用C/C++语言来实现,并将这部分C/C++代码编译成可直接运行在Android平台上的本地代码,这些本地代码以动态链接库(.so文件)的形式存在。NDK的这个特性既有利于代码的重用,也可以在某种程度上提高程序的运行效率。
NDK提供一下内容:
1、提供了一套工具集,这套工具集可以将C/C++源代码生成本地代码;
2、用于定义NDK接口的C头文件(*.h)和实现这些接口的库文件;
3、一套编译系统,可以通过非常少的配置生成目标文件;
4、从Android2.3开始,支持本地Activity(Native Activity)。
最新版本Android NDK 支持ARMv5TE机器指令,并且提供大量的C语言库,包括libm(Math库)、OpenGL ES、JNI接口以及其他的库。
虽然在程序中使用NDK可以达到提高运行速度,但使用NDK也会带来很多副作用,例如:使用NDK并不是总会提高应用程序的性能,但却增加程序的复杂度,而且使用NDK必须自己控制内存的分配和释放,这样将无法利用Dalvik虚拟机来管理内存,也会给应用程序带来很大的风险。因此,建议应根据具体的情况适度使用NDK。例如,需要大幅度提高性能或者需要保密(java生成的目标文件很容易被反编译)的情况下就可以使用NDK来生成相应的本地代码。
package mobile.android.jni;
......
public class HelloWorldJni extends Activity
{
public void oncreat(Bundle savedInstanceState){
......stringFromJNI();
}
public native Strign stringFromJNI();
static{
System.loadLibrary("hello-jni");
}
}
JNI部分:
#include <jni.h>
jstring Java_mobile_android_jni_HelloWorldJni_stringFromJNI(JNIEnv* env,jobject thiz)
{
return (*env)->NewStringUTF(env , "hello world");
}
其中“Java_mobile_android_jni_HelloWorldJni_stringFromJNI”为NDK函数名,函数名与其参数的命名规则如下。
NDK函数的返回值类型和参数类型都是在JNI的头文件中定义的类型(如就string、jobject等)。这些类型与java中的数据类型对应,例如,就string对应java中的String,jobject对应java中的Object。在定义被java调用的JNI函数是必须使用这些数据类型,否则java无法成功调用这些函数。
从HelloWorldJni类的代码可以看出,调用的方法是stringFromJNI。而NDK源码中的方法却是Java_mobile_android_jni_HelloWorldJni_stringFromJNI。实际上,这里涉及到一个命名规则。JNI方法名的命名规则是Java_xxx_MethodName。从这个命名规则可以看出,JNI方法名分三段,中间是下划线“_”分割。第一段是“Java”,这是固定的,最后一段就是在Java中调用实际方法名,而中间一段“xxx”实际上就是调用JNI方法的类的全名(package + classname),只是将中间的点“.”换成了下划线“_”,所以最终是JNI方法名是Java_mobile_android_jni_HelloWorldJni_stringFromJNI。
上面两个参数:env 和 thiz 。这两个参数必须包含在JNI函数中,而且必须是头两个参数。其中env表示JNI的调用环境,thiz标识定义native方法的java类的对象本身。