原文連接:http://blog.csdn.net/codezjx/article/details/8879670html
前言:Android NDK r7及以上的版本已經集成了Cygwin編譯環境,也就是說,咱們徹底能夠拋棄龐大的Cygwin了。java
r6及如下版本,也能夠拋棄幾個G的完整版,使用精簡過的Mini-Cygwin來編譯,解壓後大小僅9M,但短小巧精悍,徹底能夠知足Android NDK的開發。android
下載地址:https://code.google.com/p/mini-cygwin/c++
Eclipse集成Cygwin編譯環境能夠參考個人這篇貼:http://blog.csdn.net/codezjx/article/details/8858825windows
下面進入正題,r7及以上版本,跟着個人這篇帖子,完成環境的升級吧!!!app
參考官網:http://tools.android.com/recent/usingthendkplugineclipse
一、首先確認本身的ADT版本,NDK plugin的支持是在ADT 20及之後的版本。ide
二、安裝Android Native Development Tools(該組件集成C/C++開發環境),既在安裝ADT工具的時候勾選NDK組件,一路next後重啓Eclipse使插件生效。函數
三、下載NDK工具http://developer.android.com/tools/sdk/ndk/index.html,我使用的是最新的android-ndk-r8e-windows-x86.zip,下載完後解壓縮。工具
四、Eclipse -> Window -> Preferences -> Android -> NDK,設置NDK爲剛剛解壓縮的工具包路徑。
侯注:作到這裏時,控制檯報出了一個錯誤:「Unable to launch cygpath. Is Cygwin on the path」,由於個人ndk是以前安裝的,並無專門設置環境變量。按照這個連接中的引導解決:
Head to the project's properties. If you're using Windows, the shortcut is Alt + Enter
; or simply right-click the project name to find its properties.
Go to the C/C++ Build
section; under Builder Settings
tab in Build command:
text box you're likely to find something similar to that below, if it's empty then type in the similar text - namely:${NDKROOT}/ndk-build.cmd
where NDKROOT
, as its name implies, refers to the path where your NDK root folder exists.
Now you must inform eclipse what NDKROOT
equates to; as in, where is the NDK root path. You can do this by heading to (in your project's properties) C/C++ Build
> Environment
> press Add…
Now add your environment variable named NDKROOT (the Name
) with the relevant path (Value
). Note that you're to repeat this per NDK project. You would get a window similar to that below.
Press OK
to the New variable input window and then OK
again to the properties window.
五、NDK環境基本上已經搭建好,新建一個普通Android項目測試NDK支持。項目右鍵->Android Tools->Add Native Support...,輸入.so庫名字後點擊Finish
(注意:若項目已是一個Jni項目,例如NDK example裏面的HelloJni,這一步中.so庫名字不用填)
六、如今已經能夠Build咱們的Jni項目了,選擇項目,Project->Build Project,編譯咱們的c/c++代碼,此時項目結構以下,NDK plugin已經爲咱們添加好了include,已經爲咱們生成了相應的Android.mk以及 cpp文件。(注意:這裏插件爲咱們生成的是cpp文件,若你不喜歡能夠改回.c,並在mk文件中進行相應更改)
七、這時,Android NDK環境已經完美搭建好,咱們能夠在cpp文件中流暢地書寫咱們的c/c++代碼。
(並且當你Alt+/時,已經可使用自動提示,各類爽歪歪有木有。若你不是用NDK plugin來構建JNI項目,而是選擇手動方式,Alt+/是不會提示的)
八、關於編譯,默認狀況下:選擇項目,Project->Build Project,來從新編譯咱們的代碼。並且每次run項目的時候,也會自動編譯.so庫。
一些問題與解決方法:
問題一:Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml (這個是NDK工具的一個BUG,若build Target大於minSdkVersion,則會報這個錯誤,致使沒法運行)
解決方法:
android-ndk-r8e/build/core/add-application.mk第128行把__ndk_warning改成__ndk_info;而後從新build一次項目便可消除錯誤。
原文:
this problem may be safely fixed by changing this line in add-application.mk from __ndk_warning to __ndk_info
連接:
https://code.google.com/p/android/issues/detail?id=39752
問題二:使用c++來編寫本地庫,會有一些兼容問題。
(1)直接黏貼HelloJni的stringFromJNI函數過來測試,提示Method 'NewStringUTF' could not be resolved
解決方法:
改成:將(*env)->NewStringUTF(env, "Hello from JNI !")改成return env->NewStringUTF("Hello from JNI !")便可
緣由是:
NDK plugin默認爲咱們生成的是cpp文件,而C與C++調用函數的參數不一致,所以找不到函數,具體參考jni.h中的定義。cpp文件中形如(*env)->Method(env, XXX)改爲env->Method(XXX)便可。
(2)運行c++生成的.so庫,若報如下錯誤:(既找不到函數)
No implementation found for native Lcom/dgut/android/MainActivity;.stringFromJNI ()Ljava/lang/String;
java.lang.UnsatisfiedLinkError: stringFromJNI
at com.dgut.android.MainActivity.stringFromJNI(Native Method)
解決方法:
爲供Java調用的c++函數前加入extern "C" 修飾,如:(NDK example裏面的cpp文件也是這麼聲明的,參考hello-gl2)
被extern "C"修飾的變量和函數是按照C語言方式編譯和鏈接的。
首先看看C++中對相似C的函數是怎樣編譯的:做爲一種面向對象的語言,C++支持函數重載,而過程式語言C則不支持。函數被C++編譯後在符號庫中的名字與C語言的不一樣。例如,假設某個函數的原型爲:void foo( int x, int y );該函數被C編譯器編譯後在符號庫中的名字爲_foo,而C++編譯器則會產生像_foo_int_int之類的名字(不一樣的編譯器可能生成的名字不一樣,可是都採用了相同的機制,生成的新名字稱爲「mangled name」)。_foo_int_int這樣的名字包含了函數名、函數參數數量及類型信息,C++就是靠這種機制來實現函數重載的。例如,在C++中,函數voidfoo( int x, int y )與void foo( int x, float y )編譯生成的符號是不相同的,後者爲_foo_int_float。
一樣地,C++中的變量除支持局部變量外,還支持類成員變量和全局變量。用戶所編寫程序的類成員變量可能與全局變量同名,咱們以"."來區分。而本質上,編譯器在進行編譯時,與函數的處理類似,也爲類中的變量取了一個獨一無二的名字,這個名字與用戶程序中同名的全局變量名字不一樣。
所以,若咱們沒有使用extern "C"修飾函數,按照C語言方式編譯和鏈接,Jni調用將可能找不到該函數。