3.NDK
配置
這個版本NDK的配置比較簡單,前面的老版本還須要設置許多環境變量,這個版本不須要設置,直接解壓縮就能夠了。主目錄android-ndk-r8下有一個腳本文件ndk-build,這個就是進行編譯用的腳本程序。固然,若是運行腳本時不想輸入ndk-build的路徑的話能夠將其所在路徑加入到PATH環境變量中,具體的加入方式咱們在前面的「Linux平臺JDK安裝」一文中已經講過,在此就不重複了。要編譯的文件放在一個目錄下,通常就叫jni(也能夠叫別的名字),把這個目錄放在Android工程下,編譯後的庫文件缺省會自動放到Android工程的庫文件目錄libs中。咱們以NDK自帶的例子程序hello-jni爲例,以下圖所示:
在jni的目錄中,包括編譯配置用的腳本文件和C/C++兩種文件,C/C++除了少許遵循JNI規範外,主要實際上都是Linux環境中C/C++編程而已。配置文件主要有兩個:Android.mk和Application.mk。咱們簡單說一下這兩個文件,通常的NDK開發就足夠了,想詳細瞭解的話能夠閱讀NDK中的相關文檔。
以hello-jni例子中Android.mk文件爲例,以下圖所示:
上面兩條是相關的參數和環境變量設置,咱們不用管它。LOCAL_MODULE
右邊的hello-jni
是編譯後庫的名字,LOCAL_SRC_FILES
右邊的hello-jni.c
是C/C++
源文件的名字,若是有多個源文件,只須要放在後面用空格隔開就好了,不須要把頭文件放進來。最下面的BUILD_SHARED_LIBRARY
表示編譯爲動態庫,若是要編譯爲靜態庫的話就應該是BUILD_STATIC_LIBRARY
。
文件Application.mk主要是對編譯的補充,以native-plasma例子中的Application.mk爲例,以下圖所示:
「APP_ABI
」的右邊指定了所支持的處理器架構,本次版本的NDK
支持arm
、x86
和mips
三種。缺省是按arm
架構編譯。APP_PLATFORM
的右邊指定的是Android
平臺的版本。缺省是按Android SDK 1.5
版本編譯,版本越高所提供的特性也越多,不過能適配的Android SDK
版本也就越少,意味着可以使用該應用的用戶也越少。
固然,NDK既支持C語言環境,也支持C++語言環境,不過對C++的特性支持要少一些,具體能夠看文檔中對C++支持的相關說明。另外在Android.mk和Application.mk中均可以加入對C/C++進行編譯的一些編譯選項,以例子san-angeles中的Android.mk文件爲例,以下圖所示:
和前面的相比,這裏上邊多了LOCAL_CFLAGS,它的右邊就是編譯選項,這個例子中包括兩個ANDROID_NDK和DISABLE_IMPORTGL,每一個選項前加上-D做爲標識符。下邊多了LOCAL_LDLIBS,它的右邊是編譯中用到的庫,每一個庫名前加上-l做爲標識符。 java
本版本的NDK
中有多個例子,咱們簡要說明一下這些的例子的具體做用,便於你們對這些例子有一個初步認識,至少知道每一個例子引入的目的。
bitmap-plasma
:
如何在NDK
中使用bitmap
的例子,早期的NDK
版本不能直接使用bitmap
,後來的版本中增長了對bitmap
的支持。
hello-gl2
:
在NDK
中如何使用OpenGLES
的運用
hello-jni
:
最基本的NDK
使用方式,經過NDK
獲取字符串而後在Android
應用中顯示出來
hello-neon
:
在NDK
中有關neon
的優化
module-exports
:
多個庫的調用方式。foo
被編譯爲靜態庫,bar
被編譯爲動態庫並調用了庫foo
,zoo
被編譯爲動態庫並調用了庫bar
。
native-activity
:
徹底用NDK
實現整個Android
程序
native-audio
:
在NDK
中有關音頻的操做
native-media
:
在NDK
中對視頻的操做
native-plasma
:
徹底用NDK
實現整個Android
程序而且提供了涉及plasma
的優化
san-angeles
:
移植到Android
平臺的OpenGL ES
的例子
test-libstdc++
:
對C++
的支持,但並不是支持C++
的所有特徵
two-libs:兩個庫的使用,first爲靜態庫,second爲動態庫,而且second庫調用first庫 android
4.C
語言代碼實現:
咱們以NDK開發包中自帶的例子hello-jni來進行演示和說明。進入jni目錄下,運行ndk-build就能夠進行編譯了,以下圖所示:
編譯後獲得庫libhello-jni.so
,以lib
字符做爲前綴,so
做爲後綴。實際在程序加載時要去掉這兩部分,即文件名稱在lib
和.so
中間的部分爲真正的庫名稱。須要說明的是和libhello-jni.so
文件在一塊兒的還有兩個文件gdb.setup
和gdbserver
,這兩個是用於NDK
調試的,在最後正式發佈apk
文件時這兩個文件時不須要的。具體NDK
的調試方法,咱們在後面會將,如今在這裏暫時不講。
在Eclipse中加載該例子,因爲該例子最開始不是Eclipse項目,須要建立新項目,選擇從源代碼方式建立,以下圖所示:
建立後,以下圖所示:
Jni
目錄下文件hello-jni.c
以下圖所示:
從上面兩幅圖能夠看到,hello-jni在Java環境中的類HelloJni中聲明的函數名爲stringFromJNI,前面要用到修飾符native,類HelloJni所在的包名爲com.example.hellojni,須要用函數System.loadLibrary加載lib庫libhello-jni.so,採用static修飾符確保只加載一次。而後按正常函數使用就好了。而在NDK這邊,即C語言這層,函數命名要遵循Java_包_類_函數的命名方式,中間用下劃線_進行鏈接,如上面所示,在包com.example.hellojni中的類HelloJni聲明爲stringFromJNI,則在C/C++文件中定義的函數名爲Java_com_example_hellojni_HelloJni_stringFromJNI,注意區分大小寫。函數能夠傳參數,本例子中沒有傳入參數,只是有返回參數,返回參數的數據類型爲jstring,即Java中的String類型。對於C/C++中與上面的Java環境打交道的數據類型能夠參照JNI,具體可訪問官方網站http:// java.sun.com/docs/books/jni/。對於函數Java_com_example_hellojni_HelloJni_stringFromJNI中的兩個參數env和thiz是系統必須的,若是須要輸入參數,必須再增長參數。這個例子運行的結果就是在文本控件(TextView)上面顯示Hello from JNI by C !,以下圖所示: |