欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

使用NDK移植開源項目,JNI的使用技巧

系統 2145 0

jni 的介紹

? JNI是Java Native Interface的縮寫,中文為JAVA本地調用。從Java1.1開始,Java Native Interface(JNI)標準成為java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI一開始是為了本地已編譯語言,尤其是C和C++而設計的,但是它并不妨礙你使用其他語言,只要調用約定受支持就可以了。以下介紹Android 中如何使用jni移植開源庫的技巧.

?JNI日志輸出到Logcat中

#include <android/log.h>
#define LOG_TAG "===xcloud==="
#define LOGI(...)? android_log_print(ANDROID_LOG_INFO,LOG_TAG, VA_ARGS__)
#define LOGW(...)? android_log_print(ANDROID_LOG_WARN,LOG_TAG, VA_ARGS__)
#define LOGE(...)? android_log_print(ANDROID_LOG_ERROR,LOG_TAG, VA_ARGS__)

?

Android.mk文件添加編譯模塊:
LOCAL_LDLIBS=-lm -llog
使用方法:
LOGE("%s",test);

JNI調用Java方法

以調用String 的getBytes方法為例:
第一步:
jclass clsstring = (*env)->FindClass(env,"java/lang/String"); //找到Java String 類
第二步:
jstring strencode = (*env)->NewStringUTF(env,"utf-8");  //得到一個jstring 對象
第三步:
jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B"); //得到getBytes方法

?

第四步:
jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr, mid, strencode); //“jstr 為傳入的字符串”調用getBytes方法

第五步:
jsize alen = (*env)->GetArrayLength(env,barr); //得到數組長度

?

jstring 轉換 char*

char* test=(char*)(*env)->GetStringUTFChars(env,jstringVariable,NULL);

?

?

返回一個java對象數組

第一步:
jclass objectClass=(*env)->FindClass(env,"com/xuzhitech/xcloud/resource"); //找到對應的java 類(對象)
第二步:
jobjectArray array=(*env)->NewObjectArray(env,currentListCount,objectClass,NULL); //通過取到的java類(對象)創建一個指定固定大小的數組
第三步:
jfieldID _uri=(*env)->GetFieldID(env,objectClass,"uri","Ljava/lang/String;");//找到對象中的列
注意:在JNI中并未提供jstring 類型的對象,所以必須通過L指定包名找到該類,在有提供的類型中,可以直接使用該類型的大寫首字母(jlong 需使用J)
如jint 類型可以如此編寫:
jfieldID _vcr=(*env)->GetFieldID(env,objectClass,"is_vcr","I");對應的JNI提供類型可以參考如下  http://download.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html
第四步:
jmethodID jid = (*env)->GetMethodID(env,objectClass,"<init>","()V");//"<init>"代表可以訪問默認構造函數
jobject jobj=(*env)->NewObject(env,objectClass,jid); //通過第一步找到的jclass創建對應的對象

?

第五步:
(*env)->SetObjectField(env,jobj,_modtime,jmodtime); //為對象中的每一列賦值。注意:如果JNI有提供的數據類型,可按提供的類型為對象中的列賦值,
如:(*env)->SetIntField(env,jobj,_vcr,current->is_vcr);
第六步:
(*env)->SetObjectArrayElement(env,array,i,jobj);將對象設置進第二步聲明的數組中
DeleteLocalRef(env,jobj);//刪除引用對象

在JNI中循環讀取對象數組

?

for ?(i?=? 0 ?;i?<?currentListCount?;i++)?{
jobject?obj?=?(*env)->GetObjectArrayElement(env,array,i);
jstring?jstr=(*env)->GetObjectField(env,obj,_uri);
LOGE( " =====uri===%s==== " ,jstringtoChar(env,jstr));
}
上面使用到的jstringtoChar方法代碼:
/* *
*jstring?to?char
*/
char *?jstringtoChar(JNIEnv*?env,jstring?jstr){
char *?rtn?=?NULL;
jclass?clsstring?=?(*env)->FindClass(env, " java/lang/String " );
jstring?strencode?=?(*env)->NewStringUTF(env, " utf-8 " );
jmethodID?mid?=?(*env)->GetMethodID(env,clsstring,? " getBytes " ,? " (Ljava/lang/String;)[B " );
jbyteArray?barr=?(jbyteArray)(*env)->CallObjectMethod(env,jstr,?mid,?strencode);
jsize?alen?=?(*env)->GetArrayLength(env,barr);
jbyte*?ba?=?(*env)->GetByteArrayElements(env,barr,?JNI_FALSE);
if ?(alen?>? 0 )
{
rtn?=?( char *)malloc(alen?+? 1 );
memcpy(rtn,?ba,?alen);
rtn[alen]?=? 0 ;
}
(*env)->ReleaseByteArrayElements(env,barr,?ba,? 0 );
return ?rtn;

}?

