一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Android JNI開發(fā)入門之二

 MikeDoc 2011-08-19
 在上一篇文章《Android JNI開發(fā)入門之一》中,我介紹了Android應(yīng)用程序(APK)怎樣通過(guò)JNI調(diào)用Native C實(shí)現(xiàn)的共享庫(kù)。本文將進(jìn)一步介紹Android應(yīng)用程序通過(guò)JNI調(diào)用Native C++實(shí)現(xiàn)的共享庫(kù),并實(shí)現(xiàn)一個(gè)和上文《Android JNI開發(fā)入門之一》相同功能的Helloworld應(yīng)用程序。

兩套不同的API

前文已經(jīng)提到,Android系統(tǒng)的Java虛擬機(jī)為C和C++實(shí)現(xiàn)兩套不同的API,所以我們調(diào)用的時(shí)候需要注意這一點(diǎn)兒。另外Google并沒(méi)有提供JNI的文檔,我們調(diào)用的時(shí)候可以參考Android的jni.h文件,里面有C和C++的JNI函數(shù)原型。也可以把本例的相同功能HelloWorld庫(kù)和上文《Android JNI開發(fā)入門之一》進(jìn)行比較。

C++實(shí)現(xiàn)HelloWorld共享庫(kù)

在本例中Android應(yīng)用程序不需要有任何變化,我們需要重新用C++實(shí)現(xiàn)HelloWorld共享庫(kù)。創(chuàng)建com_simon_Helloworld.cpp文件,并在文件中輸入如下內(nèi)容:

#include <jni.h>
#define LOG_TAG "HelloWorld"
#include <utils/Log.h>
/*
* Class:     com_simon_Helloworld
* Method:    print
* Signature: ()V
*/
/*JNIEXPORT void JNICALL Java_com_simon_Helloworld_print(JNIEnv *, jobject)*/
JNIEXPORT jstring JNICALL Java_com_simon_HelloWorld_printJNI(JNIEnv *env, jobject obj)
{
LOGI("Hello World From libhelloworld.so!");
return env->NewStringUTF("Hello World!");
}
static const char *classPathName = "com/simon/HelloWorld";
static JNINativeMethod methods[] = {
{"printJNI", "()Ljava/lang/String;", (void*)Java_com_simon_HelloWorld_printJNI },
};
/*
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL) {
LOGE("Native registration unable to find class '%s'", className);
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
LOGE("RegisterNatives failed for '%s'", className);
return JNI_FALSE;
}
return JNI_TRUE;
}
/*
* Register native methods for all classes we know about.
*
* returns JNI_TRUE on success.
*/
static int registerNatives(JNIEnv* env)
{
if (!registerNativeMethods(env, classPathName,
methods, sizeof(methods) / sizeof(methods[0]))) {
return JNI_FALSE;
}
return JNI_TRUE;
}
typedef union {
JNIEnv* env;
void* venv;
} UnionJNIEnvToVoid;
/* This function will be call when the library first be loaded */
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
UnionJNIEnvToVoid uenv;
JNIEnv* env = NULL;
LOGI("JNI_OnLoad!");
if (vm->GetEnv((void**)&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed");
return -1;
}
env = uenv.env;;
if (registerNatives(env) != JNI_TRUE) {
LOGE("ERROR: registerNatives failed");
return -1;
}
return JNI_VERSION_1_4;
}

本例與上文《Android JNI開發(fā)入門之一》對(duì)比有如下幾點(diǎn)不同需要注意:

1、C和C++實(shí)現(xiàn)共享庫(kù)調(diào)用不同JNI API。前面已經(jīng)提到Android系統(tǒng)JNI為C和C++提供了兩套不同的API。請(qǐng)仔細(xì)對(duì)比NewStringUTF,GetEnv函數(shù),就會(huì)發(fā)現(xiàn)JNI API不同。

2、C++版的helloworld共享庫(kù)提供了函數(shù)映射表。前文《

Android JNI開發(fā)入門之一》也已經(jīng)提到,JNI API為了避免丑陋的函數(shù)名,提供了方法向Java虛擬機(jī)注冊(cè)函數(shù)映射表。這樣當(dāng)Java調(diào)用Native接口的時(shí)候,Java虛擬機(jī)就可以不用根據(jù)函數(shù)名來(lái)決定調(diào)用哪個(gè)函數(shù)了,直接通過(guò)查詢表格就可以找到需要調(diào)用的函數(shù)了。

3、我們注意到RegisterNatives第一個(gè)參數(shù)(C語(yǔ)言接口中是第二個(gè)參數(shù))為調(diào)用該函數(shù)的Java類。這也和標(biāo)準(zhǔn)JNI函數(shù)名包含類名(包名和類名)的作用一樣——聲明那個(gè)Java類可以調(diào)用這個(gè)方法。

4、函數(shù)映射表的定義非常的怪異。你可以參考

Android JNI 使用的數(shù)據(jù)結(jié)構(gòu)JNINativeMethod詳解JNI標(biāo)準(zhǔn)手冊(cè)相關(guān)類型的部分。

 

