Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android ndk開發

Android ndk開發

編輯:關於Android編程

前言:我對C/C++是沒有任何基礎的,雖然大學中學了一個學期的C但是都算還給老師了。這篇文章是我做一個NDK項目積累下來的知識,可以說是一篇小白上手文章,所以高手請自行繞路。

1、准備

做NDK開發是非常要注意開發環境和開發版本的(個人認為)。我使用的是Eclipse (Luna 4.4.0),NDK版本r10,應該是在<=r6版本的NDK還需要安裝cygwin(這這裡就不討論,網上大把資料),附上NDK的下載鏈接方便不能翻牆的朋友,32位 ,64位,網站不能訪問,但是直接用下載鏈接是可以下載到的。

安裝好NDK後,就需要在Eclipse上進行配置了。

1、windows-preferences-android-ndk-ndklocation 選擇ndk的安裝目錄

2、配置builder環境在需要進行ndk開發的項目上右鍵-properties-builder-new - program 在出現的彈窗中做以下配置

 

wKioL1Uva7bxkgyqAAHHkSQdv6o361.jpg

wKiom1UvamKgeEteAAE299U2L3w010.jpg

wKioL1Uva7eRmrMdAAIIeisqxW0452.jpg

3、右鍵項目工程Android tools - Add Native Support

wKioL1UvbF_Cvl6KAAAst-L9hxw144.jpg

出現jni目錄以及Android.mk,xx.cpp就說明添加成功了。就可以進行NDK開發了。

 

2、Java調用C++中的方法。

例如:獲取從C++文件中獲取字符串並打印

在Activity類A中:

1 2 3 4 5 6 7 8 9 10 11 static{ System.loadLibrary("xx");//xx是Android.mk文件中LOCAL_MODULE 的字段 } //必須和ndk中的方法名一樣 public native String getString(); //onclick方法 public void click(View v){ String str = getString(); System.out.println("調用JNI中的方法:"+str); }

在ndk.cpp中

1 2 3 4 5 6 7 8 9 10 11 #include #include /** * extern "C" 是必須加的,經測試不加的話方法調用不成功,也沒找到答案,有知道為什麼的請* 告知,方法名稱必須按照JNI的規范來Java_包名_類名_方法名,都必須以'_'隔開。 */ extern "C" jstring Java_com_test_ndk_A_getString(JNIEnv* env,jobject thiz){ jstring str ; //在C中的是以(*env)->調用的,網上大部分的博客文檔也是這種情況。 str = env->newStringUTF("hello world");//不能使用中文,不然會報錯。 return str; }

運行工程即可看到效果。

3、C++中調用Java方法

在ClassB中

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 static{ System.loadLibrary("ndk"); } public native void loadJavaMethod(); public void f1(){ String str ; str = "hello world from java"; System.out.println(str); } public String f2(){ String str ; str = "f2: hello world from java"; System.out.println(str); return str; } public void f3(String str,int i){ System.out.println("f3 內容為:"+str+",數字為:"+i); }

在ndk.cpp中

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include #include extern "C" void Java_com_test_ndk_B_loadJavaMethod(JNIEnv *env,jobject thiz){ //調用無參無返回值的方法 jclass cls = env->GetObjectClass(thiz); //GetMethodID("jclass對象","方法名","方法參數") jmethodID mID = env->GetMethodID(cls,"f1","()V"); if(mID != NULL){ env->CallVoidMethod(thiz,mID); } //調用有參無返回值得方法 //參數類型除了基本數據類型外,其他的都需要按照這樣的格式 //L包名/類名; 包名用/分割,必須以;結束 //詳情請參考這篇文章 jclass cls = env->GetObjectClass(thiz); jmethodID mID = env->GetMethodID(cls,"f3","(Ljava/lang/String;I)V"); jstring content = env->NewStringUTF("hehe"); jint i = 10; if(mID != NULL){ env->CallVoidMethod(thiz,mID,content,i); } //調用有返回值無參的方法 jclass cls = env->GetObjectClass(thiz); jmethodID mID = env->GetMethodID(cls,"f2","()Ljava/lang/String;"); if(mID != NULL){ env->CallObjectMethod(thiz,mID); } //調用其他類中的方法假設有一個Student類,如果要使用Student類中的內部類A,格式為 //com/test/ndk/Student$A jclass stu = env->FindClass("com/test/ndk/Student"); //實例化無參構造方法 jobject stuObj = env->NewObject(stu,env->GetMethodID(stu,"","()V")); jmethodID getNameId = env->GetMethodID(stu,"getName","()V"); if(getNameId !=NULL){ env->CallVoidMethod(stuObj,getNameId); } }

4、在自己的 so文件中調用第三方的so文件

這種情況一般是因為第三方的C/C++中的方法不是按照JNI的規范來寫,這時就需要進行重新包裝,並使用,當然前提是有了第三方的說明文檔。

將第三方的so文件配置到預編譯環境

在工程的jni文件下新建prebuilt文件夾(名稱隨意)將第三方的so文件放到裡面例如libthird.so,然後在這個文件夾下新建Androdid.mk文件,文件內容為

1 2 3 4 5 6 7 8 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libthird LOCAL_SRC_FILES := libthird.so include $(PREBUILT_SHARED_LIBRARY)

打開jni下的Android.mk文件,加入以下字段

1 2 3 4 5 6 7 8 9 10 11 12 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := ndk LOCAL_SRC_FILES := ndk.cpp #名稱和第三方mk中LOCAL_MODULE定義的名稱一樣 LOCAL_SHARED_LIBRARIES := libthird include $(BUILD_SHARED_LIBRARY) #添加路徑 include $(LOCAL_PATH)/prebuilt/Android.mk

配置完成後,在工程的libs\armeabi目錄下可以看到第三方的so文件,注意不能直接將第三方的so文件放到這個目錄下。否則在builde的時候會刪除。

假設在第三方的C/C++文件中有這樣一個方法

1 2 3 4 //extern "C"在第三方的包中的方法也必須添加,測試時,如果不添加方法調用不成功,但這個是不能限//制到第三方的,有待解決 extern "C" int f1(){ return 101; }

在自己的C/C++文件中調用第三方的方法

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include #include #include void *filehandle = NULL; jstring (*f1)() =NULL; extern "C" jint Java_com_test_ndk_classA_f1(JNIEnv * env,jobject thiz){ jint i ; filehandle = dlopen("/data/data/com.fly.ndk2/lib/libndk.so", RTLD_LAZY); if(filehandle){ f1 = (int(*)())dlsym(filehandle,"f1"); } if(f1){ i = f1(); dlclose(filehandle); filehandle = NULL; } return i; }
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved