編輯:關於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 在出現的彈窗中做以下配置
3、右鍵項目工程Android tools - Add Native Support
出現jni目錄以及Android.mk,xx.cpp就說明添加成功了。就可以進行NDK開發了。
2、Java調用C++中的方法。
例如:獲取從C++文件中獲取字符串並打印
在Activity類A中:
1 2 3 4 5 6 7 8 9 10 11static
{
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 21static
{
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 8LOCAL_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 12LOCAL_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;
}
unity3d發布apk在android虛擬機中運行的詳細步驟(unity3d導出android apk),總的流程分為以下6個步驟:1、安裝java_jdk2、配置ja
當編寫一個混合有本地C代碼和Java的應用程序時,需要使用Java本地接口(JNI)作為連接橋梁。JNI作為一個軟件層和API,允許使用本地代碼調用Java對象的方法,同
前言:生活的艱難,更會激發對夢想的渴望,但艱難的生活卻往往會成為夢想的絆腳石上篇給大家簡單講了Webview中Native代碼與JS相互調用的方法,這篇我們再講講有關各種
一、概述 在上一篇博文中,我們給大家介紹了Android自定義控件系列的基礎篇。鏈接:http://www.cnblogs.com/jerehedu/p/4360