JNIEnv从monodroid应用程序中调用

时间:2012-08-10 12:23:52

标签: xamarin.android jnienv

这是我在monodroid应用程序中通过JNIEnv访问的Java类

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 个答案:

答案 0 :(得分: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);