?

cpp JNI與 c JNI的主要注意事項:

用C編寫jni文件,訪問JNI內置提供方法格式:
(*env)->SetObjectArrayElement(env,array,i,jobj);
用CPP編寫JNI文件,訪問JNI內置提供方法格式:
env->SetObjectArrayElement(array,i,jobj);
另外,使用CPP編寫的JNI代碼,在調用C語言編寫的庫的時候,要添加以下代碼,才可以正常使用(不然在鏈接的時候找不到相關接口:undefined reference.....):
ifdef __cplusplus
extern "C" {
#endif
... //引入的頭文件
#ifdef __cplusplus
}
#endif

?

其他用法幾乎一致。

?

JNI 使用Native注冊

按照上面的方法寫函數體,必須遵循JNI官方的一大堆標準進行方法的定義,有時候方法一多,不大好管理,也不利用查看,并且每次都要寫一大堆惡心的標準方法名也不是一件好事。對此JNI有一套可以通過Native 注冊的機制可以使用,以方便函數體的編寫。

?

以下是Android 調用JNI注冊Natives 的步驟:
第一步
聲明Java中要調用jni 的類路徑:
static const char *className="com/xuzhitech/xcloud/cadaver";
第二步
創建方法格式結構體:
struct JNINativeMethod {
const char* name;//method name?
const char* signature; //java method return value?
void* fnPtr;//c/c++ method?
} ;

第三步
使用結構體注冊需要供Android 調用的方法體:

static ?JNINativeMethod?methods[]?=?{
{ " StringTestOne " ,? " ()Ljava/lang/String; " ,?( void *)StringTestOne},
{ " executels " , " ()[Lcom/xuzhitech/xcloud/resource; " ,( void *)executels},
{ " getProgress " , " ()Lcom/xuzhitech/xcloud/fileProgress; " ,( void *)getProgress},
{ " getdownloadState " , " ()I " ,( void *)getdownloadState},
{ " changeExecutable " , " (Ljava/lang/String;Ljava/lang/String;)I " ,( void *)changeExecutable},
{ " Login " , " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I " ,( void *)Login},
{ " getCurrentListCount " , " ()I " ,( void *)getCurrentListCount},
{ " mkcol " , " (Ljava/lang/String;)I " ,( void *)mkcol},
{ " deleteFile " , " (Ljava/lang/String;)I " ,( void *)deleteFile},
{ " deleteCol " , " (Ljava/lang/String;)I " ,( void *)deleteCol},
{ " getFullUri " , " ()Ljava/lang/String; " ,( void *)getFullUri},
{ " cdCommand " , " (Ljava/lang/String;)I " ,( void *)cdCommand},
{ " logout " , " ()V " ,( void *)logout},
{ " doCopy " , " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I " ,( void *)doCopy},
{ " doMove " , " (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I " ,( void *)doMove},
{ " getFile " , " (Ljava/lang/String;Ljava/lang/String;)V " ,( void *)getFile},
{ " putFile " , " (Ljava/lang/String;Ljava/lang/String;)V " ,( void *)putFile},
{ " lock " , " (Ljava/lang/String;)I " ,( void *) lock },
{ " unlock " , " (Ljava/lang/String;Ljava/lang/String;)I " ,( void *)unlock},
{ " getToken " , " (Ljava/lang/String;)Ljava/lang/String; " ,( void *)getToken},
{ " isSetToken " , " (Ljava/lang/String;)I " ,( void *)isSetToken},

};?

第一個參數為:Java實現要調用的方法名稱
第二個參數為:該方法需要的返回值與方法參數,如->(方法參數)返回值,詳細使用參考如下:
具體的每一個字符的對應關系如下

字符 Java類型 C類型

V? void ? void
Z?jboolean?boolean
I?jint? int
J?jlong? long
D?jdouble? double
F?jfloat? float
B?jbyte? byte
C?jchar? char
S?jshort? short

?

數組則以"["開始,用兩個字符表示

?

