Java – Application crashes when switching from cocos2d-x activity to another activity on Android

Application crashes when switching from cocos2d-x activity to another activity on Android… here is a solution to the problem.

Application crashes when switching from cocos2d-x activity to another activity on Android

I’m working on an Android game using the Cocos2d-x game engine. The app is launched via the activity that cocos2d-x generated for me. What I want to do is start another activity that starts File Explorer using JNI calling the cocos Activity method, and then switches to the File Explorer activity using the Intent. However, the application crashes before the file browser opens.

The JNI calling code is as follows:

void MusicSelect::HandleYourMusicPressed(CCObject* sender)
{
    SimpleAudioEngine::sharedEngine()->playEffect("SFX/select.wav");

JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
    if (NULL == jvm)
        CCLog("Failed to get the JavaVM");

JNIEnv* env;
    jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
    if (ret != JNI_OK)
        CCLog("Failed to get then JNIEnv");

jclass classRet = env->FindClass("org/cocos2dx/extbeatanni/ExtremeBeatAnnihilation");
    if (!classRet)
        CCLog("Failed to find class ExtremeBeatAnnihilation");

jmethodID methodRet = env->GetMethodID(classRet, "startupFileExplore", "()V");
    if (!methodRet)
        CCLog("Failed to find method startupFileExplore");

env->CallVoidMethod(classRet, methodRet);
}

This is the

activity generated by Cocos2d-x, and startupFileExplore() is the function I added:

public class ExtremeBeatAnnihilation extends Cocos2dxActivity{

protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
    }

private void startupFileExplore()
    {
        Intent myIntent = new Intent(ExtremeBeatAnnihilation.this, FileExplore.class);
        System.out.println("Starting up the activity");
        startActivity(myIntent);
    }

static {
        System.loadLibrary("game");
    }
}

This is the compact file browser activity that shows the onCreate() method

public class FileExplore extends Activity {

 some class members defined here

@Override
    protected void onCreate(Bundle savedInstanceState) {
        System.out.println("Inside the onCreate()");
        super.onCreate(savedInstanceState);

loadFileList();

showDialog(DIALOG_LOAD_FILE);
        Log.d(TAG, path.getAbsolutePath());
    }

 some more methods that aren't necessarily relevant
}

Here is my AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.cocos2dx.extbeatanni"
    android:versionCode="1"
    android:versionName="1.0" >

<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="15" />

<uses-feature android:glEsVersion="0x00020000" />

<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name="org.cocos2dx.extbeatanni.ExtremeBeatAnnihilation"
            android:configChanges="orientation"
            android:label="@string/app_name"
            android:screenOrientation="landscape"
            android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="org.cocos2dx.extbeatanni.FileExplore"
            android:label="@string/app_name" >
        </activity>
    </application>

<supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true" />

</manifest>

When I run it and call the function with JNI code, I only see Starting up the activity get output in logcat, but I never see Inside onCreate( ) get output before crashing.

I looked up and tried a lot of things, but still couldn’t get into that. I think the cocos activity might be a weird thing. Questions like these are never what they seem. Please, does anyone know what happened, or what I did wrong? Thanks!

Edit:

As required, here is the logcat output. Thanks to Vikas Patidar’s comment, I was able to start seeing this paragraph error :

