Is it Possible to see whats happening in onPause of an Android Activity?
I want to know if the app is
closing, going to background or screen is switched off
or
activity is changed or Sub-Activity is closed
is there a way to get this information?
You can see what it happening in the pause by looking at what is written in onPause().
I think you meant to ask, "What happens to the activity after onPause?"
To put it another way, you can't tell what is happening to the activity in onPause because the things that happen to the activity are taken care of in other methods. You'll have to look at these other methods at runtime.
Put a breakpoint in onRestart(), if this is hit, you can be sure that your activity was never destroyed.
Put a breakpoint in onDestroy(), if the activity is being destroyed, this breakpoint will be hit.
Related
I'm developing a videogame in Android. For it, I'm using a game loop and all the typical stuff it envolves. I have a doubt about the states of the activity in android.
I need an activity to create the GLSurfaceView and so, the problem is the activity, when it finishes its onCreate method, continues this way: onCreate -> onResume -> onStart -> onStop.
I guess it goes throught those states because the activity doesn't have anything to do and it's the loop who is working. But I have a problem with this behaviour:
How can I know when the user "minimize" or put the device in a stand by state? Again, the methods onStop -> onResume -> onStart will trigger, but, how can I difference this time with the first?
I need to stop the loop when the user switch the device to stand by, but not when it starts the first time.
I hope I have explained well. Thanks.
If onStop is running immediately after onStart, something is wrong. The activity will only be placed in the Stopped state only when it is no longer visible to the user. Unless maybe your code immediately creates another activity that displaces it as the foreground activity, I guess, but if the activity is visible on the screen, onStop shouldn't be firing. Some code would be helpful in diagnosing that.
onPause occurs when the activity is still visible but there is another activity that is being resumed. If you're trying to save game data or something when the user backs out of the app, gets a phone call, turns off the screen, etc., I'd use onPause, because onStop is not guaranteed to be called and you run the risk in certain situations of the system killing your activity before you can do what you need to do.
For more info on activity lifecycle, see the Activities guide.
I have an activity that needs to turn on the screen when it is started (just in case the screen was off). So in my onCreate, I have:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
|WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
Using this straightforward combination, I am able to cause my activity to display whenever it is started from my background service (yes, this is a legitimate case).
The problem, however, is that there is a very strange lifecycle behavior when I start up my activity in such a case. Using extensive logging, I was able to figure out that the following 7-step process happens immediately after the activity is started:
onCreate
onStart
onResume
onPause
onStop
onStart
onResume
See that? For a simple activity start, onStart is called twice. And more importantly, onStop is mysteriously called, even though the activity was just started - and nothing happened that would cause it to stop.
I have tested this in many different scenarios and it appears that this strange behavior only happens when the screen is off and the activity is launched after it was destroyed. If the screen is on, or if the activity was stopped [but not yet destroyed] the activity launches normally, and onStart is only called once.
Bottom line: it appears that when my activity is launched and the screen is forced on, Android starts the activity, then stops it, and then starts it again for no apparent reason.
So: why is this happening? And is there anything I can do to workaround this (so that onStop isn't called until there is a legitimate cause for it to be)?
Notes:
The activity in question is using the singleTask launchmode
I have tried disabling the keyguard / lock but it has no effect
I am witnessing this behavior on a Samsung Galaxy Tab 10.1 running Android 3.2. I have not tested whether this applies to anything else...
I had a similar problem here:
Activity Lifecycle X Power Button X Lock Screen
The problem was that as my activity was forced landscape, when I turned on the screen it showed the lock screen in portrait and it was causing a configuration change and hence destroying the current activity.
The solution was to add a android:configChanges="orientation" on the Activity in my AndroidManifest.xml.
As suggested by #cyberhuman, the answer to this question OnPause and OnStop() called immediately after starting activity pointed me to the right direction.
My issue with the activity completing a full 'dummy' lifecycle before being actually displayed to the user was that my attempt to play the ringtone when the activity became visible was directly muted by the additional, subsequent "onStop()", and using flags to make the activity behave properly when launched when screen is off/when screen is locked/when screen is on/when activity is running in the background was not possible.
I finally solved my issue by overriding the onWindowFocusChanged(boolean hasFocus) method and launching the ringtone from there. Putting it here in case somebody has the same issue.
You could check for the situation in onStart, set a static or global variable, and then check the variable in onStop to override the standard behavior.
The Activity Lifecycle is giving me headaches.
The documentation at http://developer.android.com/reference/android/app/Activity.html is so darn ambiguous when it describes the concept of visibility, that I can't figure out when onStop() is called vs onPause().
Compare the following two statements from the documentation:
(taken from right beneath the lifecycle diagram)
The onStart() and onStop() methods can be called multiple times, as
the activity becomes visible and hidden to the user.
vs
(further down in the blue table with the "killable" columns)
onPause() Called when the system is about to start resuming a previous activity.
What I'd understand from the first quote, is that onStop() is called on activity A when A is "hidden". "Hidden" I'd guess is referring to when another activity B has been resumed and is completely covering actvity A.
But the second quote then states that onPause() is called when another activity is about to start resuming. Wouldn't that completely hide activity A as well? Both cases seem to imply that that activity A becomes "hidden", no? According to my likely faulty interpretation, onPause() and onStop() are called in identical situations.
The documentation also seems to differ between being hidden (onStop() gets called) and being partial visibility (onPause() gets called). But when is an activity still partially visible? Do they mean literally? Or can an activity still be deemed "partially visible" when it has started up a new activity (activity calls startActivityForResult and starts a date picker activity) that covers the entire screen? Surely the activity is not going get onStop invoked? Its supposed to receive a result any moment!
So I'm trying to figure out what I'm not getting.
I understand that a call to onPause is guaranteed. That would be when activity A loses focus (device enters sleep mode, screenlock, etc), a different activity B takes the foreground (where activity B may or may not have been initiated by activity A).
But at which point is the onStop() invoked on activity A?
Is it matter of how many activities have been piled ontop of activity A on the activity stack? Are there two different definitions of "visiblity" at play?
Sorry about the wall of text, but I'm really frustrated :S
So the question stands: Precisely in which situations is an activity deemed "hidden" such that onStop() is called on it?
EDIT:
I inserted Toast notifications in each onX method, and discovered some additional weirdness:
Pressing the Home button will always call onStop(). But starting up the application won't call onRestart(). Instead it calls onCreate(). This seems strange to me, but ok...
When the "USB Mass Storage" activity is started on top of the main activity, onStop() is called. And when exiting the usb storage activity, returning to the main activity, onRestart() is called, instead of onCreate().
When the device goes into Sleep mode and is waken up, the activity only goes through the onPause() and onResume() cycle.
The last point was expected (although I can't get it to fit in the lifecycle diagram). But whats up with 1. and 2. ?
In the first point, I was expecting a call to onRestart() when starting the activity again. Why did it deallocate the activity and call onCreate() instead?
And take a look at point nr 2:
According to the documentation: when "another activity comes in front of the activity", onPaused() should be called. Isn't that what happened when the USB Storage activity came up? It didn't call onPause(), it went through the onStop() - OnRestart() cycle! Obviously, the documentation doesn't consider that a case where "another activity comes in front of the activity". So what really happened?
Ok, I think I've got this now.
1.
The key to the first point was this link:
http://code.google.com/p/android/issues/detail?id=2373
Its a bug. Theres some code in the link that has completely solved the problem with new root activity instances being created, instead of just restarting the last active activity (before the home button was pressed).
I put the code at the top of the onCreate method, just below the super.onCreate call:
if (!isTaskRoot()) {
final Intent intent = getIntent();
final String intentAction = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) &&
intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
finish(); return;
}
}
Note that I added the return statement after finish so the rest of the onCreate method doesn't run in the case that the bug is detected.
2.& 3.
The key to the second and third points was these two links:
http://answers.oreilly.com/topic/2692-android-programming-understanding-the-activity-life-cycle/
How to make Activity, not covering full screen
It turns out that "visibility" really is literally! So when the documentation says "another activity comes in front of the activity", the activity behind the bumped activity is still partially visible. This means that the Android Activity manager must check whether the bumped Activity is a full-screen activity or not: If it is, onStop() is called on the previous activity. If not, then onPaused() is called on the previous activity instead.
This trivially explains why the USB Storage manager caused the onStop() to be called.
This also means that when device goes into sleep mode, the Activity Manager considers it a non-fullscreen activity, even though technically the main activity is completely hidden behind it.
(See the second link on how to make non-fullscreen activities )
Interestingly, the pull-down window (with the notifications) doesn't call onPause() (nor does it call onStop()), even though it would have made sense as a non-fullscreen activity. This must be some kind of exception that I'll be investigating on my own.
This also means that the onStop()-onRestart() cycle is probably more common than the onPause()-onResume() cycle (although both must still be accounted for), since activities probably more often than not are full-screen activities (personally, I thought the documentation indicated the opposite: that onPause-onResume was more commmon, but maybe thats just me).
Additionally, this must mean that when the main activity starts a new fullscreen activity for a result, the main activity will be first stopped and later restarted when the result-retrieveing activity is done.
So the only question now is how to best deal with a paused activity (meaning, it is covered by a non-fullscreen activity) that gets deallocated (although this case would be rare). What challenges may there be?
But thats outside the scope of this question.
Finally tracked this down: you can detect the status bar pulldown using onWindowFocusChanged()
how to use OnWindowFocusChanged method
I don't know if these are related yet, but I have an app that won't let me click one of the buttons after resuming from onDestroy()
is this a known issue? the listeners are set onCreate()
and never set to null
onDestroy is the end of the life cycle for an activity. This means that the next time your activity is opened it is not "resumed" it is being created. This may be a bit confusing because even though the activity is being recreated onResume is still called. You might want to take a look at the activity lifecycle for a better description of what is actually happening as your activity moves through the different activity states.
I just developed a screen saver app and I found a strange behavior in its lifecycle.
My work flow is like this:
start my RegisterService, where I call registerReceiver method to register a BroadcastReceiver, which can receive ACTION_SCREEN_OFF.
2.In the onReceive method of this BroadcastReceiver, I start an activity as the screensaver.
3.In the activity, I write Log.i() statement to track its running.
My question is:
When the screen times out, or when I press the POWER key, the screen turns off, and the system will send ACTION_SCREEN_OFF message. As I expect, my receiver starts the screen saver activity. However, I find this Activity calls onCreate(), onResume(), onPause(), onResume() sequentially according to the output in logcat.
It seems as if some a activity comes at front of my screensaver and finishes immediately, so my screensaver calls onPause() and then onResume().
Any idea? This problem handicaps me in programming, please help. Thanks!
Well based on a brief study of the PowerManagerService.java source code, when it's time to turn the screen off, the system initiates an animation (look at line 2183 for the class source) to do that. That means that your activity will pause and then will resume after the animation has ended.
I cannot be 100% sure for this, since I haven't tested it in my environment but this is the only logical explanation I found for your situation.
Hope this helps...
I can recommend you something very easy that might work for you, if you do not want the pause behavior why don't you try to Override the method onPause() and just do nothing :P don't call super.onPause() and that will terminate the behavior of it.
Other thing that might work for you, declare a static variable, add 1 on the "onResume()" method and return to "0" when "onStop()" is called. now just evaluate when the "onResume()" is called and if the variable is "0" then is the first time, anything else do nothing.
I hope this helps cause there is no much information on your question to be more specific.