NDK入門、提高和實戰

    網上也有一些對NDK的介紹,不過都是很簡單的把sample裏面的例子講解一下,並不深入,我這裏把我的所得分享一下。我下載的是Android Native Developer Kit (NDK) R4版本,當前的最新版。
    下載地址如下:

    http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip

 

    我下面講的都是以linux環境爲準,因爲我的系統是linux的。windows下可以弄個Cygwin,模擬linux環境,網上有很多介紹。
    首先進入ndk目錄,有個README文件,裏面提到了API的文檔在docs/STABLE-APIS.TXT裏面,如何安裝NDK,參考docs/INSTALL.TXT,還有如何使用NDK,參考docs/HOWTO.TXT。建議這些文檔都看一遍,有個大概瞭解。

 

    安裝:
    INSTALL.TXT裏面講的是如何安裝,安裝NDK,就需要一個可以make環境,linux自帶了,所以不用關心。還有一點,以前的版本都需要運行build/host-setup.sh來進行初始化,這個版本把它刪除了,這樣更方便。
    然後就是配置環境變量。
    在~/.bashrc文件裏面,添加   

NDK_ROOT=~/android-ndk-r4b #後面的路徑是NDK所在的目錄,根據自己的目錄修改
export NDK_ROOT
 

    然後保存,重新打開bash。

 

    使用:
    先拿sample試刀吧,剛開始什麼都不知道,只有運行出一個例子,才能增加信心。
    編譯的兩種方法:
    1.進入要目標工程目錄,比如$NDK_ROOT/samples/hello-jni,然後執行$NDK_ROOT/ndk-build
    2.在任何地方,執行$NDK_ROOT/ndk-build -C $NDK_ROOT/samples/hello-jni.
    如果成功的話,會生成obj和libs兩個目錄。
    選擇一種方法,編譯這個例子。然後打開eclipse,把hello-jni這個工程導入,運行,ok,就能看到效果了。

 

    進階:
    docs下的STABLE-APIS.TXT裏面講了系統API的用法。我以1.5爲例。進入$NDK_ROOT/build/platforms/android-3/arch-arm/usr/include,裏面有很多.h文件,這些都是可以在NDK裏面調用的,除了linux和asm目錄下的。
    一般來說,主要用到的是jni.h,裏面提供了很多對類和對象的操作。
    另外,1.5提供了log的API,在android/log.h裏面,使用的時候,在c文件中#include <android/log.h>,然後在Android.mk裏面加上LOCAL_LDLIBS := -llog,就可以了。
    1.6到2.01提供了openGL ES 1.x的API,2.1提供了openGL ES 2.0的API,2.2提供了graphics的處理接口。使用方法同log。

 

    實例:
    給出兩個點的座標,求它們的距離。
    首先,創建一個Point對象,
   

public class Point {
	float x;
	float y;
}
 

    然後在c文件中定義一個函數   

jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b){}

 

    返回值是float,在jni中定義的是jfloat。

    函數名規則: Java開頭,接着是包名的每一段,然後是類名,最後是Java中調用的方法名,中間都用下劃線隔開。第一個參數JNIEnv* env和第二個參數jobject thiz都是必須的,後面的纔是Java中傳遞進來的參數。這裏是兩個Point對象。


    首先確定要做的步驟:
    1.找到這個Point類
    2.找到類中的域x和y的域id
    3.根據ID取出x和y的值
    4.計算結果並返回
    那麼代碼如下:

#include <jni.h>
#include <math.h>
#include <android/log.h>

jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b)
{
        //步驟1
	jclass point_class = (*env)->FindClass(env, "chroya/demo/ndk/Point");
	if(point_class == NULL) {
		//printf("class not found");
		__android_log_write(ANDROID_LOG_INFO, "MyNdkDemo", "class Point not found");
		return 0;
	} else {
		__android_log_write(ANDROID_LOG_INFO, "MyNdkDemo", "found class Point");
	}
        //步驟2
	jfieldID field_x = (*env)->GetFieldID(env, point_class, "x", "F");
	jfieldID field_y = (*env)->GetFieldID(env, point_class, "y", "F");
        //步驟3
	jfloat ax = (*env)->GetFloatField(env, a, field_x);
	jfloat ay = (*env)->GetFloatField(env, a, field_y);
	jfloat bx = (*env)->GetFloatField(env, b, field_x);
	jfloat by = (*env)->GetFloatField(env, b, field_y);
        //步驟4
	return sqrtf(powf(bx-ax, 2) + powf(by-ay, 2));
}

     然後在Java裏面調用:

public class Main extends Activity {
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(getApplicationContext());
        Point a = new Point();
        a.x = 3;
        a.y = 3;
        
        Point b = new Point();
        b.x = 5;
        b.y = 5;
        
        float d = distance(a,b);
        tv.setText("distance(a,b):"+d);
        setContentView(tv);
    }
    
    public native float distance(Point a, Point b);
    
    static {
    	System.loadLibrary("demo");
    }
}

      運行,得到結果distance(a,b):2.828427

      源碼參見附件

發佈了18 篇原創文章 · 獲贊 1 · 訪問量 3467
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章