開始學習NDK開發,首先以輸出Hello World執行個體開始講解。
NDK的開發步驟:
1、在Java檔案中聲明native方法
public class TestActivity extends Activity {static {System.loadLibrary("my-ndk");}// 聲明JNI層的原生方法,使用native關鍵字public native String stringFromJNI();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);TextView tvText = new TextView(this);tvText.setText(stringFromJNI());setContentView(tvText);}}
2、編譯Java檔案
直接用javac命令編譯聲明native方法的Java檔案
shamoo的工程目錄在E:\project\test
在cmd中,輸入cd E:\project\test
javac src\com\shamoo\jni\HelloJni.java -d bin\classes
-d指定.class檔案的輸出目錄
也可以使用eclipse直接產生,產生的目錄在工程目錄的bin\classes
3、使用javah命令產生標頭檔
關於javah命令,Shamoo也折騰了一段時間,一直使用命令失敗,總是提示不能訪問Android sdk的類,後來用-classpath指定src的位置就可以了,具體原因不明...
javah -classpath src -d jni -jni com.shamoo.activity.TestActivity
如果聲明native方法的類中沒有使用Android sdk的類就可以使用以下命令,例如HelloJni聲明了navtive方法
javah -classpath bin/classes -d jni -jni com.shamoo.jni.HelloJni
-classpath指定.class檔案的根目錄 -d指定輸出目錄 -jni指定聲明了native方法的類。javah是根據.class檔案反編譯產生標頭檔的
產生的標頭檔如下:
/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class com_shamoo_activity_TestActivity */#ifndef _Included_com_shamoo_activity_TestActivity#define _Included_com_shamoo_activity_TestActivity#ifdef __cplusplusextern "C" {#endif/* * Class: com_shamoo_activity_TestActivity * Method: stringFromJNI * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_shamoo_activity_TestActivity_stringFromJNI (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
從標頭檔可以看出,原生方法必須指定Java + 原生方法的包名(點用底線代替) + 方法名
4、編寫標頭檔對應的源檔案 com_shamoo_activty_TestActivity.cpp
#include #include #include JNIEXPORT jstring JNICALL Java_com_shamoo_activity_TestActivity_stringFromJNI (JNIEnv *env, jobject) {printf("Hello World");return env->NewStringUTF("Hello World");} 是不是很熟悉,printf("Hello World");不過printf預設不會輸出到Log裡面,需要設定一下才可以。這次編寫源檔案就不需要再寫extern "C"標誌,因為自動產生的標頭檔已經幫我們完成啦!
5、修改Android.mk檔案
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := my-ndkLOCAL_SRC_FILES := my-ndk.cpp com_shamoo_activity_TestActivity.cppLOCAL_LALIBS += -lloginclude $(BUILD_SHARED_LIBRARY)
Android.mk其實就是Makefile,分析一下上面的幾個環境變數
LOCAL_PATH指定源碼的目錄,$(call my-dir),學過Linux Shell再熟悉不過了
LOCAL_MODULE編譯產生的.so庫
LOCAL_SRC_FILES指定加入編譯的源檔案
LOCAL_LALIBS指定其他庫,-l + 庫名,例如上述要使用到NDK的LOG就要使用log庫
include匯入一些Makefile的片段,比如匯入CLEAR_VARS會在配置之前清除以前的環境變數,以免編譯的時候受到其他環境變數的影響,BUILD_SHARED_LIBRARY是匯入其他的共用庫
好的直接編譯,執行,沒問題就會看到一個Activity顯示Hello World的文本啦!