Вызов 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);
Другие вопросы по тегам