原理:
Android NDK 是一系列工具,允许 Android 应用程序开发者嵌入从 C、C++源代码文件编译来的本地机器代码到各自的应用软件包中。NDK 集成了交叉编译器,可以把你用 C、C++书写的代码,编译为.so 格式的文件。在 Android 程序当中可以用 Java 语言(JNI)调用这些代码。并可以自动地将 so 和 Java 应用一起打包生成 apk,极大地减轻了开发人员的打包工作。
NDK 的功能
Android 虚拟机允许应用程序源代码通过 JNI 调用本地代码实现的方法。在 Java 代码中声明本地方法必须有"native"标识符,native 修饰的方法,在 Java 代码中只作为声明存在。例如: native byte[] loadFile(String filePath);必须提供一个包含这些方法实现的本地共享库,该共享库将会打包到你的应用程序的.apk 文件中。这个共享库是根据标准的 Unix 的规定来命名,像 lib<something>.so,并且应包含标准 JNI 调用点。例如:libFileLoader.so
在调用本地方法前,必须首先装载含有该方法的本地库. 如 HelloWorld.java 中所示,置于 static 块中,在 Java VM 初始化一个类时,首先执行这部分代码,这可保证调用本地方法前,装载了本地库。例如,在应用程序的开始加载它,只需将以下内容添加到应用程序的源代码中:
static {
System.loadLibrary("FileLoader"); 注意:在这里,您不需要使用前缀'lib'和后缀'.so'。
}
Java 通过 JNI 机制和 C/C++沟通的具体步骤:
- 编写包含 native 本地方法的 Java 类。
- 通过 javah 工具生成 C/C++语言的头文件。
- 使用 C/C++语言实现的头语言。
- 使用交叉编译工具对 C/C++本地代码进行编译,最后通过链接生成*.so 可执行的 C/C++库。
- 实际执行 Java 代码去和本地 C/C++代码相互勾通。
源码分析:
HelloJniActivity.java
public void onClick(View v) {
String result = StringFromJNI(); //调用 jni 函数
mTextView.setText(result);
}
});
}
/* 添加函数声明,告诉编译和链接器该方法在本地代码中实现 */
public native String StringFromJNI();
/* 加载 JNI 代码编译生成的共享库 */
static {
System.loadLibrary("hello -jni");
}
}
main.xml
hello-jni.c
#include <jni.h>
/* This is a trivial JNI example where we use a native method
* to return a new VM String. See the corresponding Java source
* file located at:
*/
jstring
Java_com_ndk_hellojni_HelloJniActivity_StringFromJNI( JNIEnv* env,jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
Android.mk
LOCAL_PATH := $(call my -dir) #当前路径include $(CLEAR_VARS) #清除变量
LOCAL_MODULE := hello -jni
LOCAL_SRC_FILES := hello-jni.c #源文件路径
include $(BUILD_SHARED_LIBRARY) #编译生成一个名为 lib.*.so 的共享库
Android.mk 是 JNI 代码的 Makefile 文件。 hello-jni 为生成共享库名。编译成功后会 libs/armeabi/目录下生成 libled-jni.so 库文件。