onCreate() after finish() in onStop()
Asked Answered
H

4

11

I have an Android activity that calls finish() inside it's onStop() so when I switch to other activities (including the main menu), the activity will be shut down. Up this point, everything works as expected.

However, when I run the application again, (sometimes, not always) I notice the application runs using the same PID as the previous and it calls onCreate() again. I didn't see any call to onRestart() so I assume that onCreate() call is performed straight after onStop(), which is something that violates the activity lifecyce. When the app uses a new PID, I can understand why onCreate() is called, that's because this is the beginning of the activity.

Anyone knows why this happen?

A bit about the app I am developing: This is a Unity + Vuforia + Android application. I create a custom activity because I need to create a native UI on Android (instead of from Unity).

I found a similar issue reported into the Android project: http://code.google.com/p/android/issues/detail?id=15331 but I am not sure if the cause is the same or not.

update: From what I see from the log, after the finish() call, there is no call to onDestroy(). However, if the problem I mentioned happens (the activity is started using the same process), there is a call to onDestroy() at the beginning of activity.

update: Sorry for the late update. Here I show an excerpt of the logcat.

## First run

I/ActivityManager(  265): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=the.app/the.app.UnityAriusActivity bnds=[238,115][351,273] } from pid 423
I/ActivityManager(  265): Start proc the.app for activity the.app/the.app.UnityAriusActivity: pid=1686 uid=10013 gids={3003, 1006, 1015}
D/arius   ( 1686): UnityAriusActivity: onStart
D/arius   ( 1686): UnityAriusActivity: onResume

## Home button is pressed

I/ActivityManager(  265): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.sonyericsson.home/.HomeActivity } from pid 265
D/arius   ( 1686): UnityAriusActivity: onPause
D/arius   ( 1686): UnityAriusActivity: onStop

## Second run

I/ActivityManager(  265): Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=the.app/the.app.UnityAriusActivity bnds=[238,115][351,273] } from pid 423

## Same process, onStart is called again

D/arius   ( 1686): UnityAriusActivity: onStart
D/arius   ( 1686): UnityAriusActivity: onResume
I/ActivityManager(  265): Displayed the.app/the.app.UnityAriusActivity: +500ms
D/Unity   ( 1686): Creating OpenGL ES 2.0 context (RGB16 565 16/0)
W/IInputConnectionWrapper(  423): showStatusIcon on inactive InputConnection
I/QCAR    ( 1686): onSurfaceCreated

## Strangely, there's an onDestroy here

D/arius   ( 1686): UnityAriusActivity: onDestroy

## Unity apparently kills the process from its onDestroy

I/Process ( 1686): Sending signal. PID: 1686 SIG: 9
I/ActivityManager(  265): Process the.app (pid 1686) has died.

The problem is that, there's an onDestroy() after onStart() on the second run. My activity is basically a subclass of Vuforia/QCAR activity which is also a subclass of activity from Unity. So, inside my onDestroy(), I make a call to the superclass' (super.onDestroy()) and also the same for the other methods that I override.

If I looked at the Unity and Vuforia/QCAR Android library (I was curious so I decompiled them -- yeah this may be not right), inside Unity's onDestroy(), Unity tries to kill its own process (which is the application process).

Process.killProcess(Process.myPid());

So, when this happens, my app just shut down again. If the second run uses different process, that strange onDestroy() does not happen.

