本示例将引导您开发一个使用 NDK 构建的超小应用 HelloJNI。 此示例位于 NDK 安装根目录下的 samples/hello-jni/
目录内。
Android.mk
以下两行代码提供原生源文件的名称,以及要构建的共享库的名称。 构建系统添加 lib
前缀和 .so
扩展名后,构建库的全名将为 libhello-jni.so
。
LOCAL_SRC_FILES := hello-jni.c LOCAL_MODULE := hello-jni
如需了解有关 Android.mk
文件用途和使用方式的详细信息,请参阅 Android.mk。
Application.mk
这行代码的作用是告诉构建系统,针对哪些 CPU 和架构实施构建。在此示例中,构建系统为所有受支持的架构实施构建。
APP_ABI := all
如需了解有关 Application.mk
文件和使用方式的详细信息,请参阅 Application.mk。
Java 端实现
helloJNI.java
文件位于 hellojni/src/com/example/hellojni/
。它通过调用一个函数,从原生端提取一个字符串,然后将这个字符串显示在屏幕上。
源代码中包含三行 NDK 用户应特别注意的代码。本文中以调用顺序展示这三行代码,而非代码编写顺序。
应用启动时,调用此函数以加载 .so
文件。
System.loadLibrary("hello-jni");
在此方法声明中,使用 native
关键字的作用是告诉虚拟机,函数位于共享库中(即在原生端实现)。
public native String stringFromJNI();
Android 框架调用在前面步骤中加载和声明的函数,在屏幕上显示字符串。
tv.setText( stringFromJNI() );
C 端实现
hello-jni.c
文件位于 hello-jni/jni/
。其中包含的一个函数能够返回 Java 端请求的字符串。 此函数声明如下:
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz )
此声明与 Java 源代码中声明的原生函数相对应。 返回类型 jstring
是在 Java 原生接口规格中定义的数据类型。 它是指向 Java 字符串的指针,并非真正的字符串。
返回 jstring
后,接下来是根据 Java 函数名和函数名所在文件的路径返回的函数名。 函数名根据以下规则构建:
- 在名称前面加上
Java_
。 - 描述与顶级源目录相关的文件路径。
- 使用下划线代替正斜杠。
- 删掉
.java
文件扩展名。 - 在最后一个下划线后,附加函数名。
按照这些规则,此示例使用的函数名为 Java_com_example_hellojni_HelloJni_stringFromJNI
。 此名称描述 hellojni/src/com/example/hellojni/HelloJni.java
中一个名为 stringFromJNI()
的 Java 函数。
JNIEnv*
是指向虚拟机的指针,jobject
是指向从 Java 端传递的隐式 this
对象的指针。
以下代码行调用虚拟机 API (*env)
并向其传递返回值(即 Java 端函数请求的字符串)。
return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");