概念
JNI(Java Native Interface,Java本地介面),實現了Java和其他語言的互動(主要是C/C++),如:Java程式通過JNI調用C/C++編寫的在Windows上啟動並執行DLL動態連結程式庫。
so(shared object,共用對象),Linux系統中的動態庫,類似於Windows系統中的DLL。.so有時被直接調用,有時會參與到編譯中。Android由Linux核心發展而來,因此在Android系統中也使用.so。
Android NDK(Android Native Development Kit),是Google提供的一系列的工具,簡化通過JNI將C/C++動態庫編譯為.so庫的過程。NDK整合了交叉編譯器,並提供了相應的.mk檔案隔離CPU、平台、ABI等差異,開發人員只需要簡單修改mk檔案,執行編譯指令碼就可以建立.so。
NDK與JNI的關係:
JNI是Java與其他語言互動的機制,是Java語言自身的特性,與Android無關。
Android在架構上分為Application應用程式層、Application Framework應用程式框架層、libraries類庫、Linux kernel核心。在應用程式框架層以及之上,使用Java語言進行開發;在此之下,Android自身的類庫、驅動使用C/C++編寫,再通過JNI提供介面給上層的Java調用。所以,Android架構使用了大量的JNI技術,讓應用程式層的開發人員使用Java操控C/C++。
通常的Android開發都在應用程式框架層以及之上進行,但有時也需要對底層進行實現。顯然,對底層的開發要複雜得多,NDK則是Google推出的協助開發人員通過C/C++編寫應用的開發包,包含部分Android底層中常用的C/C++的標頭檔、庫檔案、說明文檔和範例程式碼。 安裝
Windows下配置NDK的步驟:
1、下載:android-ndk-r13b-windows-x86_64.zip
2、解壓:D:\sdk\android-ndk-r13b
3、環境變數:
ANDROID_NDK:D:\sdk\android-ndk-r13b PATH:%ANDROID_NDK%
4、驗證:cmd命令輸入ndk-build若出現“Android NDK: Could not find application project directory”表示NDK正確安裝,只是沒有待編譯的工程而已。 NDK中的hello-jni
可以下載Google的NDK Samples,下面以其中的hello-jni工程為例,說明NDK中JNI的使用:
hello-jni工程目錄結構: hello-jni
jni
Android.mk(編譯設定檔) hello-jni.c(.c代碼) res src
com/example/hellojni/HelloJni.java(.java代碼) test ndk-build
JNI是獨立於NDK存在的,瞭解JNI才對NDK有更好的認識。[參考1]。
獨立使用JNI時,需要自行使用Cygwin等編譯工具將C/C++代碼編譯為動態庫;而NDKr7開始,整合了交叉編譯器和ndk-build.cmd指令碼,開發人員可以直接執行這個指令碼完成編譯工作。
運行以下命令,進行編譯:
D:\>cd sdk\android-ndk-r13b\samples\hello-jni //定位到hello-jniD:\sdk\android-ndk-r13b\samples\hello-jni>ndk-build //編譯
P.S.
當ndk-build命令提示找不到工程時,可以查看工程的Android.mk檔案中的路徑關係,定位到正確的路徑後使用ndk-build命令。或者,可以將工程路徑設定為NDK_PROJECT_PATH環境變數。
編譯成功的話,\hello-jni會多出兩個檔案夾\libs與\obj。其中:
\libs目錄下是編譯出來的不同CPU類型的.so檔案,在實際使用時根據需要選擇
\obj是編譯過程中的產生的其他檔案(如.o中間檔案,或調試檔案)
調用
在Eclipse-ADT中import進hello-jni工程,建立與\src同級的檔案夾\libs,並把編譯出來的.so放在該檔案夾下。(這裡我直接import進編譯後的工程檔案夾)
直接運行出結果:
Android.mk
ndk-build命令實際是執行了%NDK_PROJECT_PATH%/jni/Android.mk這個makefile檔案,如果未配置%NDK_PROJECT_PATH%環境變數,則需要定位到工程目錄。同時,待編譯的.c和編譯設定檔Android.mk也需要位於名為jni的目錄下。
Android.mk是NDK編譯的設定檔,其中定義了需要編譯的.c檔案、依賴的.h標頭檔、編譯出的so庫名等等資訊,是使用NDK進行編譯的關鍵。
//Android.mkLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := hello-jni //編譯出的庫名為 libhello-jni.soLOCAL_SRC_FILES := hello-jni.c //編譯源檔案include $(BUILD_SHARED_LIBRARY)
Android.mk常見配置
常見配置將在工作中積累更新… Application.mk
不同CPU編譯的.so不同,ndk-build預設編譯所有CPU的.so。可以通過Application.mk檔案指定APP_ABI指定CPU,如armeabi-v7a。
//Application.mkAPP_ABI := all //編譯所有CPU的.soAPP_ABI := armeabi-v7a //編譯armeabi-v7a的.so
Eclipse整合NDK編譯操作
前文中對NDK的操作都使用cmd命令,顯然在工作中十分不便,好在可以將這些操作都整合到Eclipse中的按鈕,一鍵完成任務。
參考:Eclipse整合JNI與AndroidNDK操作 Eclipse添加NDK攜帶的JNI代碼提示
NDK中攜帶了不同CPU的JNI操作源碼,可以添加到Eclipse中有助於在Eclipse中編寫JNI的C/C++代碼。
1、右擊工程 -> Android Tools -> Add Native Support,之後點擊快顯視窗的finish即可
2、右擊工程 -> Properties -> C/C++ General -> Paths and Symbols,選擇c,cpp語言 -> Add,使用File system選擇NDK中一個Android版本具體CPU實現的include,確定即可。
//include路徑D:\sdk\android-ndk-r13b\platforms\android-19\arch-arm\usr\include
提示效果:
參考 JNI入門——hellojni so格式檔案是什麼 Android jni開發資料–NDK環境搭建 Android架構介紹 NDK與JNI的關係 Eclipse整合JNI與AndroidNDK操作