[I?jintArray? int []
[F?jfloatArray? float []
[B?jbyteArray? byte []
[C?jcharArray? char []
[S?jshortArray? short []
[D?jdoubleArray? double []
[J?jlongArray? long []
[Z?jbooleanArray?boolean[]
也可返回任意java對象,如上代碼的()[Lcom/xuzhitech/xcloud/resource;代表一個不帶參數的方法,并且返回java類中的Lcom/xuzhitech/xcloud/resource;數組。'['代表數組的意思,'L'代表類的意思

?

第三個參數為,第一個參數需要映射的本地c/c++對應的函數指針方法。

第四步
在加載jni的時候指定JNI版本并且通過傳入進來的class路徑注冊Natives 方法

?

jint?JNI_OnLoad(JavaVM*?vm,? void *?reserved){ ?

jint?result?=?JNI_ERR;
JNIEnv*?env?=?NULL;
jclass?clazz;
int ?methodsLenght;
if ?((*vm)->GetEnv(vm,?( void **)?&env,?JNI_VERSION_1_4)?!=?JNI_OK)?{
LOGE( " ERROR:?GetEnv?failed\n " );
return ?JNI_ERR;
}
// ?assert(env?!=?NULL);?
clazz?=?(*env)->FindClass(env,className);
if ?(clazz?==?NULL)?{
LOGE( " Native?registration?unable?to?find?class?'%s' " ,?className);
return ?JNI_ERR;
}
methodsLenght?=? sizeof (methods)?/? sizeof (methods[ 0 ]);
if ?((*env)->RegisterNatives(env,clazz,?methods,?methodsLenght)?<? 0 )?{
LOGE( " RegisterNatives?failed?for?'%s' " ,?className);
return ?JNI_ERR;
}
// ?
result?=?JNI_VERSION_1_4;
return ?result;
}

?

?

注意,使用Natives注冊運行程序時,它會先檢測jni與java類使用jni 類的native 方法是否相對應與一致,即使你沒有使用到該 方法也會進行檢測。
第五步
通過上面的修改,c/c++編寫的jni 文件就可以不帶一大串標準名稱了,您可以像正常編寫c一樣編寫你的jni函數,如下:

/*
*move?file
*/
jint?doMove(JNIEnv*?env,jobject?thiz,jstring?jsrc,jstring?jdest,jstring?jrename){
char *?src=( char *)(*env)->GetStringUTFChars(env,jsrc,NULL);
char *?dest=( char *)(*env)->GetStringUTFChars(env,jdest,NULL);
char *?rename=( char *)(*env)->GetStringUTFChars(env,jrename,NULL);
int ?returnValue=multi_move(src,dest,rename);
// ?free(src);
(*env)->ReleaseStringUTFChars(env,jsrc,src);
// ?free(dest);
(*env)->ReleaseStringUTFChars(env,jdest,dest);
// ?free(rename);
(*env)->ReleaseStringUTFChars(env,jrename,rename);
return ?returnValue;
}

?

?注:

JNI的一些基本方法的使用都可以參考這個網站:http://docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/functions.html

使用NDK移植開源項目,JNI的使用技巧


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲欧美日韩在线 | 一区日韩 | 一级毛片视频免费 | 精品免费国产一区二区三区 | 国产色在线 | 欧美日韩精品在线观看 | 久草经典视频 | 毛片免费大全短视频 | 欧美激情综合网 | 久久久久久久久日本理论电影 | 久久99热久久精品23 | 久久国产精品一区二区 | 免费能直接在线观看黄的视频 | 久久一日本道色综合久久m 亚洲三级视频 | 日韩欧美视频在线 | 喷潮网站 | xnxx18日本| 天天躁夜夜躁很很躁麻豆 | 99久热国产精品视频尤物不卡 | 久久只有这里有精品 | 国产三级做爰在线观看∵ | 成在线人免费视频一区二区三区 | 天天干天天操 | 奇米视频777 | 午夜精品毛片 | 狠狠影视| 日韩电影一区 | 亚洲人成在线精品 | 黄色小视频在线观看 | 日本不卡一区 | 91精品一区二区综合在线 | 久久视屏这里只有精品6国产 | 一区二区视频在线 | 欧美精品 在线观看 | 亚欧成人中文字幕一区 | 亚洲欧美日韩精品久久 | 国内外成人免费视频 | 影音先锋资源av | 日本中文字幕一区 | 色花堂国产精品第一页 | 欧美成人午夜在线全部免费 |