Java Native Interface(JNI)即java本地接口,它允許Java代碼和其他編程語言(主要是C/C++)的代碼進行交互。native實現(xiàn)的代碼的效率可以比java高,有一些對運行效率要求比較高的場合需要用到Jni。有時候需要調(diào)用C/C++編寫的代碼,也需要用到Jni。所以Jni開發(fā)在android開發(fā)里面有特殊的作用。本文就從創(chuàng)建一個簡單的JniDemo講起。
本文的源碼請前往Github https://github.com/dragonjiang/HelloJni.git
環(huán)境配置
下載ndk,墻內(nèi)官網(wǎng)訪問不了,可以度娘,現(xiàn)在最新的是
android-ndk-r10e-windows-x86_64.exe解壓,一般是解壓到與SDK同級的目錄下:

- 設(shè)置Windows環(huán)境變量

然后在Path里面添加%Android_NDK_HOME%
新建工程
1. 打開android studio,新建工程

選擇新建一個Empty Actity

2. 新建NativeHelper類,聲明一個native方法:

聲明代碼如下:
public class NativeHelper {
public native String getStringFromJni();
}
3. 執(zhí)行Build->Make Project,目的是生成class文件###

打開工程目錄HelloJni\app\build\intermediates\classes\debug\com\dj\jni\hellojni\NativeHelper.class 可以看到生成了NativeHelper.class文件:

4. 根據(jù)class文件生成對應(yīng)的c語言頭文件
打開android stuido 的 terminal,執(zhí)行命令cd app/src/main進入mian目錄,目的是在mian目錄下生成jni文件夾。

然后用javah生成c頭文件:
javah -d jni -classpath D:\ANDROID_DEVELOP_ENVIRNMONT\SDK\platforms\android-21\android.jar;..\..\build\intermediates\classes\debug com.dj.jni.hellojn
i.NativeHelper
命令格式是:
javah -d (jni文件夾名) -classpath (sdk路徑);(class路徑) (class完整的文件名,包括包名)

然后再看main目錄下會多出jni文件夾,里面已經(jīng)自動生成了一個頭文件com_dj_jni_hellojni_NativeHelper.h
文件內(nèi)容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_dj_jni_hellojni_NativeHelper */
#ifndef _Included_com_dj_jni_hellojni_NativeHelper
#define _Included_com_dj_jni_hellojni_NativeHelper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_dj_jni_hellojni_NativeHelper
* Method: getStringFromJni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_dj_jni_hellojni_NativeHelper_getStringFromJni
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
5. 新建.c文件
在jni文件下新建.c文件,當(dāng)然新建.cpp文件也是可以的啦,就看大家習(xí)慣使用c還是c++

添加內(nèi)容如下:
#include <jni.h>
/*
* Class: com_dj_jni_hellojni_NativeHelper
* Method: getStringFromJni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_dj_jni_hellojni_NativeHelper_getStringFromJni
(JNIEnv *env, jobject obj){
return (*env)->NewStringUTF(env,"Hello from JNI !");
}
6. 配置ndk
執(zhí)行Build->Clean Project, 再執(zhí)行Build->Make Project,期間可能會提示錯誤:

我們根據(jù)提示在gradle.properties文件中添加以下內(nèi)容:
android.useDeprecatedNdk=true

打開File->Project Structure,選擇ndk的路徑

在app目錄下的build.gradle中設(shè)置要生成的so庫文件名,在defaultConfig這項里面添加:
ndk {
moduleName "HelloJni" //編譯后會生成HelloJni.so
}

在NativeHelper類中添加對so庫的加載:
static {
System.loadLibrary("HelloJni");
}
android動態(tài)加載庫文件有兩個方法,System.load 和 System.loadLibrary
System.load 參數(shù)必須為庫文件的絕對路徑
System.loadLibrary 參數(shù)為庫文件名,不包含庫文件的擴展名。
注意加載的庫名字要與build.gradle中配置的庫名字一致。
NativeHelper類的完整代碼如下:

7. 編譯jni, 調(diào)用native方法
再執(zhí)行Build->Clean Project,
執(zhí)行Build->Make Project。
打開工程目錄HelloJni\app\build\intermediates\ndk\debug\lib 可以看到生成了各個平臺的so文件:

注意: 每次修改jni文件夾下的.c文件或者.h文件都要重新執(zhí)行Build->Make Project,重新生成so文件。
打開MainActivity,調(diào)用native方法:

運行結(jié)果:
