android jni 调用java对象_Android NDK开发之Jni调用Java对象
本地代碼中使用Java對(duì)象
通過(guò)使用合適的JNI函數(shù),你可以創(chuàng)建Java對(duì)象,get、set 靜態(tài)(static)和 實(shí)例(instance)的域,調(diào)用靜態(tài)(static)和實(shí)例(instance)函數(shù)。JNI通過(guò)ID識(shí)別域和方法,一個(gè)域或方法的ID是任何處理域和方法的函數(shù)的必須參數(shù)。
下表列出了用以得到靜態(tài)(static)和實(shí)例(instance)的域與方法的JNI函數(shù)。每個(gè)函數(shù)接受(作為參數(shù))域或方法的類(lèi),它們的名稱(chēng),符號(hào)和它們對(duì)應(yīng)返回的jfieldID或jmethodID。
函數(shù)
描述
GetFieldID
得到一個(gè)實(shí)例的域的ID
GetStaticFieldID
得到一個(gè)靜態(tài)的域的ID
GetMethodID
得到一個(gè)實(shí)例的方法的ID
GetStaticMethodID
得到一個(gè)靜態(tài)方法的ID
構(gòu)造一個(gè)Java對(duì)象的實(shí)例
C代碼??
jclass?cls?=?(*env)->FindClass(env,?"Lpackagename/classname;");??//創(chuàng)建一個(gè)class的引用
jmethodID?id?=?(*env)->GetMethodID(env,?cls,?"",?"(D)V");??//注意這里方法的名稱(chēng)是"",它表示這是一個(gè)構(gòu)造函數(shù),而且構(gòu)造參數(shù)是double型的
jobject?obj?=?(*env)->NewObjectA(env,?cls,?id,?args);??//獲得一實(shí)例,args是構(gòu)造函數(shù)的參數(shù),它是一個(gè)jvalue*類(lèi)型。
首先是獲得一個(gè)Java類(lèi)的class引用?(*env)->FindClass(env, "Lpackagename/classname;"); ?請(qǐng)注意參數(shù):Lpackagename/classname;,L代表這是在描述一個(gè)對(duì)象類(lèi)型,packagename/classname是該對(duì)象耳朵class路徑,請(qǐng)注意一定要以分號(hào)(;)結(jié)束!
然后是獲取函數(shù)的id,jmethodID id = env->GetMethodID(cls, "", "(D)V");? 第一個(gè)是剛剛獲得的class引用,第二個(gè)是方法的名稱(chēng),最后一個(gè)就是方法的簽名了
還是不懂?我曾經(jīng)如此,請(qǐng)接著看...
難理解的函數(shù)簽名
JNINativeMethod的定義如下:
typedef struct{const char*name;const char*signature;void*fnPtr;
} JNINativeMethod;
第一個(gè)變量name是Java中函數(shù)的名字。
第二個(gè)變量signature,用字符串是描述了函數(shù)的參數(shù)和返回值
第三個(gè)變量fnPtr是函數(shù)指針,指向C函數(shù)。
其中比較難以理解的是第二個(gè)參數(shù),例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
實(shí)際上這些字符是與函數(shù)的參數(shù)類(lèi)型一一對(duì)應(yīng)的。
"()" 中的字符表示參數(shù),后面的則代表返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);
那其他情況呢?請(qǐng)查看下表:
類(lèi)型
符號(hào)
boolean
Z
byte
B
char
C
short
S
int
I
long
L
float
F
double
D
void
V
object對(duì)象
LClassName; ? ? ?L類(lèi)名;
Arrays
[array-type ? ? ? ?[數(shù)組類(lèi)型
methods方法
(argument-types)return-type ? ? (參數(shù)類(lèi)型)返回類(lèi)型
稍稍補(bǔ)充一下:
1、方法參數(shù)或者返回值為java中的對(duì)象時(shí),簽名中必須以“L”加上其路徑,不過(guò)此路徑必須以“/”分開(kāi),自定義的對(duì)象也使用本規(guī)則
比如說(shuō) java.lang.String為“java/lang/String”,com.nedu.jni.helloword.Student為"Lcom /nedu/jni/helloword/Student;"
2、方法參數(shù)或者返回值為數(shù)組類(lèi)型時(shí),請(qǐng)前加上[
例如[I表示 int[],[[[D表示 double[][][],即幾維數(shù)組就加幾個(gè)[
在本地方法中調(diào)用Java對(duì)象的方法
1、獲取你需要訪問(wèn)的Java對(duì)象的類(lèi):
jclass cls = (*env)->GetObjectClass(env, obj); //使用GetObjectClass方法獲取obj對(duì)應(yīng)的jclass。
jclass cls = (*env)->FindClass(“android/util/log”) //直接搜索類(lèi)名,需要是static修飾的類(lèi)。
2、獲取MethodID:
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); //GetStaticMethodID(…),獲取靜態(tài)方法的ID使用GetMethdoID方法獲取你要使用的方法的MethdoID
使用CallVoidMethod方法調(diào)用方法。參數(shù)的意義:
env-->JNIEnv
obj-->通過(guò)本地方法穿過(guò)來(lái)的jobject
mid-->要調(diào)用的MethodID(即第二步獲得的MethodID)
depth-->方法需要的參數(shù)(對(duì)應(yīng)方法的需求,添加相應(yīng)的參數(shù))
注:這里使用的是CallVoidMethod方法調(diào)用,因?yàn)闆](méi)有返回值,如果有返回值的話使用對(duì)應(yīng)的方法,在后面會(huì)提到。
CallVoidMethod CallStaticVoidMethod
CallIntMethod CallStaticVoidMethod
CallBooleanMethod CallStaticVoidMethod
CallByteMethod CallStaticVoidMethod
現(xiàn)在稍稍明白文章開(kāi)始構(gòu)造Java對(duì)象那個(gè)實(shí)例了吧?讓我們繼續(xù)深入一下:
Jni操作Java的String對(duì)象
從java程序中傳過(guò)去的String對(duì)象在本地方法中對(duì)應(yīng)的是jstring類(lèi)型,jstring類(lèi)型和c中的char*不同,所以如果你直接當(dāng)做char*使用的話,就會(huì)出錯(cuò)。因此在使用之前需要將jstring轉(zhuǎn)換成為c/c++中的char*,這里使用JNIEnv提供的方法轉(zhuǎn)換。
const char *str = (*env)->GetStringUTFChars(env, jstr, 0);
(*env)->ReleaseStringUTFChars(env, jstr, str);
這里使用GetStringUTFChars方法將傳進(jìn)來(lái)的prompt(jstring類(lèi)型)轉(zhuǎn)換成為UTF-8的格式,就能夠在本地方法中使用了。
注意:在使用完你所轉(zhuǎn)換之后的對(duì)象之后,需要顯示調(diào)用ReleaseStringUTFChars方法,讓JVM釋放轉(zhuǎn)換成UTF-8的string的對(duì)象的空間,如果不顯示的調(diào)用的話,JVM中會(huì)一直保存該對(duì)象,不會(huì)被垃圾回收器回收,因此就會(huì)導(dǎo)致內(nèi)存溢出。
下面是Jni訪問(wèn)String對(duì)象的一些方法:
GetStringUTFChars ? ? ? ? ?將jstring轉(zhuǎn)換成為UTF-8格式的char*
GetStringChars ? ? ? ? ? ? ? 將jstring轉(zhuǎn)換成為Unicode格式的char*
ReleaseStringUTFChars ? ?釋放指向UTF-8格式的char*的指針
ReleaseStringChars ? ? ? ? 釋放指向Unicode格式的char*的指針
NewStringUTF ? ? ? ? ? ? ? 創(chuàng)建一個(gè)UTF-8格式的String對(duì)象
NewString ? ? ? ? ? ? ? ? ? ?創(chuàng)建一個(gè)Unicode格式的String對(duì)象
GetStringUTFLength ? ? ?獲取UTF-8格式的char*的長(zhǎng)度
GetStringLength ? ? ? ? ? 獲取Unicode格式的char*的長(zhǎng)度
下面提供兩個(gè)String對(duì)象和char*互轉(zhuǎn)的方法:
/* c/c++ string turn to java jstring */
jstring charToJstring(JNIEnv* env, const char* pat)
{
jclass strClass = (*env)->FindClass(env, "java/lang/String");
jmethodID ctorID = (*env)->GetMethodID(env, strClass, "", "([BLjava/lang/String;)V");
jbyteArray bytes = (*env)->NewByteArray(env, strlen(pat));
(*env)->SetByteArrayRegion(env, bytes, 0, strlen(pat), (jbyte*)pat);
jstring encoding = (*env)->NewStringUTF(env, "UTF-8");
return (jstring)(*env)->NewObject(env, strClass, ctorID, bytes, encoding);
}
/* java jstring turn to c/c++ char* */
char* jstringToChar(JNIEnv* env, jstring jstr)
{
char* pStr = NULL;
jclass jstrObj = (*env)->FindClass(env, "java/lang/String");
jstring encode = (*env)->NewStringUTF(env, "utf-8");
jmethodID methodId = (*env)->GetMethodID(env, jstrObj, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode);
jsize strLen = (*env)->GetArrayLength(env, byteArray);
jbyte *jBuf = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);
if (jBuf > 0)
{
pStr = (char*)malloc(strLen + 1);
if (!pStr)
{
return NULL;
}
memcpy(pStr, jBuf, strLen);
pStr[strLen] = 0;
}
env->ReleaseByteArrayElements(byteArray, jBuf, 0);
return pStr;
}
總結(jié)
以上是生活随笔為你收集整理的android jni 调用java对象_Android NDK开发之Jni调用Java对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java java.doc_使用 jav
- 下一篇: android sina oauth2.