2013-02-25 271 views
1

我想从jni类中调用一些非常简单的java函数用于cocos2dx项目。但我一直收到错误有时在一些重要的调用中无法使用GetEnv()获取环境,这会改变整个操作流程。无法使用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); 
} 

我使用JniHelper类从已被如下的cocos2d-x。

#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 

这工作有时,但我也有时得到上述错误。谁能告诉我如何解决这个问题。

+0

什么是你回来的时候'GetEnv'失败的实际错误代码('jint')功能引起的? – 2013-02-25 08:20:02

+0

getEnv(JNIEnv ** env)返回布尔值而不是jint – glo 2013-02-25 08:22:51

+1

那么,[文档](http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#GetEnv )似乎不同意。 – 2013-02-25 09:02:51

回答

1

错误是因为我是不是要求从主线程