開發環境下載:
JDK
cywin
eclipse: plugin ADT(for android) + CDT(for C/C++)
android sdk
android ndk
編輯/home/your_account/.bash_profile,並加入以下環境變數宣告(請依sdk的存放位置改變路徑)
ANDROID_TOOLS=/android/android-sdk/tools/ANDROID_PLATFORM_TOOLS=/android/android-sdk/platform-tools/NDK_ROOT=/android/android-ndk-r8b/NDK_SAMPLE=/android/android-ndk-r8b/samples/ export PATH=ANDROID_TOOLS:NDK_ROOT:$NDK_SAMPLE
打開Cygwin Bash Shell,在windows下,因為換行的格式不同(\r\n),因此在存檔後需將格式換回unix,請執行以下指令:dos2unix .bash_profile
這樣子在每次打開Cygwin Bash Shell的時候,因為系統就會自動去執行.bash_profile這個檔案,所以便能夠自動將正確的路徑導入到環境變數之中。
試著執行: adb version,如果可以執行便表示環境變數順利載入,shell可以找到ANDROID_PLATFORM_TOOLS底下的工具。
android hello world:
新建一個android application project,然後run as Android application.
那麼,我們到底該怎麼使用NDK來呼叫C/C++呢?
首先,在專案目錄下建立一個資料夾:jni,接著在這個資料夾中加入三個檔案:
Android.mk:
LOCAL_PATH := (CLEAR_VARS) LOCAL_LDLIBS := -llog LOCAL_MODULE := myNativeLOCAL_SRC_FILES := native.cpp include $(BUILD_SHARED_LIBRARY)
Application.mk:
APP_STL := stlport_static
native.cpp (這個可以隨自己高興命名,但必須命名一致其中functin的命名規則必須遵照一定的格式):
#include <jni.h>#include
Java端如下:
package com.horizon.AndroidHelloWorld; import com.horizon.AndroidHelloWorld.R; import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } private native void helloLog(String logThis); public void onClickButton(View v){ helloLog(“This will log to LogCat via the native call.”); } static { System.loadLibrary(“myNative”); } }
之後打開cygwin bash shell,到project的目錄底下,執行以下指令:
ndk-build
如果執行成功,則會產生檔案至project/obj/local/armeabi/libmyNative.so
名稱則是Android.mk中LOCAL_MODULE中加上前綴lib及後綴.so,由於這個特性,因此在命名LOCAL_MODULE的時候,千萬不能以lib作為開頭,因為NDK會沒辦法產生正確的.so檔。
之後,就可以執行android程式來進行測試。
另外,請注意任何在android.mk中的space都會導致路徑無法找到
例如:
“LOCAL_PATH := (call my-dir) “是不同的,後者會導致 no rule to make target的錯誤。
如果產生
expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘attribute’ before ‘.’ token 之類的錯誤 則表示我們用到gcc去編譯C++的檔案了,解決方法有二種:
1.改用g++來編譯:.c的檔案會使用gcc而.cpp會使用g++。
2.加入extern “C”在C的CODE中來兼容C的語法
只是,在jni中,其提供了二個不同的界面給C及C++使用,例如同樣一個function:
在C中:(*env)→NewStringUTF(env, “Hello from JNI”);
在C++中:env→NewStringUTF(“Hello from JNI”);
由於C是C++的子集合,而C++在語法規則上又比C更加的嚴格,因此在開發上最好統一用C++來進行開發。(意即所有的檔名都是以.h或.cpp結尾)
在初始的設定上,其實NDK並不支持stl,為了效能的問題,在預設計只會使用最少的C++函式庫。如果要使用stl的話,我們就必須在Application.mk中加入以下的宣告:
APP_STL := stlport_static
其實還有其他的stlport,各有不同特性的支援:
stlport_static :目前推薦的方法,但在現時點並不支援exception及RTTI。
stlport_shared:作為動態函式庫,可能會有兼容性的問題,目前不推薦使用。
gnustl_static:其使用GNU libstdc++作為靜態庫,可支援exception及RTTI,但由於這個library的license是基於GPLv3,因此在使用前要多加考慮。
參考:http://www.open-open.com/bbs/view/1319209398468