无法使用GetEnv()获取环境

Failed to get the environment using GetEnv()

本文关键字:获取 环境 GetEnv      更新时间:2023-10-16

我正试图从jni类中为cocos2dx项目调用一些非常简单的java函数。但我一直收到错误在某些重要调用上使用GetEnv((获取环境失败,这会改变整个操作流程。

我正在以以下方式拨打JNI电话

void SaveStringJni(const char *key, const char *value)
{
    cocos2d::JniMethodInfo methodInfo;
    if (! JniHelper::getStaticMethodInfo(methodInfo, CLASS_NAME, "SaveString", "(Ljava/lang/String;Ljava/lang/String;)V"))
    {
        return;
    }
    jstring stringArg = methodInfo.env->NewStringUTF(key);
    jstring stringArg2 = methodInfo.env->NewStringUTF(value);
    methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg, stringArg2);
    methodInfo.env->DeleteLocalRef(stringArg);
    methodInfo.env->DeleteLocalRef(stringArg2);
    methodInfo.env->DeleteLocalRef(methodInfo.classID);
}

我使用的是下面给出的cocos2d-x中的JniHelper类。

 #include "JniHelper.h"
#include <android/log.h>
#include <string.h>
#if 1
#define LOG_TAG "JniHelper"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#else
#define LOGD(...)
#endif
#define JAVAVM cocos2d::JniHelper::getJavaVM()
using namespace std;
extern "C"
{
//////////////////////////////////////////////////////////////////////////
// java vm helper function
//////////////////////////////////////////////////////////////////////////
static bool getEnv(JNIEnv **env)
{
    bool bRet = false;
    do
    {
        if (JAVAVM->GetEnv((void**)env, JNI_VERSION_1_4) != JNI_OK)
        {
            LOGD("Failed to get the environment using GetEnv()");
            break;
        }
        if (JAVAVM->AttachCurrentThread(env, 0) < 0)
        {
            LOGD("Failed to get the environment using AttachCurrentThread()");
            break;
        }
        bRet = true;
    } while (0);
    return bRet;
}
static jclass getClassID_(const char *className, JNIEnv *env)
{
    JNIEnv *pEnv = env;
    jclass ret = 0;
    do
    {
        if (! pEnv)
        {
            if (! getEnv(&pEnv))
            {
                break;
            }
        }
        ret = pEnv->FindClass(className);
        if (! ret)
        {
             LOGD("Failed to find class of %s", className);
            break;
        }
    } while (0);
    return ret;
}
static bool getStaticMethodInfo_(cocos2d::JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode)
{
    jmethodID methodID = 0;
    JNIEnv *pEnv = 0;
    bool bRet = false;
    do
    {
        if (! getEnv(&pEnv))
        {
            break;
        }
        jclass classID = getClassID_(className, pEnv);
        methodID = pEnv->GetStaticMethodID(classID, methodName, paramCode);
        if (! methodID)
        {
            LOGD("Failed to find static method id of %s", methodName);
            break;
        }
        methodinfo.classID = classID;
        methodinfo.env = pEnv;
        methodinfo.methodID = methodID;
        bRet = true;
    } while (0);
    return bRet;
}
    static bool getMethodInfo_(cocos2d::JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode)
    {
        jmethodID methodID = 0;
        JNIEnv *pEnv = 0;
        bool bRet = false;
        do
        {
            if (! getEnv(&pEnv))
            {
                break;
            }
            jclass classID = getClassID_(className, pEnv);
            methodID = pEnv->GetMethodID(classID, methodName, paramCode);
            if (! methodID)
            {
                LOGD("Failed to find method id of %s", methodName);
                break;
            }
            methodinfo.classID = classID;
            methodinfo.env = pEnv;
            methodinfo.methodID = methodID;
            bRet = true;
        } while (0);
        return bRet;
    }
    static string jstring2string_(jstring jstr)
    {
        if (jstr == NULL)
        {
            return "";
        }
        JNIEnv *env = 0;
        if (! getEnv(&env))
        {
            return 0;
        }
        const char* chars = env->GetStringUTFChars(jstr, NULL);
        string ret(chars);
        env->ReleaseStringUTFChars(jstr, chars);
        return ret;
    }
}
NS_CC_BEGIN
JavaVM* JniHelper::m_psJavaVM = NULL;
JavaVM* JniHelper::getJavaVM()
{
    return m_psJavaVM;
}
void JniHelper::setJavaVM(JavaVM *javaVM)
{
    m_psJavaVM = javaVM;
}
string JniHelper::m_externalAssetPath;
const char* JniHelper::getExternalAssetPath() {
    return m_externalAssetPath.c_str();
}
void JniHelper::setExternalAssetPath(const char * externalAssetPath) {
    m_externalAssetPath = externalAssetPath;
}
jclass JniHelper::getClassID(const char *className, JNIEnv *env)
{
    return getClassID_(className, env);
}
bool JniHelper::getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode)
{
    return getStaticMethodInfo_(methodinfo, className, methodName, paramCode);
}
bool JniHelper::getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode)
{
    return getMethodInfo_(methodinfo, className, methodName, paramCode);
}
string JniHelper::jstring2string(jstring str)
{
    return jstring2string_(str);
}
NS_CC_END

这有时有效,但我有时也会遇到上面提到的错误。有人能告诉我怎么解决这个问题吗。

错误是因为我没有从主线程调用函数