CocosDenshion Crashes on Android

I met a problem in my project using cocos2d-1.0.1-x-0.9.2 API on Android platform.

Calling to any function such as preloadBackgroundMusic and playBackgroundMusic in SimpleAudioEngine will cause a crash.

I found that actually calling to any function in class SimpleAudioEngine will cause a crash just at the very line “env~~>CallStaticVoidMethod;" where the global variable classOfCocos2dxActivity is NULL.
The questionable code is here:
<pre>
static jmethodID getMethodID
{
jmethodID ret = 0;
// get jni environment and java class for Cocos2dxActivity
if &env, JNI_VERSION_1_4) != JNI_OK)
{
LOGD (“Failed to get the environment using GetEnv()”);
return 0;
}
if < 0)
{
LOGD (“Failed to get the environment using AttachCurrentThread()”);
return 0;
}
classOfCocos2dxActivity = env~~>FindClass(”org/cocos2dx/lib/Cocos2dxActivity");
if (! classOfCocos2dxActivity)
{
LOGD (“Failed to find class of org/cocos2dx/lib/Cocos2dxActivity”);
return 0;
}

if (env = 0)
{
ret = env~~>GetStaticMethodID;
env~~>DeleteLocalRef(classOfCocos2dxActivity);
// *************************************************************************************************
// this line will release classOfCocos2dxActivity, but later, classOfCocos2dxActivity will be used again in preloadBackgroundMusicJNI
// by the line “env->CallStaticVoidMethod(classOfCocos2dxActivity, preloadBackgroundMusicMethodID, stringArg);”
//*************************************************************************************************
}

if (! ret)
{
LOGD (“get method id of %s error”, methodName);
}

return ret;
}

void preloadBackgroundMusicJNI(const char *path) { // void playBackgroundMusic(String,boolean) jmethodID preloadBackgroundMusicMethodID = getMethodID("preloadBackgroundMusic", "(Ljava/lang/String;)V");
  if (preloadBackgroundMusicMethodID)
  {
    jstring stringArg = env->NewStringUTF(path);
    env->CallStaticVoidMethod(classOfCocos2dxActivity, preloadBackgroundMusicMethodID, stringArg);
    // ************************************************************************
    // above, classOfCocos2dxActivity is a NULL pointer which will cause crash in CallStaticVoidMethod
    // ************************************************************************
    env->DeleteLocalRef(stringArg);
  }
}

For now, I have to fix this problem by following steps:

static jmethodID getMethodID(const char *methodName, const char *paramCode)
{
  jmethodID ret = 0;

  // get jni environment and java class for Cocos2dxActivity
  if (gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
  {
    LOGD("Failed to get the environment using GetEnv()");
    return 0;
  }

  if (gJavaVM->AttachCurrentThread(&env, 0) < 0)
  {
    LOGD("Failed to get the environment using AttachCurrentThread()");
    return 0;
  }

  if (env == 0)
  { LOGD("Failed to get environment, env* = 0");  
    return 0;
  }

  // **************************************************************************************
  if (!classOfCocos2dxActivity) classOfCocos2dxActivity = env->FindClass("org/cocos2dx/lib/Cocos2dxActivity"); // fix #1
  // **************************************************************************************
  if (! classOfCocos2dxActivity)
  {
    LOGD("Failed to find class of org/cocos2dx/lib/Cocos2dxActivity");
    return 0;
  }

  ret = env->GetStaticMethodID(classOfCocos2dxActivity, methodName, paramCode);
  LOGD("SimpleAudioEngine just got methodID: %d", ret);

  //********************************************
  //env->DeleteLocalRef(classOfCocos2dxActivity);  // fix #2
  //********************************************  
  if (! ret)
  {
    LOGD("get method id of %s error", methodName);
  }

  return ret;
}

Did anybody meet the same problem?

Had you succeeded running the test case CocosDenshionTest?
I think you missing the java codes like HelloWord/android/src/org/cocos2dx/lib, they are part of engine on Android platform.

Hi, Minggo Zhang, thanks for replying!

I have all files you mentioned above in the PrjName/android/src/org/cocos2dx/lib package like this:

actually the app can successfully start up and run on Android if I don’t call any functions defined in SimpleAudioEngine.h.

However, I had successfully invoke java function preloadBackgroundMusic in Cocos2dxActivity.java by using JNIHelper:

  void aFunction()
  {
    JniMethodInfo t;
    JniHelper::getStaticMethodInfo(t
        , "org/cocos2dx/lib/Cocos2dxActivity"
        , "preloadBackgroundMusic"
        , "(Ljava/lang/String;)V");
    jstring jstr = t.env->NewStringUTF("res/bgm.mp3");
    t.env->CallStaticObjectMethod(t.classID, t.methodID, jstr);
    ...
  }

Then I switched to call SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic(“res/bgm.mp3”) but the java function preloadBackgroundMusic was not called and app crashed.

Today, I’m not sure I solved the problem, but the app runs well with SimpleAudioEngine on Android now by removing “env->DeleteLocalRef(classOfCocos2dxActivity);” in getMethodID and adding it into preloadBackgroundMusicJNI function.

CocosDenshionTest crash.
I have problem call CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic(“background-music-aac.wav”, true);

Me too, maybe this is a new bug…
CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic(
“hello.mp3”, true);

I am checking it.

I just run CocosDenshionTest, everything is ok.
The version of cocos2d-x is cocos2d-1.0.1-x-0.9.2, the device is g10.

The attachment is the modified file to replace CocosDenshion\android\jni\SimpleAudioEngineJni.cpp in my test(using cocos2d-1.0.1-x-0.9.2), which will help SimpleAudioEngine to run well on Android.

The modification solves my problem but I think there are some other ways…

BTW, the problem occurs on simulator of Android, I didn’t get an Android device in hand, so I haven’t test it on a real device yet.

I think you should test in real device. Simulator is not the same as real device, and it is slow.

Yes, yes, yes…
real Android device, I must get one…

Hi I got this problem today in real device! (Galaxy S2, Acer liquid, …)
And the solution YUAN gave fix the problem ^^
Thanks a lot!

What’s your version of cocos2d-x?
And which solution of YUAN did you use?