1. 程式人生 > >Eclipse中ndk配置及示例

Eclipse中ndk配置及示例

一、關於NDK:
NDK全稱:Native Development Kit。 
1、NDK是一系列工具的集合。 
NDK提供了一系列的工具,幫助開發者快速開發C(或C++)的動態庫,並能自動將so和java應用一起打包成apk。這些工具對開發者的幫助是巨大的。 
NDK集成了交叉編譯器,並提供了相應的mk檔案隔離CPU、平臺、ABI等差異,開發人員只需要簡單修改mk檔案(指出“哪些檔案需要編譯”、“編譯特性要求”等),就可以創建出so。 
NDK可以自動地將so和Java應用一起打包,極大地減輕了開發人員的打包工作。 
2、NDK提供了一份穩定、功能有限的API標頭檔案宣告。 
Google明確宣告該API是穩定的,在後續所有版本中都穩定支援當前釋出的API。從該版本的NDK中看出,這些API支援的功能非常有限,包含有:C標準庫(libc)、標準數學庫(libm)、壓縮庫(libz)、Log庫(liblog)。



二、NDK例項的實現:
對於Windows環境下NDK的開發,如果使用的NDK是r7之前的版本,必須要安裝Cygwin才能使用NDK,所以為Eclipse需要配置的builder,其實是執行Cygwin,然後傳遞ndk-build作為引數。在NDKr7開始,Google的Windows版的NDK提供了一個ndk-build.cmd的指令碼,這樣,就可以直接利用這個指令碼編譯,而不需要使用Cygwin了。只需要為EclipseAndroid工程新增一個Builders,就能讓Eclipse自動編譯NDK。


本文是講述NDK-r7下的實現例項。
下面是使用NDK-r7在下配置自動編譯的builders的過程(實際上對於Linux,只需要修改ndk-build.cmd為ndk-build就可以了。)。

(1)先下載安裝NDK-r7。
下載地址:http://developer.android.com/sdk/ndk/index.html
下載後解壓縮就可以用了。
(2)開啟Eclipse,新建一個Android工程(我的取名為TestNdk),在工程目錄TestNdk下新建jni資料夾,該資料夾就用來儲存NDK需要編譯的檔案程式碼等。
(3)新建並配置一個Builder:
  (a)Project->Properties->Builders->New,新建一個Builder。 
  (b)在彈出的【Choose configuration type】對話方塊,選擇【Program】,點選【OK】: 

  (c)在彈出的【Edit Configuration】對話方塊中,配置選項卡【Main】。
       在“Name“中輸入新builders的名稱(我取名為Ndk_Builder)。
       在“Location”中輸入nkd-build.cmd的路徑。
      (我的是D:\AndroidDev\-ndk-r7\ndk-build.cmd,根據各自的ndk路徑設定,也可以點選“Browser File System…”來選取這個路徑)。
       在“Working Diretcoty”中輸入${workspace_loc:/TestNdk}(也可以點選“Browse Workspace”來選取TestNdk目錄)。

  (d)【Edit Configuration】對話方塊中,配置選項卡【Refresh】。
      勾選“Refresh resources upon completion”,
      勾選“The entire workspace”,
      勾選“Recuresively include sub-folders”。

  (e)【Edit Configuration】對話方塊中,配置選項卡【Build options】。
      勾選“After a “Clean””,
      勾選“During manual builds”,
      勾選“During auto builds”,
      勾選“Specify working set of relevant resources”。

      點選“Specify Resources…”
      勾選TestNdk工程的“jni“目錄,點選”finish“。 
點選“OK“,完成配置。
OK,到這裡Eclipse就能夠自動呼叫NDK編譯jin目錄下的C/C++程式碼了。
Android NDK開發篇(一):新版NDK環境搭建(免Cygwin,超級快)
2014-04-14     0 個評論   來源:Android NDK開發篇(一):新版NDK環境搭建(免Cygwin,超級快)  
收藏  我要投稿

以前做Android的專案要用到NDK就必須要下載NDK,下載安裝Cygwin(模擬Linux環境用的),下載CDT(Eclipse C/C++開發外掛),還要配置編譯器,環境變數...

麻煩到不想說了,Shamoo在網上查了一下資料,發現了一個超級快配置NDK的辦法。

