Вызов JNIEnv из приложения monodroid
Это класс Java, к которому я обращаюсь через JNIEnv в моем приложении для монодроида
package mypackage;
import android.util.Log;
public class JavaScriptInterface {
public String submitAns = "";
// The JNI in the original question uses a default constructor.
// Either provide one explicitly or use the implicit one...
public JavaScriptInterface()
{
}
public String getSelctd()
{
return submitAns;
}
}
Я могу создать экземпляр класса с помощью следующих утверждений:
Java.Lang.Object jclassWrp_;
IntPtr JavaScriptInterface_Class = JNIEnv.FindClass("mypackage.JavaScriptInterface");
IntPtr JavaScriptInterface_ctor = JNIEnv.GetMethodID(JavaScriptInterface_Class, "<init>", "()V"); //(Landroid/context/Context;)V
IntPtr jsInterfaceinstance_ = JNIEnv.NewObject(JavaScriptInterface_Class, JavaScriptInterface_ctor);
jclassWrp_ = new Java.Lang.Object(jsInterfaceinstance_, JniHandleOwnership.TransferGlobalRef);
Но когда я пытаюсь создать объект для доступа к методу getSelctd():
IntPtr ipApid = JNIEnv.GetMethodID(jclassWrp_, "getSelctd", "()Ljava/lang/String;");
Выдает исключение NoSuchMethodExist... Пожалуйста, скажите мне, правильно ли я делаю это, и чего мне здесь не хватает...
1 ответ
Я могу создать экземпляр класса с помощью следующих утверждений:
Java.Lang.Object jclassWrp_;
IntPtr JavaScriptInterface_Class = JNIEnv.FindClass("mypackage.JavaScriptInterface");
Использование JNI должно использовать соглашения JNI, таким образом mypackage/JavaScriptInterface
(нота /
вместо .
).
IntPtr JavaScriptInterface_ctor = JNIEnv.GetMethodID(JavaScriptInterface_Class, "<init>", "()V");
IntPtr jsInterfaceinstance_ = JNIEnv.NewObject(JavaScriptInterface_Class, JavaScriptInterface_ctor);
jclassWrp_ = new Java.Lang.Object(jsInterfaceinstance_, JniHandleOwnership.TransferGlobalRef);
JNIEnv.NewObject()
возвращает локальную ссылку, а не глобальную ссылку, так что вы хотите JniHandleOwnership.TransferLocalRef
,
Но когда я пытаюсь создать объект для доступа к методу getSelctd():
IntPtr ipApid = JNIEnv.GetMethodID(jclassWrp_, "getSelctd", "()Ljava/lang/String;");
JNIEnv.GetMethodID()
берет дескриптор класса, а не экземпляр. Во-первых, вышесказанное не должно компилироваться (Java.Lang.Object
знак равно IntPtr
). Во-вторых, jclassWrp
содержит mypackage.JavaScriptInterface
экземпляр, а не mypackage.JavaScriptInterface
Экземпляр класса.
Вместо этого сделайте:
IntPtr ipApid = JNIEnv.GetMethodID(JavaScriptInterface_Class, "getSelctd", "()Ljava/lang/String;");
Наконец, не забудьте JNIEnv.DeleteGlobalRef(JavaScriptInterface_Class)
когда вам это больше не нужно, иначе вы пропустите gref.
Полный код:
// FindClass() returns a gref; must be freed (see below)
IntPtr JavaScriptInterface_Class = JNIEnv.FindClass("mypackage/JavaScriptInterface");
// MethodIDs do not need to be freed
IntPtr JavaScriptInterface_ctor = JNIEnv.GetMethodID(JavaScriptInterface_Class,
"<init>", "()V");
IntPtr JavaScriptInterface_getSelctd = JNIEnv.GetMethodID(JavaScriptInterface_Class,
"getSelctd", "()Ljava/lang/String;");
// JNIEnv.NewObject() & JNIEnv.CallObjectMethod() return lrefs; freed below
IntPtr lrefInstance = JNIEnv.NewObject(JavaScriptInterface_Class,
JavaScriptInterface_ctor);
IntPtr lrefSelectd = JNIEnv.CallObjectMethod(jsInterfaceinstance_, ipApid);
// JniHandleOwnership.TransferLocalRef causes lrefSelectd to be released for us
string selected = JNIEnv.GetString(lrefSelectd, JniHandleOwnership.TransferLocalRef);
// Resource cleanup
JNIEnv.DeleteLocalRef(lrefInstance);
JNIEnv.DeleteGlobalRef(JavaScriptInterface_Class);