【问题标题】:JNI / Android : call to non static method in Java from C++?JNI / Android:从 C++ 调用 Java 中的非静态方法?
【发布时间】:2013-08-22 08:15:57
【问题描述】:

我有以下 JNI 方法,它当前调用静态 Java 方法:

void bindToMarketBillingServiceJNI(const char *  inappID)
    {
        JniMethodInfo t;

        if (JniHelper::getStaticMethodInfo(t
            , "com/mycompany/games/js/TestsDemo"
            , "bindToMarketBillingService"
            , "(Ljava/lang/String;)V"))
        {
            jstring stringArg1;

            if (! inappID)
            {
                stringArg1 = t.env->NewStringUTF("1");
            }
            else
            {
                stringArg1 = t.env->NewStringUTF(inappID);
            }

            t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg1);

            t.env->DeleteLocalRef(stringArg1);
            t.env->DeleteLocalRef(t.classID);

        }
    }

这是我的 Java 方法:

public static void bindToMarketBillingService(final String mSku)
    {

// Some code....

}

一切正常。

但是现在,我想让我的 Java 方法成为非静态的。我以为我只需要改变:

  • JniHelper::getStaticMethodInfo 到 JniHelper::getMethodInfo
  • t.env->CallStaticVoidMethod 到 t.env->CallVoidMethod
  • 'public static void bindToMarketBillingService(final String mSku)' 到'public void bindToMarketBillingService(final String mSku)'

但是它崩溃了......(下面的崩溃日志)

有人知道如何解决这个问题吗?

谢谢!!

08-20 11:54:11.009: A/libc(9379): Fatal signal 11 (SIGSEGV) at 0x0c1f4072 (code=1)
08-20 11:54:11.109: D/dalvikvm(31592): GC_CONCURRENT freed 735K, 12% free 9743K/10951K, paused 4ms+7ms
08-20 11:54:11.184: D/dalvikvm(1976): GC_CONCURRENT freed 1720K, 35% free 28243K/43399K, paused 5ms+13ms
08-20 11:54:11.194: I/ApplicationPolicy(1976): getActualApplicationStateEnabled() : true
08-20 11:54:11.219: D/PJ_MainApplication(9698): onApplicationCreate -> Now
08-20 11:54:11.334: D/dalvikvm(31592): GC_CONCURRENT freed 273K, 9% free 9981K/10951K, paused 3ms+3ms
08-20 11:54:11.409: D/PJ_CrashManager(9698): registerHandler -> Current handler class = com.android.internal.os.RuntimeInit$UncaughtHandler
08-20 11:54:11.469: I/DEBUG(9331): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
08-20 11:54:11.469: I/DEBUG(9331): Build fingerprint: 'samsung/GT-I9100/GT-I9100:4.0.3/IML74K/XWLPG:user/release-keys'
08-20 11:54:11.469: I/DEBUG(9331): pid: 9379, tid: 9403  >>> com.audioguidia.games.js <<<
08-20 11:54:11.469: I/DEBUG(9331): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0c1f4072
08-20 11:54:11.474: I/DEBUG(9331):  r0 00000000  r1 10000000  r2 fffffffc  r3 4cbb9ef0
08-20 11:54:11.474: I/DEBUG(9331):  r4 00273f98  r5 4c7f7fc4  r6 51134ad4  r7 415077f8
08-20 11:54:11.474: I/DEBUG(9331):  r8 00000001  r9 0c1f4071  10 4cbb9ee4  fp 51134a58
08-20 11:54:11.474: I/DEBUG(9331):  ip ffffffec  sp 51134a58  lr 4096864d  pc 40968aac  cpsr 00000030
08-20 11:54:11.474: I/DEBUG(9331):  d0  0000000000000000  d1  3f80000000000000
08-20 11:54:11.474: I/DEBUG(9331):  d2  0000000000000000  d3  0000000000000000
08-20 11:54:11.474: I/DEBUG(9331):  d4  0000000000000000  d5  3f80000000000000
etc....

【问题讨论】:

  • 你在Java类中声明了新的非静态方法吗?您需要有一个对象引用才能调用非静态方法
  • 我只是将“public static void bindToMarketBillingService(final String mSku)”更改为“public void bindToMarketBillingService(final String mSku)”。我需要做其他事情吗?谢谢。
  • 是的,如 c.s.说,您需要将jobject 实例作为第一个参数传递给CallVoidMethod(**here**, jmethodId....)
  • 顺便获取java对象有什么困难吗?
  • 谢谢。如何创建此作业?抱歉,我是 JNI 的新手...

标签: java android c++ methods java-native-interface


【解决方案1】:

仅更改对 env 对象的调用是不够的。

首先,您的新 instance 方法应在 Java 类中声明,例如:public void myMethod(...)(即此处没有 static 关键字)。

其次,您需要一个 java 对象引用来调用实例方法,而不仅仅是类。即你会做类似的事情(请注意我使用的是 C 语法):

jmethodID midCallBack = (*env)->GetMethodID(env, thisClass, "myMethod", "()V");
if (NULL == midCallBack) return;

// Call back the method (which returns void), based on the Method ID
(*env)->CallVoidMethod(env, thisObj, midCallBack);

有关详细信息,请参阅this link“5.3 回调实例方法和静态方法”部分

【讨论】:

  • 谢谢。抱歉,我真的是 JNI 的新手!在我最初问题的具体代码中,我知道我必须用't.env'替换你的'env'变量。正确的 ?如何创建“thisClass”和“thisObj”变量?什么是“回调”? (我不需要回调,我只需要通过 JNI 从 C++ 触发我的 Java 方法)。如果您能准确地告诉我如何在最初的问题中修改代码,我将不胜感激。感谢您的支持。
  • Regis_AG,我认为这个问题需要更多的上下文!你可以这样做jclass jThatObjClass= jEnv-&gt;FindClass("com/package/thatobject");const char* ctorSignature = /*your object signature*/; jmethodID ctor = jEnv-&gt;GetMethodID(jThatObjClass,"&lt;init&gt;",ctorSignature);jobject thisObj = jEnv-&gt;NewObject(jThatObjClass, ctor, jYourObjectCtorArgs...),是的,但是这样做然后扔掉这个OBj会表明一些相当奇怪的设计。
【解决方案2】:

如果你想调用非静态方法,你必须创建该类的一个对象,然后只调用成员方法。代码如下所示

jmethodID constructor = env->GetMethodID(cls, "<init>", "()V"); //this is for defaul c-tor
jobject object = env->NewObject(cls, constructor);
//getting your method id
env->CallVoidMethod(object, methodId/*,your parameters*/); 

【讨论】:

  • 这让我省了很多挫折!谢谢:)
【解决方案3】:

我刚刚在java中创建了一个调用非静态方法的静态方法:

static public void startActivity() {
    try {
        Activity mother = QtNative.activity();
        Intent intent = new Intent(mother, MainActivity.class);
        mother.startActivity(intent);
    } catch (Exception e) {
        Log.e(msgTag, e.toString());
        e.printStackTrace();
    }
}

我是这样从 C++ 调用的:

void FacebookAndroid::startAndroidFacebook() {
QAndroidJniObject::callStaticMethod<void>("org.qtproject.example.MainActivity",
                                          "startFacebookActivity",
                                          "()V");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-24
    • 1970-01-01
    相关资源
    最近更新 更多