4

所以我正在使用 Cocos2Dx 开发一个小项目,但我正在尝试添加蓝牙功能,这意味着调用非静态方法能够访问 Main Activity 与 Android API 的关联。我所看到的几乎所有东西都告诉我要遵循这个过程: - 创建一个主要活动的实例(环境->NewGlobalRef 是我正在使用的) - 从活动中获取方法并执行它(环境-> GetObjectClass)

这是代码。在 java 中,我们有以下内容(省略了 onCreate、onResume 等逻辑内容):

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

就是这样!就目前而言,我只想显示一条 Log 消息,确认函数已执行。现在,有趣的部分是 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 时,它会发出 BOOM,因为它无法识别 Java 类中的方法并且无法访问它......有人可以帮帮我吗?如果有不清楚的地方,请告诉我。提前致谢!

4

1 回答 1

3

创建新的全局引用不会创建新对象。本地引用和全局引用(来自文档)之间的区别是:

本地引用在本地方法调用期间有效,并在本地方法返回后自动释放。全局引用在被显式释放之前一直有效。

如果你想调用一个对象的非静态方法,你需要将对象传递给本地方法(如果它存在 - 主要活动不应该已经存在吗?),使用 NewObject* 函数创建一个新的,或者通过调用一些工厂方法。

然后获取对象的类对象,获取methodID然后调用方法。

于 2012-03-06T17:06:10.863 回答