I have also tried the noHistory approach. But the same thing still happens :( When the second run uses the same process, a late onDestroy() will appear and then the process is kill by Unity.

Hawes answered 19/6, 2012 at 10:34 Comment(6)
I also need to call finish() when the user presses the home button. That's why I'm calling it from onStop().Hawes
Any call to finish() will force onCreate to run again, since this will destroy the ActivityRiddance
What exactly is the problem here? That onDestroy() is not being called? Or that it is being called? The Activity Lifecycle seems to require that you handle both possibilities.Fen
Just a guess for the solution : keep all as it is, in Manifest file set that activity attribute android:launchMode="singleInstance" or try with singleTaskAppleby
If the application process is killed it should receive a new PID, so this clearly sounds like the bug. Have you tried to detect it with static field initialized in onCreate?Ram
It looks like your trying to follow a state machine like logic without proper handling of processes...Gley
F
12

You are making an understandable, but critical error in assuming that a new activity must run in a new process. That is not actually the case on android - you can have the onCreate() of a new activity instance occur in a process that has been kept around after hosting an earlier activity instance.

This can make anything that is static with respect to a process (especially, though not exclusively in native code) puzzlingly unreliable.

Because the activity that is being started is a new one, it will not receive an onRestart() - that would happen only if you were restarting an existing activity.

Fen answered 21/6, 2012 at 15:18 Comment(7)
So you say it's possible for a completely new activity (in regards to its lifecycle) to reuse previous process?Hawes
I just updated my question. When the activity is started again using the same process, I see a call to onDestroy() which is supposedly done after the finish() call. This is actually what I don't want to happen.Hawes
There is no guarantee that onDestroy() will happen, especially if the process is being disposed of - look at the killable column in the Activity Lifecycle diagram.Fen
Well.. if the activity finishes, it's fine if onDestroy() is not called. But not if it happens when the activity is started.Hawes
you could be seeing a configuration change cycleFen
This is what I have regarding the config change android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|fontScale" Unity uses them so I just use them as well.Hawes
Does that mean it's possible that onCreate() gets called even if onDestroy() hasn't been called (for the same activity)?Chladek
H
6

Why don't you just set noHistory="true" on the activity's manifest entry? Then you don't have to worry about manually finishing the activity in onStop().

Search for noHistory in http://developer.android.com/guide/topics/manifest/activity-element.html

Or, alternatively, set the FLAG_ACTIVITY_NO_HISTORY in your startActivity() intent. http://developer.android.com/reference/android/content/Intent.html#FLAG%5FACTIVITY%5FNO%5FHISTORY

Hectare answered 21/6, 2012 at 19:15 Comment(4)
@Hawes - I should have mentioned above that the way you're calling finish() in onStop() seems like a hack. Is there a good reason you aren't using a more platform-friendly way of preventing your activity from entering into the history stack?Hectare
I guess I do that because I didn't know about the noHistory option, I am relatively new in Android development :) Anyway.. I tried this and unfortunately I still see the problem :(Hawes
OK, back up a bit. You said you tried this. Which method did you try? I hope that you removed the finish() call from onStop() when you did this test, right? So what are the exact things that happen when you have noHistory set to true? Could you describe it like "Open Activity A. Open Activity B from A. Press Home. Open app from homescreen. Still see Activity B!"Hectare
Let me reemphasize that chasing the lifecycle and trying to bend the OS process handling to your will is going to end in a lot of frustration. There are better ways to ensure you don't return to the same activity you were just viewing when you leave an app.Hectare
R
3

In the documentation in your link, the description of onDestroy is :

The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.

While for onStop is:

Called when the activity is no longer visible to the user, because another activity has been resumed and is covering this one. This may happen either because a new activity is being started, an existing one is being brought in front of this one, or this one is being destroyed. Followed by either onRestart() if this activity is coming back to interact with the user, or onDestroy() if this activity is going away.

This means that finish() calls onDestroy not onStop, so when the activity is restarted, onCreate must be called, since your call to finish() inside onStop will force onDestroy to run.

Riddance answered 21/6, 2012 at 15:13 Comment(1)
Yes I understand this part. I want to end the activity when it's inactive (i.e. onStop()). That's why I call finish() inside onStop().Hawes
W
0

I'm running into a similar behavior: onDestroy strangely called after onCreate/onStart/onResume, when the activity is started. I don't have a definite confirmation, but my feeling is that the onDestroy call corresponds to the previous activity, not the new one. But for some reason, its execution is delayed until the process is reactivated again (when starting a new activity).

I believe this is due to calling "finish()" from onStop. I've noticed in my logs that the activity manager complains that activity reported to stop, but is not stopped anymore (it's actually finishing). So I'm wondering whether this messes up with the state the activity manager things my activity is in.

In your case, the end result is that the entire process is killed, due to the onDestroy call. As your new activity is started in the same process as the previous one, your app exits immediately.

Wauters answered 5/2, 2016 at 22:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.