BUG: Direcror->end() leads to Android killing process instead of finishing activity

Hi,
I’ve noticed that when calling “CCDirector::sharedDirector()->end();”
it kills the process instead of finishing the activity.
I don’t think this is the right way to handle this, so I’ve tried the following (Cocos2dxActivity.java):

    @Override
    protected void onStart() {
        super.onStart();             
        sCocos2dxActivity = this;         
    }

    @Override
    protected void onStop() {
        super.onStop();     
        sCocos2dxActivity = null;
    }

    static Cocos2dxActivity sCocos2dxActivity = null;

    public static void terminateProcess(){

        if (sCocos2dxActivity != null)
        {
            if (!sCocos2dxActivity.isFinishing())
            {
                sCocos2dxActivity.finish();
            }

            sCocos2dxActivity = null;
        }
        else        
        {
            // Fallbacks to killing the process  
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }

I know it is not a good thing to keep a static reference to the Activity, but I’m nullifying that reference when stopping.

This solution works, but I’ve noticed one problem, when finishing the activity and running the game on the second time,
my splash scene is stuck, like there is no timer count.

Anyone have any idea why this may happen, or is there a better way to implement a proper Activity finish?

Thanks,
Oren

In fact I am facing the same problem.
I have a native app in front of the game and I want to finish the cocos2d activity instead of killProcess, because I don’t want to restart the whole app.
Any suggestions?

Thanks!

You can use my code with the following addition:

    // run
    pDirector->runWithScene(pScene);

    // Hack to Fix Android resume
    CCDirector::sharedDirector()->resume();

It fixes the resume bug I was having.

I used your work around and fixed in cocos2d-x-1.x, thanks!
However, it don’t works on cocos2d-x-2.0.3.
Any idea to make it work?
Please help.
Thanks!

Oren Bengigi wrote:

You can use my code with the following addition:
>
[…]
>
It fixes the resume bug I was having.

I’m currently working on it.
I’ve just migrated to Cocos2d-x 2 and there are some differences so my previous code didn’t work well on it.
I got it to finish the activity but when resuming I get an error dialog.
If anyone found a fix please share.

I just found a workaround on it and hope the solution can help you:

  1. on cocos2dx\platform\android\CCApplication.cpp : 20 , comment CC_ASSERT(! sm_pSharedApplication);
  2. on your AppDelegate.cpp, add pDirector~~>init; before pDirector~~>setOpenGLView(CCEGLView::sharedOpenGLView());

the concept is ignore the error and re-init the CCDirector.

Thanks

Oren Bengigi wrote:

I’m currently working on it.
I’ve just migrated to Cocos2d-x 2 and there are some differences so my previous code didn’t work well on it.
I got it to finish the activity but when resuming I get an error dialog.
If anyone found a fix please share.

Yep, it is not a good method to finish a activity.
We will improve it.
Any good suggestions is appreciated.

Hi,

I implemented a JNI function, which returns a flag whether to close the app or handle back key custom way not. This is called on onKeyDown() function (where the back event is handled) and if it returns true, I will pass the onKeyDown() event to the super class (closing the application in android default way). Quite ugly but works. Prettier way would be to return a flag from handleKeyDown() native function, but as it is asynchronous can’t do that (and not brave enouqh to change it synchronous :)). What do you think?

I also noticed that the life-cycle management might not be correct. If the onDestroy() is called the native side is not released properly until the system kills the process. All the resources should be released in onDestroy() though?

Hi guys!
I’ve implemented a JNI function (using EasyNDK) to call activity finish()…!
It works, but the second time I launch the Cocos2dxActivity, the screen becomes black and nothing is showed!
I’m using Cocos 2.1.3…Do you have any solution?

Hi Guys, has anyone found a solution for this problem?

I have an Android App which, in a point of its life (the user chooses some options), launches the cocos2d-x Activity, but the problem you had (or still have) is happening… when Director::getInstance()->end() is called the android activity which launched the cocos2d-x part is closed also…

I did a lot of workaround but nothing is working… when I get that the android activity is not closed (changing android.os.Process.killProcess(android.os.Process.myPid()) in Cocos2dxHelper), the second time cocos Activity is launched the textures are all black…

Some help will be appreciated!!!

PS: I am using cocos2d-x v3.1.1

1 Like

http://stackoverflow.com/questions/6468126/every-activity-in-android-is-a-process-or-one-application-is-one-process

Anyone try it?

in AndroidManifest.xml, add this line
android:process=“org.cocos2dx.myprocess”

full setting as following

    <!-- Tell Cocos2dxActivity the name of our .so -->
    <meta-data android:name="android.app.lib_name"
              android:value="cocos2dcpp" />

    <activity android:name="org.cocos2dx.cpp.AppActivity"
        	  android:process="org.cocos2dx.myprocess"
              android:label="@string/app_name"
              android:screenOrientation="sensorLandscape"
              android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
              android:configChanges="orientation|screenSize">

        <intent-filter>
        </intent-filter>
    </activity>

Are there any plan on fixing this in 3.3?
My solution works well on Cocos2dx 2.2, you can see it in my game “Run Cow Run”.
So it should be simple to implement the same in 3.3.
Killing a process is not the recommended way to exit an app…

@zhangxm or maybe in 3.4?

@macbearchen your answer is best solution. Thanks

There is still no correct solution in 3.13.1 version. But killing process behavior leads to missing data. A lot of analytic tool relies on correct activity lifecycle. Actually we have 2 sec median session length on Facebook Analytics. It’s wrong cause onDestroy is never called. And it’s very important metric for our project.

I’ve tried to fix it but have no luck. I’ve replaced Director::getInstance->purgeDirector() code with _openGLView->end(); call only and have replaced “kill process” call to sActivity.finish(); After that I’ve added native method call nativeRelease() to Cocos2dxActivity#onDestroy. Inside nativeRelease I’ve called Director::getInstance()->reset(); and Director::getInstance()->release(); (I’ve pushed them to public before). Releasing and lifecycle goes ok (Facebook gets right data metrics), but the following app starting have wrong rendering. It’s turns to white and black sprites with odd artefacts. I’ve tries to investigate whats goes worng. I’ve used few “stupid” methods. First - I’ve added PoolManager::getInstance()->getCurrentPool()->clear(); to nativeRelease after all Dirctor stuff just to check if there is any missing refernces and I’ve got error message “call to OpenGL ES API with no current context (logged once per thread)”. Secong - I’ve added mGLSurfaceView.setPreserveEGLContextOnPause(false); to check if GL context is used after onPause call and I’ve got SIGSEGV error (yes, it still used). So, my thought is that the root cause of black and white sprites is old openGL context or wrong openGL context reinitialization then the app started again.

It would be nice if someone can help to fix the relation between the new renderer and openGL context. Cause I’m in stuck, but I want to fix it.

In android onDestroy call kill process after your analytics stuff is done.

No. Cause analytic tools usually rely on Application.ActivityLifecycleCallbacks#onActivityDestroyed(Activity activity) that called after onDestroy call is done.

Has the problem been solved @zhangxm

Currently, if destroy the activity without free c++ memories will cause memory leak.