This is the Java class i'm accessing through JNIEnv in my monodroid application
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;
}
}
I'm able to instantiate the class by the following statements:
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);
But when i try to create the object to access the getSelctd() method:
IntPtr ipApid = JNIEnv.GetMethodID(jclassWrp_, "getSelctd", "()Ljava/lang/String;");
It throws NoSuchMethodExist Exception... Please tell me whether i'm doing it the right way and what i'm missing here...
I'm able to instantiate the class by the following statements:
Java.Lang.Object jclassWrp_;
IntPtr JavaScriptInterface_Class = JNIEnv.FindClass("mypackage.JavaScriptInterface");
JNI use should use JNI conventions, thus mypackage/JavaScriptInterface
(note /
instead of .
).
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()
returns a local ref, not a global ref, so you want JniHandleOwnership.TransferLocalRef
.
But when i try to create the object to access the getSelctd() method:
IntPtr ipApid = JNIEnv.GetMethodID(jclassWrp_, "getSelctd", "()Ljava/lang/String;");
JNIEnv.GetMethodID()
takes a class handle, not an instance. Firstly, the above shouldn't compile (Java.Lang.Object
!= IntPtr
). Secondly, jclassWrp
contains a mypackage.JavaScriptInterface
instance, not the mypackage.JavaScriptInterface
Class instance.
Instead, do:
IntPtr ipApid = JNIEnv.GetMethodID(JavaScriptInterface_Class, "getSelctd", "()Ljava/lang/String;");
Finally, don't forget to JNIEnv.DeleteGlobalRef(JavaScriptInterface_Class)
when you don't need it anymore, otherwise you'll leak the gref.
Complete code:
// 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);