2013-08-20 54 views
3

我有以下JNI方法目前調用靜態Java方法:JNI/Android:從C++調用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
  • 「公共靜態無效bindToMarketBillingService(終字符串MSKU)」到‘公共無效bindToMarketBillingService(最後絃樂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.... 
+0

你聲明Java類中的新的非靜態方法?你需要有一個對象引用來調用非靜態方法 –

+0

我簡單地將'public static void bindToMarketBillingService(final String mSku)'改爲'public void bindToMarketBillingService(final String mSku)'。我需要做其他事嗎?謝謝。 –

+0

是作爲c.s.說,你需要將'jobject'實例作爲第一個參數傳遞給'CallVoidMethod(** here **,jmethodId ....)' – Tom

回答

6

改變只是env對象上調用是不夠的。

首先您的新實例方法應該在Java類中聲明,如:public void myMethod(...)(即沒有0​​關鍵字在這裏)。

其次,您需要一個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); 

見部分「5.3回調實例方法和靜態方法」this link瞭解更多信息

+0

謝謝。對不起,但我真的是JNI的新手!在我最初的問題的具體代碼中,我明白我必須用't.env'替換'env'變量。正確嗎?我如何創建'thisClass'和'thisObj'變量?什麼是「回撥」? (我不需要回調,我只需要通過JNI從C++中激發我的Java方法)。如果你能告訴我在我最初的問題中如何修改代碼,我將非常感激。感謝您的支持。 –

+1

Regis_AG,我認爲這個問題需要更多的上下文!你可以做'jclass jThatObjClass = jEnv-> FindClass(「com/package/thatobject」);','const char * ctorSignature =/*你的對象簽名* /; jmethodID ctor = jEnv-> GetMethodID(jThatObjClass,「」,ctorSignature);','jobject thisObj = jEnv-> NewObject(jThatObjClass,ctor,jYourObjectCtorArgs ...)',是的,但是這樣做然後只是扔掉thisOBj將表明一些相當奇怪的設計。 – Tom

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*/); 
+0

這爲我節省了很多挫折!謝謝 :) –

0

我只是做了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"); 
} 
相關問題