2012-03-05 3 views
4

私はCocos2Dxで小さなプロジェクトを開発していますが、Bluetooth機能を追加しようとしています。これは、主なアクティビティのAndroid APIへのアソシエーションにアクセスできるように非静的メソッドを呼び出すことを意味します。私が見たほとんどのものは、この手順に従うように指示しています。 - メインアクティビティのインスタンスを作成します(environment-> NewGlobalRefは私が使っているものです) - アクティビティからメソッドを取得して実行します(environment-> GetObjectClass )AndroidからJavaの非静的関数への適切な呼び出し方法(Cocos2Dxが混在している)

ここにコードがあります。 Javaでは、私たちは(などのonCreate、onResume、のような論理的なものを省略)は、次のを持っています。

public class TSP extends Cocos2dxActivity{ 
    public void CnxAttempt(){ 
     Log.e("TSP_BT","aTTEMPTING!"); 
    } 
} 

それだそれ!今のところ、機能が実行されたことを確認するログメッセージを表示するだけです。今、楽しい部分はC++です:

static JNIEnv* getJNIEnv(void){ 
    JNIEnv *env = 0; 

    // get jni environment 
    if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK){ 
     CCLog("Failed to get the environment using GetEnv()"); 
    } 

    if (gJavaVM->AttachCurrentThread(&env, 0) < 0){ 
     CCLog("Failed to get the environment using AttachCurrentThread()"); 
    } 

    return env; 
} 
typedef struct JniMethodInfo_{ 
     JNIEnv * env;  // The environment 
     jclass  classID; // classID 
     jmethodID methodID; // methodID 
    } JniMethodInfo;   // Struct that stores most of the important information to relate to Java code 

    static bool getMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode){ 
     jmethodID methodID = 0; 
     JNIEnv *pEnv = 0; 
     jobject methodObject = NULL; 

     bool bRet = false; 

     do { 
      pEnv = getJNIEnv(); 
      if (! pEnv){ 
       CCLog("getMethodInfo -- pEnv false"); 
       break; 
      } 

      jclass localRef = pEnv->FindClass("org/cocos2dx/tsp/TSP"); 
      if (localRef == NULL) { 
       CCLog("getMethodInfo -- localRefCls false"); 
       break; // exception thrown 
      } 

      gCallbackObject = pEnv->NewGlobalRef(localRef); 
      if (gCallbackObject == NULL){ 
       CCLog("getMethodInfo -- CallbackOBJ false"); 
       break; 
      } 

      jclass classID = pEnv->GetObjectClass(methodObject); 
      if (!classID){ 
       CCLog("getMethodInfo -- classID false"); 
       break; 
      } 

      methodID = pEnv->GetMethodID(classID, methodName, paramCode); 
      if (!methodID){ 
       CCLog("getMethodInfo -- methodID false"); 
       break; 
      } 
      methodinfo.classID = classID; 
      methodinfo.env = pEnv; 
      methodinfo.methodID = methodID; 
      CCLog("getMethodInfo -- methodinfo created"); 
      bRet = true; 
     } while(0); 

     return bRet; 
    } 

    void CnxAttempt(){ 
     JniMethodInfo methodInfo; // Creating a JniMethodInfo object to store all the data 

     if (! getMethodInfo(methodInfo, "CnxAttempt", "()V")){ 
      CCLog("getMethodInfo is FALSE :("); 
      return; 
     } 
     methodInfo.env->CallVoidMethod(methodObject,methodInfo.methodID); 
     methodInfo.env->DeleteLocalRef(methodInfo.classID); 
    } 

それだけです! C++でCnxAttemptを呼び出すと、Javaクラス内のメソッドを認識せず、それに到達できないためにBOOMになります... 誰かが私に手を差し伸べることはできますか?何かが明確でない場合は、私に知らせてください。ありがとうございました!

答えて

3

新しいグローバル参照を作成すると、は作成されません新しいオブジェクトを作成します。

ローカル参照は、ネイティブメソッド呼び出しの期間有効であり、ネイティブメソッドが返された後に自動的に解放されます。グローバル参照は、明示的に解放されるまで有効です。

非スタティックメソッドをオブジェクトに呼び出す場合は、オブジェクトをネイティブメソッド(存在する場合は、メインアクティビティは存在しないはずです)に渡すか、新しいオブジェクトを作成する必要がありますNewObject *関数を使用するか、またはいくつかのファクトリメソッドを呼び出します。

次に、オブジェクトのクラスオブジェクトを取得し、メソッドIDを取得してメソッドを呼び出します。

+0

返信いただきありがとうございます!私は実際にNewGlobalRef関数の使用をやめ、NewObjectを使い始めましたが、結果は同じです。主題とコードに関するいくつかのさらなる研究の後、私はこの例に従う定義の順序を変えることによって、非静的な関数に到達することができました:[link](http://coding.derkeiler.com /Archive/Java/comp.lang.java/2004-02/0570.html) 私が今直面しなければならないことは、メインアクティビティからの外部機能(Bluetoothなど)を使用すると、アプリがクラッシュする:( それは別の質問です...多分。 ありがとう! – ASM

関連する問題