概念
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-jni
D:\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.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni //編譯出的庫名為 libhello-jni.so
LOCAL_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.mk
APP_ABI := all //編譯所有CPU的.so
APP_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操作