Android NDK初探 你也可以做移動(dòng)開發(fā)
51CTO曾介紹Android開發(fā)WebView組件的使用詳解,本文將為各位詳細(xì)介紹Android NDK的安裝、使用和實(shí)戰(zhàn)。我下載的是Android Native Developer Kit (NDK) R4版本,當(dāng)前的最新版。
Android NDK
下載地址如下: http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip
我下面講的都是以linux環(huán)境為準(zhǔn),因?yàn)槲业南到y(tǒng)是linux的。windows下可以弄個(gè)Cygwin,模擬linux環(huán)境。
首先進(jìn)入NDK目錄,有個(gè)README文件,里面提到了API的文檔在docs/STABLE-APIS.TXT里面,如何安裝NDK,參考docs/INSTALL.TXT,還有如何使用NDK,參考docs/HOWTO.TXT。建議這些文檔都看一遍,有個(gè)大概了解。
安裝:
INSTALL.TXT里面講的是如何安裝,安裝NDK,就需要一個(gè)可以make環(huán)境,linux自帶了,所以不用關(guān)心。還有一點(diǎn),以前的版本都需要運(yùn)行build/host-setup.sh來(lái)進(jìn)行初始化,這個(gè)版本把它刪除了,這樣更方便。
然后就是配置環(huán)境變量。
在~/.bashrc文件里面,添加Shell代碼
NDK_ROOT=~/android-ndk-r4b #后面的路徑是NDK所在的目錄,根據(jù)自己的目錄修改 export NDK_ROOT
然后保存,重新打開bash。
使用:
先拿sample試刀吧,剛開始什么都不知道,只有運(yùn)行出一個(gè)例子,才能增加信心。
編譯的兩種方法:
1.進(jìn)入要目標(biāo)工程目錄,比如$NDK_ROOT/samples/hello-jni,然后執(zhí)行$NDK_ROOT/ndk-build
2.在任何地方,執(zhí)行$NDK_ROOT/ndk-build -C $NDK_ROOT/samples/hello-jni.
如果成功的話,會(huì)生成obj和libs兩個(gè)目錄。
選擇一種方法,編譯這個(gè)例子。然后打開eclipse,把hello-jni這個(gè)工程導(dǎo)入,運(yùn)行,ok,就能看到效果了。
進(jìn)階:
docs下的STABLE-APIS.TXT里面講了系統(tǒng)API的用法。我以1.5為例。進(jìn)入$NDK_ROOT/build/platforms/android-3/arch-arm/usr/include,里面有很多.h文件,這些都是可以在NDK里面調(diào)用的,除了linux和asm目錄下的。
一般來(lái)說(shuō),主要用到的是jni.h,里面提供了很多對(duì)類和對(duì)象的操作。
另外,1.5提供了log的API,在android/log.h里面,使用的時(shí)候,在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。
實(shí)例:
給出兩個(gè)點(diǎn)的坐標(biāo),求它們的距離。
首先,創(chuàng)建一個(gè)Point對(duì)象,
Java代碼
- public class Point {
- float x;
- float y;
- }
然后在c文件中定義一個(gè)函數(shù)
C代碼
- jfloat Java_chroya_demo_ndk_Main_distance(JNIEnv* env, jobject thiz, jobject a,jobject b){}
返回值是float,在jni中定義的是jfloat。
函數(shù)名規(guī)則: Java開頭,接著是包名的每一段,然后是類名,最后是Java中調(diào)用的方法名,中間都用下劃線隔開。第一個(gè)參數(shù)JNIEnv* env和第二個(gè)參數(shù)jobject thiz都是必須的,后面的才是Java中傳遞進(jìn)來(lái)的參數(shù)。這里是兩個(gè)Point對(duì)象。
首先確定要做的步驟:
◆找到這個(gè)Point類
◆找到類中的域x和y的域id
◆根據(jù)ID取出x和y的值
◆計(jì)算結(jié)果并返回
那么代碼如下:
Java代碼
- #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里面調(diào)用:
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");
- }
- }
運(yùn)行,得到結(jié)果distance(a,b):2.828427
源碼參見(jiàn)附件 。
【編輯推薦】