Step1:到Android官網下載Android的開發工具ADT(Android Development Tool的縮寫),該工具集成了最新的ADT和NDK外掛以及Eclipse,還有一個最新版本SDK。解壓之後就可以用了,非常爽!

ADT外掛:管理Android SDK和相關的開發工具的

NDK外掛:用於開發Android NDK的外掛,ADT版本在20以上,就能安裝NDK外掛,另外NDK集成了CDT外掛

也可以線上更新ADT、NDK外掛,不過速度超級慢...所以果斷在網上下載整合開發工具ADT,下載連結見:http://developer.android.com/sdk/index.html

Step2:到Android官網下載最新的NDK,注:NDK版本在r7以上之後就集成了Cygwin,而且還是十分精簡版。比起下載Cygwin要方便多啦!下載連結見:http://developer.android.com/tools/sdk/ndk/index.html

下載完成之後,解壓搞定!

Step3:開啟Eclipse,點Window->Preferences->Android->NDK,設定NDK路徑,例如Shamoo的是E:\android-ndk-r9c

\

Step4:新建一個Android工程,在工程上右鍵點選Android Tools->Add Native Support...,然後給我們的.so檔案取個名字,例如:my-ndk

\

這時候工程就會多一個jni的資料夾,jni下有Android.mk和my-ndk.cpp檔案。Android.mk是NDK工程的Makefile,my-ndk.cpp就是NDK的原始檔。

Step5:接下來仿著NDK的demo,Hello-JNI工程寫一下。使用Alt + '/'可以程式碼提示!很爽!有木有?之前用CDT時候死活都按不出程式碼提示,鬱悶...

\

JNI介面的命名規範是:Java_ + 呼叫該方法的包名(包名的點用_代替) + _ + 呼叫該介面的類名 + _ + 方法名,對於例項方法,有兩個引數是必要的,一個JNI的環境指標JNIEnv *,另一個是呼叫該方法的Java例項jobject

my-ndk.cpp:

?
1 2 3 4 5 6 #include <jni.h> JNIEXPORT jstring JNICALL Java_com_shamoo_activity_TestActivity_stringFromJNI(JNIEnv *env, jobject thiz) { return env->NewStringUTF("Hello jni"); }</jni.h>

TestActivity.java: ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class TestActivity extends Activity { static { System.loadLibrary("my-ndk"); } // 宣告JNI層的原生方法,使用native關鍵字 public native String stringFromJNI(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tvText = new TextView(this); tvText.setText(stringFromJNI()); setContentView(tvText); } }

使用ndk庫必須在static程式碼塊裡面用System.loadLaibrary載入.so庫

Step6:完成了,然後執行。執行之前先編譯NDK,然後在編譯JAVA程式碼。編譯也許會遇到Unable to launch cygpath. Is Cygwin on the path?錯誤,解決辦法如下:

1.工程右鍵,點Properties->C/C++ Build的Building Settings中去掉Use default build command,然後輸入${NDKROOT}/ndk-build.cmd

\

2.在C/C++ Build中點選Environment,點Add...新增環境變數NDKROOT,值為NDK的根目錄

\

3.再編譯,問題就解決啦!

執行時崩潰,遇到java.lang.UnsatisfiedLinkError: stringFromJNI錯誤,解決辦法:在C++檔案中函式定義前新增extern "C"修飾

?
1 2 3 4 5 6 7 8 9 extern "C" { JNIEXPORT jstring JNICALL Java_com_shamoo_activity_TestActivity_stringFromJNI(JNIEnv *env, jobject thiz); } JNIEXPORT jstring JNICALL Java_com_shamoo_activity_TestActivity_stringFromJNI(JNIEnv *env, jobject thiz) { return env->NewStringUTF("Hello jni"); }

原因是:使用extern "C"修飾,編譯器會按C語言的方式編譯和連線。在C語言中,函式編譯之後函式名與C++函式編譯之後不同,例如foo(int x, int y),C可能會編譯成_foo的名字,而C++因為支援過載,所以會編譯成像_foo_int_int這種帶引數的函式名。如果是按照C語言的編譯方式,呼叫foo函式是找不到_foo的函式名就會報出函式名找不到的錯誤。所以要新增extern "C"修飾。