Android NDK 的具體開發步驟可以參考這裡:http://www.linuxidc.com/Linux/2012-07/66104.htm
使用Android NDK 在底層開發時,有可能會導致代碼結構的混亂,因為C 和C++的代碼明顯沒有Java那樣工整,再加上代
碼層調用中往往需要進行數據類型的轉化,所以,搭建一個條理清晰的代碼框架顯得非常重要,昨天看到一個老外的文章,就
說到這個問題,現在根據個人經驗稍微總結一下:
本Demo中用到的三個代碼文件為 JNI.java(負責Java層的native方法), native_glue.c(負責Java與C 語言間的類型轉化,
java與C語言函數的調用),native.c (負責實現具體的C語言函數);
第一、在Java層,建議專門寫一個類來進行C和Java代碼間的調用,比如 JNI.java,在這個 類中只寫上 native方法和 加載
動態庫的代碼,如下:
- package ndk.demo;
-
- public class JNI {
- static {
- //調用 ndk 編譯生成的庫
- System.loadLibrary("ndkDemo");
- }
-
- private static native int test(byte[] data, int size);
-
- private static native int getResult();
- }
現在生成.h頭文件,具體生成方法請參考文章開頭的連接,生成的.h內容如下:
- /*
- * Class: ndk_demo_JNI
- * Method: test
- * Signature: ([BI)I
- */
- JNIEXPORT jint JNICALL Java_ndk_demo_JNI_test
- (JNIEnv *, jclass, jbyteArray, jint);
-
- /*
- * Class: ndk_demo_JNI
- * Method: getResult
- * Signature: ()I
- */
- JNIEXPORT jint JNICALL Java_ndk_demo_JNI_getResult
- (JNIEnv *, jclass);
注意方法的名稱,其和你所寫的 JNI.java的包名對應一致;
第二、這一步是關鍵,在程序的目錄下新建一個文件夾,命名為 jni ,在裡面寫一個 native_glue.c的C 文件,我把這個 .c 文
件命名為glue(膠水),意為用它來將Java代碼和C 代碼粘和起來,就像一個接口一樣,負責Java層和C/C++層的相互調用,
在這個文件中寫上上面生成的 .h 文件中的,除此之外,可以在這個文件文件中寫上Java和 C語言數據類型轉換的代碼,而真正
的 native.c 代碼只負責函數功能的實現,屬於純C語言代碼,不涉及任何與Java有關的操作,現 native_glue.c的完整代碼如下:
- #include<stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include <jni.h>
- #include <android/log.h>
-
- #include"native.c"
-
- JNIEXPORT jint JNICALL Java_ndk_demo_JNI_test(JNIEnv *env, jclass thiz,
- jbyteArray jdata, jint size) {
-
- //數據類型轉換:jbyteArray---> jbyte*
- jbyte*data = (jbyte*) (*env)->GetByteArrayElements(env, jdata, 0);
- //調用 native.c 中的方法
- int len = native_test(data, size);
- //釋放類型轉換中的資源
- (*env)->ReleaseByteArrayElements(env, jdata, data, 0);
- return len;
- }
-
- JNIEXPORT jint JNICALL Java_ndk_demo_JNI_getResult(JNIEnv * env, jclass thiz) {
- return native_getResult();
- }
第三、native.c的代碼如下:
- #include<stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- /*代碼只是做個演示,沒有寫任何功能,*/
-
- int native_test(jbyte*data, int size) {
- return size;
- }
-
- int native_getResult() {
- return 0;
- }
如上所示,native_glue.c 作為接口,對數據進行預處理,再調用 native.c中的函數,使得 native.c集中負責具體實現,不會牽
扯任何多余操作,代碼結構清晰,以後修改代碼時也會更加方便,你只需更改native_glue.c 的函數名稱就行,不用對整個文件
修改。
第四、經過上述三個步驟,一個完整的Android NDK 代碼框架就寫好了,再在 .c 文件的目錄下編寫 Android.mk,在該文件目
錄下運行 ndk-build 命令,生成動態庫,Android.mk文件如下:
- LOCAL_PATH := $(call my-dir)
-
- include $(CLEAR_VARS)
-
- LOCAL_MODULE := ndkDemo #要生成的動態庫的名字
- LOCAL_SRC_FILES := native_glue.c
- LOCAL_LDLIBS+= -lz -lgcc
-
- include $(BUILD_SHARED_LIBRARY)
編譯如下圖所示:
這樣,就會自動在程序根目錄下生成一個 libs 文件夾,裡面有一個 libndkDemo.so 文件(NDK 規定編譯生成的庫文件名稱必須以
lib 開頭,比如你在Android.mk中寫的庫名稱為 ndkDemo,那麼真正生成的庫名稱是 libndkDemo.so),這就是你所需要的動態
庫文件了。這個Demo的代碼結構如下:
源代碼下載地址:
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /2012年資料/7月/23日/Android NDK :編寫清晰的代碼結構/