(轉自:http://blog.csdn.net/redoffice/article/details/6654714)javascript
「NDK全稱:Native Development Kit。java
一、NDK是一系列工具的集合。android
* NDK提供了一系列的工具,幫助開發者快速開發C(或C++)的動態庫,並能自動將so和java應用一塊兒打包成apk。這些工具對開發者的幫助是巨大的。app
* NDK集成了交叉編譯器,並提供了相應的mk文件隔離CPU、平臺、ABI等差別,開發人員只須要簡單修改mk文件(指出「哪些文件須要編譯」、「編譯特性要求」等),就能夠建立出so。eclipse
* NDK能夠自動地將so和Java應用一塊兒打包,極大地減輕了開發人員的打包工做。ide
二、NDK提供了一份穩定、功能有限的API頭文件聲明。函數
Google明確聲明該API是穩定的,在後續全部版本中都穩定支持當前發佈的API。從該版本的NDK中看出,這些API支持的功能很是有限,包含有:C標準庫(libc)、標準數學庫(libm)、壓縮庫(libz)、Log庫(liblog)。」工具
在深刻理解以前,暫且就把NDK當成是一種工具,這種工具使得JAVA可以使用C/C++編譯出的so包。並將此包一塊兒打入apk包中。ui
下面開始正式入門:this
1. 下載NDK壓縮包,至於從哪裏下載藉助搜索引擎吧。
2. 解壓NDK壓縮包,配置環境變量。將解壓的地址寫入環境變量PATH中
3. 在命令提示符下輸入ndk-build若是彈出以下的錯誤,而不是說ndk-build not found,就說明ndk環境已經安裝成功了。特別提示一下,搜索引擎中會告訴一些早期的NDK版本的使用,是在命令提示符下輸入build/host-setup.sh;可是NDK通過更新,這個文件已經沒有了。只須要輸入ndk-build就能夠了。
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
/home/braincol/workspace/android/android-ndk-r5/build/core/build-local.mk:85: *** Android NDK: Aborting . Stop.
4. cygwin的安裝,至於如何安裝,從哪裏安裝也去借助搜索引擎吧。在Cygwin安裝過程當中,可能比較慢,必須安裝的項目有make和gcc;建議安裝下面幾個包:autoconf2.1 ,automake1.10 ,binutils ,gcc-core ,gcc4-core ,gdb ,pcre ,pcre-devel,都安裝最新版本。安裝完畢後,運行Cygwin,輸入"make -v"和"gcc -v"來檢測是否安裝成功;make版本要在3.81以上。
5. 以上任務結束後,就表示基本的開發環境搭建完成了。
1. 創建一個android的工程TestNDK,建立TestNDK.java文件。
2. 必要的一些說明
代表程序開始運行的時候會加載testNDK, static區聲明的代碼會先於onCreate方法執行。若是程序中有多個類,並且若是TestNDK這個類不是你應用程序的入口,那麼testNDK(完整的名字是lib testNDK.so)這個庫會在第一次使用TestNDK這個類的時候加載。
能夠看到這兩個方法的聲明中有 native 關鍵字, 這個關鍵字表示這兩個方法是本地方法,也就是說這兩個方法是經過本地代碼(C/C++)實現的,在java代碼中僅僅是聲明。
用eclipse編譯該工程,生成相應的.class文件,這步必須在下一步以前完成,由於生成.h文件須要用到相應的.class文件。暫時不考慮報錯信息。
3. 生成.h文件
在C/C++文件編寫以前,須要利用javah這個工具生成相應的.h文件,而後根據這個.h文件編寫相應的C/C++代碼。
進入到剛纔創建的testNDK工程目錄中,查看工程文件:AndroidManifest.xml assets bin default.properties gen res src並新建一個ndk的文件夾後就能夠進行.h文件的生成了。
在工程目錄下執行: javah -classpath bin -d ndk com.blueeagle.example.TestNDK
這裏-classpath表示類的路徑;-d ndk 表示生成的.h文件存放的目錄;com.blueeagle.example.TestNDK則是完整的類名。
如今能夠再ndk目錄下看到多了一個.h文件:com_blueeagle_example_testNDK.h;打開後,能夠看到.h的內容:
com_blueeagle_example_testNDK.h:
上面代碼中的JNIEXPORT 和 JNICALL 是jni的宏,在android的jni中不須要,固然寫上去也不會有錯。
函數名比較長可是徹底按照:java_pacakege_class_mathod 形式來命名。
也就是說:
TestNDK.java中stringTestNdk() 方法對應於 C/C++中的 Java_com_blueeagle_example_testNDK_ stringTestNdk() 方法
TestNDK.java中stringTestNdk2() 方法對應於 C/C++中的 Java_com_blueeagle_example_testNDK_ stringTestNdk2() 方法
注意下其中的註釋:
Signature: ()Ljava/lang/String;
()Ljava/lang/String;
()表示函數的參數爲空(這裏爲空是指除了JNIEnv *, jobject 這兩個參數以外沒有其餘參數,JNIEnv*, jobject是全部jni函數必有的兩個參數,分別表示jni環境和對應的java類(或對象)自己),
Ljava/lang/String; 表示函數的返回值是java的String對象。
testNDK.c:
這裏只是實現了Java_com_blueeagle_example_testNDK_stringTestNdk方法,而Java_com_blueeagle_example_testNDK_stringTestNdk2 方法並無實現,由於在testNDK.java中只調用了stringTestNdk ()方法,因此stringTestNdk 2()方法沒有實現也不要緊,不過建議最好仍是把全部java中定義的本地方法都實現了。
Java_com_blueeagle_example_testNDK_stringTestNdk 函數只是簡單的返回了一個內容爲 "Hello Test NDK !" 的jstring對象(對應於java中的String對象)。
testNDK.c文件就已經編寫好了,這時的.h文件已經沒有用了。
1 首先須要編寫Android.mk文件
在testNDK.c的同級目錄下新建一個Android.mk的文件
這個Androd.mk文件很短,下面咱們來逐行解釋下:
LOCAL_PATH := $(call my-dir)
一個Android.mk 文件首先必須定義好LOCAL_PATH變量。它用於在開發樹中查找源文件。在這個例子中,宏函數’my-dir’, 由編譯系統提供,用於返回當前路徑(即包含Android.mk file文件的目錄)。
include $( CLEAR_VARS)
CLEAR_VARS由編譯系統提供,指定讓GNU MAKEFILE爲你清除許多LOCAL_XXX變量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),
除LOCAL_PATH 。這是必要的,由於全部的編譯控制文件都在同一個GNU MAKE執行環境中,全部的變量都是全局的。
LOCAL_MODULE := testNDK
編譯的目標對象,LOCAL_MODULE變量必須定義,以標識你在Android.mk文件中描述的每一個模塊。名稱必須是惟一的,並且不包含任何空格。
注意:編譯系統會自動產生合適的前綴和後綴,換句話說,一個被命名爲'hello-jni'的共享庫模塊,將會生成'libhello-jni.so'文件。
重要注意事項:
若是你把庫命名爲‘libtestNDK’,編譯系統將不會添加任何的lib前綴,也會生成libfoo.so,這是爲了支持來源於Android平臺的源代碼的Android.mk文件,若是你確實須要這麼作的話。
LOCAL_SRC_FILES := testNDK.c
LOCAL_SRC_FILES變量必須包含將要編譯打包進模塊中的C或C++源代碼文件。注意,你不用在這裏列出頭文件和包含文件,由於編譯系統將會自動爲你找出依賴型的文件;僅僅列出直接傳遞給編譯器的源代碼文件就好。
注意,默認的C++源碼文件的擴展名是’.cpp’. 指定一個不一樣的擴展名也是可能的,只要定義LOCAL_DEFAULT_CPP_EXTENSION變量,不要忘記開始的小圓點(也就是’.cxx’,而不是’cxx’)
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY表示編譯生成共享庫,是編譯系統提供的變量,指向一個GNU Makefile腳本,負責收集自從上次調用'include $(CLEAR_VARS)'以來,定義在LOCAL_XXX變量中的全部信息,而且決定編譯什麼,如何正確地去作。還有 BUILD_STATIC_LIBRARY變量表示生成靜態庫:lib$(LOCAL_MODULE).a, BUILD_EXECUTABLE 表示生成可執行文件。
2 其次進行編譯
進入到工程根目錄,輸入ndk-build便可生成相應的庫libs/armeabi/testNDK.so
從新編譯testNDK工程,將so包打入工程apk包,便可看到結果。在模擬器上顯示Hello Test NDK!