通過(guò)對(duì)比你會(huì)發(fā)現(xiàn)C++的實(shí)現(xiàn)同樣功能的共享庫(kù)比C加入更多的代碼,另外你可能會(huì)有疑問(wèn)既然Java虛擬機(jī)能用通過(guò)函數(shù)名訪問(wèn)到相應(yīng)的Native code函數(shù),為什么還要提供注冊(cè)映射函數(shù)表呢?沒(méi)錯(cuò)!作為一個(gè)HelloWorld程序,確實(shí)簡(jiǎn)單為第一要?jiǎng)?wù)!如果Java虛擬機(jī)能用函數(shù)名能訪問(wèn)到相應(yīng)的函數(shù)的話,我是不會(huì)多此一舉來(lái)注冊(cè)映射函數(shù)表。在實(shí)踐中我發(fā)現(xiàn):

標(biāo)準(zhǔn)JNI不能通過(guò)標(biāo)準(zhǔn)函數(shù)名找到C++實(shí)現(xiàn)的Helloworld共享庫(kù)中的函數(shù),但是C實(shí)現(xiàn)的helloworld共享沒(méi)有這個(gè)問(wèn)題。我不知道為什么會(huì)這樣,請(qǐng)達(dá)人指教。沒(méi)有辦法才提供注冊(cè)映射函數(shù)表。

下面提供一個(gè)helloworld共享庫(kù)的Makefile——Android.mk:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=com_simon_Helloworld.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_MODULE := libhelloworld
LOCAL_SHARED_LIBRARIES := libutils
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)

和前文《Android JNI開發(fā)入門之一》的Android.mk文件相比也就是修改了一下源文件,沒(méi)有什么可說(shuō)。編譯生成libhelloworld.so文件,允許前文HelloWorld Android應(yīng)用程序,你將會(huì)得到和前文相同的結(jié)果。

JNI的進(jìn)一步學(xué)習(xí)

通過(guò)上面的例子我們已經(jīng)初步掌握了Android編寫JNI程序的方法。這也只能算是Android JNI入門而已,有很多JNI相關(guān)的內(nèi)容我們?cè)诶又胁](méi)有涉及到,比如:

1、我們并沒(méi)有提到怎樣在Native代碼中回調(diào)Java的函數(shù)。

2、每個(gè)Native的函數(shù)中前兩個(gè)參數(shù)是什么意思?

如果想用JNI進(jìn)行Android應(yīng)用開發(fā)我們需要更深入的學(xué)習(xí)。為了大家共同進(jìn)步,我這里也可以提供一些相關(guān)的資料和方法。

如果我們想深入學(xué)習(xí)JNI首先要先熟悉標(biāo)準(zhǔn)的JNI。推薦大家學(xué)習(xí)《Java Native Interface: Programmer’s Guide and Specification》,權(quán)威的標(biāo)準(zhǔn)JNI學(xué)習(xí)文檔。

前文提到Google沒(méi)有Android JNI編程提供文檔,但是在網(wǎng)上Simon也找到了一篇非常好的文檔供大家參考——JNI Examples for Android。這篇文章中舉了一個(gè)例子包含了Android JNI開發(fā)的方方面面,想深入學(xué)習(xí)Android JNI開發(fā)的朋友請(qǐng)仔細(xì)研讀。

總結(jié)

俗話說(shuō)得好“問(wèn)道有先后,如是而已”,Simon也是剛剛才開始學(xué)習(xí)Android JNI編程,對(duì)JNI的理解上面難免有一些地方有錯(cuò)誤,歡迎朋友們指正。

參考資料:

Android JNI 使用的數(shù)據(jù)結(jié)構(gòu)JNINativeMethod詳解

Android JNI實(shí)例

JNI Examples for Android

How to add a new module to Android

Android JNI(實(shí)現(xiàn)自己的JNI_OnLoad函數(shù))

Android中JNI編程的那些事兒

Java Native Interface: Programmer’s Guide and Specification

Java Native Interface Specification

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    午夜福利大片亚洲一区| 中文字幕日韩无套内射| 国产一级片内射视频免费播放| 好吊妞视频这里有精品| 91日韩欧美国产视频| 好吊一区二区三区在线看| 美女被草的视频在线观看| 国产欧美一区二区色综合| 欧美午夜一区二区福利视频| 精品一区二区三区不卡少妇av| 日本欧美一区二区三区就| 国产福利一区二区久久| 午夜视频免费观看成人| 国产在线一区二区三区不卡| 久久国产亚洲精品赲碰热| 日本欧美一区二区三区就| 富婆又大又白又丰满又紧又硬| 欧美国产日本免费不卡| 免费在线成人午夜视频 | 黄色日韩欧美在线观看| 欧美一区二区三区高潮菊竹| 午夜福利大片亚洲一区| 女人高潮被爽到呻吟在线观看| 中文字幕亚洲在线一区| 国产亚洲欧美另类久久久| 91精品国产综合久久精品| 欧美日韩国产的另类视频| 91日韩在线观看你懂的| 国产日韩欧美专区一区| 爽到高潮嗷嗷叫之在现观看| 国产日韩欧美在线播放| 亚洲欧洲一区二区中文字幕| 欧美精品亚洲精品一区| 色播五月激情五月婷婷| 精品人妻一区二区三区四在线| 亚洲av秘片一区二区三区| 国产视频福利一区二区| 国产偷拍盗摄一区二区| 国产精品激情对白一区二区| 精品国产av一区二区三区不卡蜜| 日本妇女高清一区二区三区|