4

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

そして、これがコードです。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になります...誰かが私に手を貸してくれませんか?不明な点がある場合はお知らせください。よろしくお願いします!!

4

1 に答える 1

3

新しいグローバル参照を作成しても、新しいオブジェクトは作成されません。ローカル参照とグローバル参照の違い (ドキュメントから) は次のとおりです。

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

オブジェクトに対して非静的メソッドを呼び出したい場合は、オブジェクトをネイティブ メソッドに渡す必要があります (存在する場合 - メイン アクティビティは既に存在するべきではありませんか?)、NewObject* 関数を使用して新しいメソッドを作成します。または、ファクトリメソッドを呼び出すことによって。

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

于 2012-03-06T17:06:10.863 に答える