12-12 11:32:37.414: I/DEBUG(28509): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
12-12 11:32:37.414: I/DEBUG(28509): Build fingerprint: 'verizon_wwe/inc/inc:2.3.4/GRJ22/389630.15:user/release-keys'
12-12 11:32:37.414: I/DEBUG(28509): pid: 28510, tid: 28520  >>> org.cocos2dx.extbeatanni <<<
12-12 11:32:37.414: I/DEBUG(28509): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000042
12-12 11:32:37.414: I/DEBUG(28509):  r0 00000038  r1 00000002  r2 00000002  r3 00000002
12-12 11:32:37.414: I/DEBUG(28509):  r4 44e4754a  r5 44e5aee0  r6 44f5a780  r7 000020f8
12-12 11:32:37.414: I/DEBUG(28509):  r8 80018380  r9 44e4754a  10 44e5aecc  fp 800a73d4
12-12 11:32:37.414: I/DEBUG(28509):  ip 000000f8  sp 44f5a730  lr 8001c1ac  pc 8001d2a0  cpsr 00000010
12-12 11:32:37.414: I/DEBUG(28509):  d0  42156fb442156fe8  d1  42156e7c42156e6f
12-12 11:32:37.414: I/DEBUG(28509):  d2  42156ee442156e15  d3  42156f4c42156f42
12-12 11:32:37.414: I/DEBUG(28509):  d4  421e17e0421e17ac  d5  421e1848421e1814
12-12 11:32:37.414: I/DEBUG(28509):  d6  421e18b0421e187c  d7  421e1918421e18e4
12-12 11:32:37.414: I/DEBUG(28509):  d8  0000000000000000  d9  0000000000000000
12-12 11:32:37.414: I/DEBUG(28509):  d10 0000000000000000  d11 0000000000000000
12-12 11:32:37.414: I/DEBUG(28509):  d12 0000000000000000  d13 0000000000000000
12-12 11:32:37.414: I/DEBUG(28509):  d14 0000000000000000  d15 0000000000000000
12-12 11:32:37.414: I/DEBUG(28509):  d16 0000001040529e50  d17 3fdffffffddaaf00
12-12 11:32:37.414: I/DEBUG(28509):  d18 3fe0000000000000  d19 3fe000000112a880
12-12 11:32:37.414: I/DEBUG(28509):  d20 0000000000000000  d21 3f872e5c54a96637
12-12 11:32:37.414: I/DEBUG(28509):  d22 3e21e7c5992989f4  d23 bda8fae9be8838d4
12-12 11:32:37.414: I/DEBUG(28509):  d24 3fc74721cad6b0ed  d25 3fc39a09d078c69f
12-12 11:32:37.414: I/DEBUG(28509):  d26 0000000000000000  d27 0000000000000000
12-12 11:32:37.414: I/DEBUG(28509):  d28 0000000000000000  d29 0000000000000000
12-12 11:32:37.414: I/DEBUG(28509):  d30 0000000000000000  d31 0000000000000000
12-12 11:32:37.414: I/DEBUG(28509):  scr 80000012
12-12 11:32:37.454: I/DEBUG(28509):          #00  pc 0001d2a0  /system/lib/libdvm.so
12-12 11:32:37.454: I/DEBUG(28509):          #01  pc 000228ac  /system/lib/libdvm.so
12-12 11:32:37.454: I/DEBUG(28509):          #02  pc 000217a4  /system/lib/libdvm.so
12-12 11:32:37.454: I/DEBUG(28509):          #03  pc 00060b58  /system/lib/libdvm.so
12-12 11:32:37.454: I/DEBUG(28509):          #04  pc 0004cf86  /system/lib/libdvm.so
12-12 11:32:37.454: I/DEBUG(28509):          #05  pc 00149378  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.454: I/DEBUG(28509):          #06  pc 001493fa  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.464: I/DEBUG(28509):          #07  pc 001bb3e6  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.464: I/DEBUG(28509):          #08  pc 001bb45c  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.464: I/DEBUG(28509):          #09  pc 001b9ce6  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.464: I/DEBUG(28509):          #10  pc 001e4bf4  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.464: I/DEBUG(28509):          #11  pc 001e4e02  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.464: I/DEBUG(28509):          #12  pc 001c865c  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.464: I/DEBUG(28509):          #13  pc 001cb104  /data/data/org.cocos2dx.extbeatanni/lib/libgame.so
12-12 11:32:37.464: I/DEBUG(28509):          #14  pc 000181b4  /system/lib/libdvm.so
12-12 11:32:37.464: I/DEBUG(28509): code around pc:
12-12 11:32:37.464: I/DEBUG(28509): 8001d280 e2522001 e48a1004 1afffffb e1d030bc 
12-12 11:32:37.464: I/DEBUG(28509): 8001d290 ea00001c e1b02627 e245a014 e1d410b4 
12-12 11:32:37.464: I/DEBUG(28509): 8001d2a0 e1d090ba e1d030bc 0a000016 e2622005 
12-12 11:32:37.464: I/DEBUG(28509): 8001d2b0 e08ff202 eb0000c5 e207cc0f e795232c 
12-12 11:32:37.464: I/DEBUG(28509): 8001d2c0 e1a00000 e52a2004 e201ca0f e795252c 
12-12 11:32:37.464: I/DEBUG(28509): code around lr:
12-12 11:32:37.464: I/DEBUG(28509): 8001c18c e7952103 e3520000 0a000508 e5922000 
12-12 11:32:37.464: I/DEBUG(28509): 8001c19c e5922074 e5054008 e7920101 eb000439 
12-12 11:32:37.464: I/DEBUG(28509): 8001c1ac e320f000 e320f000 e320f000 e320f000 
12-12 11:32:37.464: I/DEBUG(28509): 8001c1bc e320f000 e1d430b4 e1d410b2 e7952103 
12-12 11:32:37.464: I/DEBUG(28509): 8001c1cc e3520000 0a0004f9 e5922000 e5922074 
12-12 11:32:37.464: I/DEBUG(28509): stack:
12-12 11:32:37.464: I/DEBUG(28509):     44f5a6f0  80018380  /system/lib/libdvm.so
12-12 11:32:37.464: I/DEBUG(28509):     44f5a6f4  0032a760  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a6f8  44e5ae4c  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a6fc  afd13795  /system/lib/libc.so
12-12 11:32:37.464: I/DEBUG(28509):     44f5a700  0032a760  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a704  80055c61  /system/lib/libdvm.so
12-12 11:32:37.464: I/DEBUG(28509):     44f5a708  4051f610  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a70c  00000000  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a710  00000000  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a714  44f5a788  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a718  4051f610  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a71c  80067bb7  /system/lib/libdvm.so
12-12 11:32:37.464: I/DEBUG(28509):     44f5a720  4271fbe0  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a724  44e5ae78  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a728  df002777  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a72c  e3a070ad  
12-12 11:32:37.464: I/DEBUG(28509): #00 44f5a730  00000004  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a734  44f5a780  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a738  00000001  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a73c  00334060  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a740  0032a768  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a744  000171a8  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a748  800acdc8  
12-12 11:32:37.464: I/DEBUG(28509):     44f5a74c  fffffe78  
12-12 11:32:37.474: I/DEBUG(28509):     44f5a750  800a73d4  
12-12 11:32:37.474: I/DEBUG(28509):     44f5a754  800228b0  /system/lib/libdvm.so
12-12 11:32:37.474: I/DEBUG(28509): #01 44f5a758  44f5a780  
12-12 11:32:37.474: I/DEBUG(28509):     44f5a75c  0032a760  
12-12 11:32:37.474: I/DEBUG(28509):     44f5a760  80022820  /system/lib/libdvm.so
12-12 11:32:37.474: I/DEBUG(28509):     44f5a764  42361bd0  
12-12 11:32:37.474: I/DEBUG(28509):     44f5a768  00000000  
12-12 11:32:37.474: I/DEBUG(28509):     44f5a76c  800217a8  /system/lib/libdvm.so

