比较老的Cocos2d游戏在Android5.0的兼容问题.
有许多的Cocos2d游戏是在Android5.0之前开发的,把原来的游戏安装到Android5.0或更高版本的安卓机后发现会出现很多问题.
刚遇到时也是一筹莫展.大概只是知道Android5.0对jni要求更加的规范了.
而Cocos2d为我们封装了一个很好用的类JniHelper.所以自然想到问题可能出现在这里.
废话不多说.
直接把原Cocos2d中的 如图:
这三个文件修改下,问题就解决了!
代码如下:
1.JniHlper.h
#ifndef __ANDROID_JNI_HELPER_H__#define __ANDROID_JNI_HELPER_H__#include#include#include "CCPlatformMacros.h"
namespace cocos2d {
typedef struct JniMethodInfo_
{
JNIEnv * env;
jclass classID;
jmethodID methodID;
} JniMethodInfo;
class CC_DLL JniHelper
{
public:
static JavaVM* getJavaVM();
static void setJavaVM(JavaVM *javaVM);
static jclass getClassID(const char *className, JNIEnv *env=0);
static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static std::string jstring2string(jstring str);
private:
static JavaVM *m_psJavaVM;
};
}
#endif // __ANDROID_JNI_HELPER_H__
2.JniHlper.cpp
#include "JniHelper.h"#include#include#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)
{
JNIEnv *env = 0;
jboolean isCopy;
if (! getEnv(&env))
{
return 0;
}
const char* chars = env->GetStringUTFChars(jstr, &isCopy);
string ret(chars);
if (isCopy)
{
env->ReleaseStringUTFChars(jstr, chars);
}
return ret;
}
}
namespace cocos2d {
JavaVM* JniHelper::m_psJavaVM = NULL;
JavaVM* JniHelper::getJavaVM()
{
return m_psJavaVM;
}
void JniHelper::setJavaVM(JavaVM *javaVM)
{
m_psJavaVM = javaVM;
}
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);
}
}
3.Java_org_cocos2dx_lib_Cocos2dxHelper.cpp
#include#include#include#include#include "JniHelper.h"
#include "CCFileUtilsAndroid.h"
#include "android/asset_manager_jni.h"
#include "CCString.h"
#include "Java_org_cocos2dx_lib_Cocos2dxHelper.h"
#define LOG_TAG "Java_org_cocos2dx_lib_Cocos2dxHelper.cpp"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxHelper"
EditTextCallback s_pfEditTextCallback = NULL;
void* s_ctx = NULL;
using namespace cocos2d;
using namespace std;
string g_apkPath;
extern "C" {
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetApkPath(JNIEnv* env, jobject thiz, jstring apkPath) {
g_apkPath = JniHelper::jstring2string(apkPath);
}
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetContext(JNIEnv* env, jobject thiz, jobject context, jobject assetManager) {
//JniHelper::setClassLoaderFrom(context);
FileUtilsAndroid::setassetmanager(AAssetManager_fromJava(env, assetManager));
}
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetEditTextDialogResult(JNIEnv * env, jobject obj, jbyteArray text) {
jsize size = env->GetArrayLength(text);
if (size > 0) {
jbyte * data = (jbyte*)env->GetByteArrayElements(text, 0);
char* pBuf = (char*)malloc(size+1);
if (pBuf != NULL) {
memcpy(pBuf, data, size);
pBuf[size] = '\0';
// pass data to edittext's delegate
if (s_pfEditTextCallback) s_pfEditTextCallback(pBuf, s_ctx);
free(pBuf);
}
env->ReleaseByteArrayElements(text, data, 0);
} else {
if (s_pfEditTextCallback) s_pfEditTextCallback("", s_ctx);
}
}
}
const char * getApkPath() {
return g_apkPath.c_str();
}
void showDialogJNI(const char * pszMsg, const char * pszTitle) {
if (!pszMsg) {
return;
}
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "showDialog", "(Ljava/lang/String;Ljava/lang/String;)V")) {
jstring stringArg1;
if (!pszTitle) {
stringArg1 = t.env->NewStringUTF("");
} else {
stringArg1 = t.env->NewStringUTF(pszTitle);
}
jstring stringArg2 = t.env->NewStringUTF(pszMsg);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg1, stringArg2);
t.env->DeleteLocalRef(stringArg1);
t.env->DeleteLocalRef(stringArg2);
t.env->DeleteLocalRef(t.classID);
}
}
void showEditTextDialogJNI(const char* pszTitle, const char* pszMessage, int nInputMode, int nInputFlag, int nReturnType, int nMaxLength, EditTextCallback pfEditTextCallback, void* ctx) {
if (pszMessage == NULL) {
return;
}
s_pfEditTextCallback = pfEditTextCallback;
s_ctx = ctx;
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "showEditTextDialog", "(Ljava/lang/String;Ljava/lang/String;IIII)V")) {
jstring stringArg1;
if (!pszTitle) {
stringArg1 = t.env->NewStringUTF("");
} else {
stringArg1 = t.env->NewStringUTF(pszTitle);
}
jstring stringArg2 = t.env->NewStringUTF(pszMessage);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg1, stringArg2, nInputMode, nInputFlag, nReturnType, nMaxLength);
t.env->DeleteLocalRef(stringArg1);
t.env->DeleteLocalRef(stringArg2);
t.env->DeleteLocalRef(t.classID);
}
}
void terminateProcessJNI() {
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "terminateProcess", "()V")) {
t.env->CallStaticVoidMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
}
}
std::string getPackageNameJNI() {
JniMethodInfo t;
std::string ret("");
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getCocos2dxPackageName", "()Ljava/lang/String;")) {
jstring str = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
ret = JniHelper::jstring2string(str);
t.env->DeleteLocalRef(str);
}
return ret;
}
std::string getFileDirectoryJNI() {
JniMethodInfo t;
std::string ret("");
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getCocos2dxWritablePath", "()Ljava/lang/String;")) {
jstring str = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
ret = JniHelper::jstring2string(str);
t.env->DeleteLocalRef(str);
}
return ret;
}
std::string getCurrentLanguageJNI() {
JniMethodInfo t;
std::string ret("");
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getCurrentLanguage", "()Ljava/lang/String;")) {
jstring str = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
ret = JniHelper::jstring2string(str);
t.env->DeleteLocalRef(str);
}
return ret;
}
void enableAccelerometerJni() {
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "enableAccelerometer", "()V")) {
t.env->CallStaticVoidMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
}
}
void setAccelerometerIntervalJni(float interval) {
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setAccelerometerInterval", "(F)V")) {
t.env->CallStaticVoidMethod(t.classID, t.methodID, interval);
t.env->DeleteLocalRef(t.classID);
}
}
void disableAccelerometerJni() {
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "disableAccelerometer", "()V")) {
t.env->CallStaticVoidMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
}
}
// functions for UserDefault
bool getBoolForKeyJNI(const char* pKey, bool defaultValue)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getBoolForKey", "(Ljava/lang/String;Z)Z")) {
jstring stringArg = t.env->NewStringUTF(pKey);
jboolean ret = t.env->CallStaticBooleanMethod(t.classID, t.methodID, stringArg, defaultValue);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg);
return ret;
}
return defaultValue;
}
int getIntegerForKeyJNI(const char* pKey, int defaultValue)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getIntegerForKey", "(Ljava/lang/String;I)I")) {
jstring stringArg = t.env->NewStringUTF(pKey);
jint ret = t.env->CallStaticIntMethod(t.classID, t.methodID, stringArg, defaultValue);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg);
return ret;
}
return defaultValue;
}
float getFloatForKeyJNI(const char* pKey, float defaultValue)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getFloatForKey", "(Ljava/lang/String;F)F")) {
jstring stringArg = t.env->NewStringUTF(pKey);
jfloat ret = t.env->CallStaticFloatMethod(t.classID, t.methodID, stringArg, defaultValue);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg);
return ret;
}
return defaultValue;
}
double getDoubleForKeyJNI(const char* pKey, double defaultValue)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getDoubleForKey", "(Ljava/lang/String;D)D")) {
jstring stringArg = t.env->NewStringUTF(pKey);
jdouble ret = t.env->CallStaticDoubleMethod(t.classID, t.methodID, stringArg, defaultValue);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg);
return ret;
}
return defaultValue;
}
std::string getStringForKeyJNI(const char* pKey, const char* defaultValue)
{
JniMethodInfo t;
std::string ret("");
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getStringForKey", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;")) {
jstring stringArg1 = t.env->NewStringUTF(pKey);
jstring stringArg2 = t.env->NewStringUTF(defaultValue);
jstring str = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID, stringArg1, stringArg2);
ret = JniHelper::jstring2string(str);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg1);
t.env->DeleteLocalRef(stringArg2);
t.env->DeleteLocalRef(str);
return ret;
}
return defaultValue;
}
void setBoolForKeyJNI(const char* pKey, bool value)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setBoolForKey", "(Ljava/lang/String;Z)V")) {
jstring stringArg = t.env->NewStringUTF(pKey);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg, value);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg);
}
}
void setIntegerForKeyJNI(const char* pKey, int value)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setIntegerForKey", "(Ljava/lang/String;I)V")) {
jstring stringArg = t.env->NewStringUTF(pKey);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg, value);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg);
}
}
void setFloatForKeyJNI(const char* pKey, float value)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setFloatForKey", "(Ljava/lang/String;F)V")) {
jstring stringArg = t.env->NewStringUTF(pKey);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg, value);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg);
}
}
void setDoubleForKeyJNI(const char* pKey, double value)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setDoubleForKey", "(Ljava/lang/String;D)V")) {
jstring stringArg = t.env->NewStringUTF(pKey);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg, value);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg);
}
}
void setStringForKeyJNI(const char* pKey, const char* value)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setStringForKey", "(Ljava/lang/String;Ljava/lang/String;)V")) {
jstring stringArg1 = t.env->NewStringUTF(pKey);
jstring stringArg2 = t.env->NewStringUTF(value);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg1, stringArg2);
t.env->DeleteLocalRef(t.classID);
t.env->DeleteLocalRef(stringArg1);
t.env->DeleteLocalRef(stringArg2);
}
}