Solution

I figured out what caused the crash. In my JNI code env->CallVoidMethod(classRet, methodRet); line, I pass jclass to it, which points to the ExtremeBeatAnnihilation class. This shouldn’t be jclass. This should actually be a jobject that points to an instance of the currently running ExtremeBeatAnnihilation activity. Because I have this error, it’s calling methods in random instances instead of running instances, so trying to switch activities when not in a running activity causes it to crash.

Edit:

As requested, here’s the working code to switch the activity using a JNI call from native Android (this was modified from my code to be more generic, so please let me know if there is an error):

JNIEnv* env;

JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm)
    CCLog("Failed to get the JavaVM");

jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
if (ret != JNI_OK)
    CCLog("Failed to get then JNIEnv");

jclass myClass = env->FindClass("org/cocos2dx/extbeatanni/ExtremeBeatAnnihilation");
if (!myClass)
    CCLog("Failed to find class ExtremeBeatAnnihilation");

jmethodID getObjectMethod = env->GetStaticMethodID(myClass, "getObject", "()Ljava/lang/Object;" );
if(!getObjectMethod)
    CCLog("Failed to find method getObject");

jobject myInstance = env->CallStaticObjectMethod(myClass, getObjectMethod);
if(!myInstance)
    CCLog("Failed to get the current instance of the running activity");

jmethodID startupFileExploreMethod = env->GetMethodID(myClass, "startupFileExplore", "()V");
if (!startupFileExploreMethod)
    CCLog("Failed to find method startupFileExplore");

 call the java method within the ExtremeBeatAnnihilation activity that will start up file explore
env->CallNonvirtualVoidMethod(myInstance, myClass, startupFileExploreMethod);

Cocos2dxActivity code:

public class ExtremeBeatAnnihilation extends Cocos2dxActivity{

private static final int REQUEST_SONG_FILE = 0;    flag for file explore to return a selected song
    private static Object activity;                    current running instance of this activity
    private String selectedSong;                       song that was selected in the file explorer

 called on the startup of the game; will save the instance created to be returned later
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        activity = this;
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

 returns the currently running instance of this activity
    public static Object getObject()
    {
        Log.i("cppCall", "Returning activity");
        return activity;
    }

 starts the file explore activity to allow the user to choose a song on their SD card
    public void startupFileExplore()
    {
        try
        {
            Intent fileExploreIntent = new Intent(ExtremeBeatAnnihilation.this, FileExplore.class);

if(fileExploreIntent != null)
            {
                startActivityForResult(fileExploreIntent, REQUEST_SONG_FILE);
            }
            else 
            {
                Log.d("Extreme Beat Annihilation", "FileExploreIntent null\n");
            }
        }
        catch(Exception e)
        {
            Log.d("Extreme", "Error" + e.getMessage());
        }
    }

 returns the selected song
    public String getSelectedSong()
    {
        return selectedSong;
    }

 called when returning from the file explore; gets the selected song that was returned
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_SONG_FILE)
        {
            selectedSong = data.getStringExtra("Song File");
        }
    }

static {
        System.loadLibrary("game");
    }
}

Related Problems and Solutions