I have been using log messages in the activity lifecycle functions to monitor the behaviour of applications's activity, and some time ago i discovered a weird unintended recreation of the activity. This behaviour is specific, because it occurs only, if activity at the moment of screen turning of is LANDSCAPE orientation.
The steps of this behaviour are following:
while in LANDSCAPE orientation, the screen turns off, calling the onPause() and onStop() functions (probably onDestroy(), i am not monitoring it)
after few seconds, while the screen is still off, onCreate() of this activity is called, but with PORTRAIT orientation property
this cycle goes to onResume(), which is immediately followed by onPause() function (onStop() is not called)
If the screen turns off while being in portrait orientation, the activity lifecycle follows the proper path, with no debug messages after onStop is called.
Since the activity class in question is over 1800 lines long, for now i will avoid posting it here.
I am aware, that the description of my problem is generic,but hope, that maybe someone else has experienced similar problem and can maybe point towards the possible source of the problem.
Related
I've got an app that is complete, apart from the lifecycle that, guiltily, I left as last.
Things seem to work good in all cases, but one:
When I pause the app by pressing the power button, it correctly pauses and restarts when resuming.
When I rotate the screen it correctly resizes.
When I pause AND THEN rotate the screen, its behaviour is different and the app resets.
Now, obviously it's a problem of my internal code, but to help me in the debugging, I would like to understand what's the difference between the three lifecycles. Or better, if the THIRD example is some how different from the first two.
With debugging I saw that all of three do this (I resemble by mind, I hope to be right):
onSaveInstanceState()
onPause()
onStop()
onStart()
onResume()
Is it right? Or do I miss some lifecycle steps in the third example, above?
Thank you.
Please specify what you mean by the app resets.
When you press the power button, most likely your app stops. That's why you see onStart() being called after stopping (not: pausing) your app.
Given that, is it really the case that the third scenario you describe is a combination of the first two? In other words, how do you pause your app in the third scenario?
Update Regarding your comment: There is a difference between your Activity being stopped and your Activity being destroyed.
Rotation is a configuration change. In this scenario, your Activity is going to be destroyed and re-created. You can handle this case separately if you must (it depends) through the onRetainNonConfigurationInstance() callback and the getLastNonConfigurationInstance() method. Android will call onPause(), onStop(), onRetainNonConfigurationInstance() and onDestroy() in this order, and then continue with onCreate() etc and it will not handle any events in the meantime so that they won't get lost.
Most likely, some of your code is located in the wrong callback, such that in the third scenario, something does not get initialized/attached/... This is really hard to tell without the code and the exception (if it is an exception).
I suggest you proceed as follows.
Complete your understanding of the lifecycle and be precise (creation, start, restart, resume, pause, stop, destroy)
Complete your code to override the other lifecycle callbacks as well with log messages (don't forget to call the super class' callback) and analyze pause, stop, rotation and combinations
Identify the point of the crash
Analyze the life cycle of the objects involvedd in the crash in conjunction with the Activity lifecycle
Or you can post some code and the exception here, of course.
Update 2 I have made a test on an AVD. I have observed the following:
When the AVD is in landscape orientation, and I press the power button, my app receives a configuration change to portrait orientation (presumably because the portrait-orientation-only lock screen takes over). Pressing power again and unlocking the AVD, the app receives a configuration change again back to landscape orientation.
While not solving your issue, it goes to show that code must be carefully placed in the respective callbacks, because in the case above, while being re-created, the Activity will still not be shown.
Drop me a comment if you update your question.
Hi you can check the documentation regarding Managing the Activity life cycles in android .
When orientation changes Activity is re-created.
Add android:configChanges="keyboardHidden|orientation" to your activity in the manifest.
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.
When using the onPause method in the Android SDK, that code is run whenever the Activity was re-drawn (Such as rotating the device). Is there a way to detect whether the Activity was actually paused (Such as a new window popping up) or if the Activity was actually just re-drawn?
Actually if you look at the life cycle of an activity, when the device is rotated, the activity is restarted, so after onPause(), the activity goes through the complete restart cycle (onStop() and onRestart() are also called), so in this case you can set some value depending on what functions were called, or check the device's orientation.
Also when the activity goes into background, onPause() is called, and when the activity is no longer visible to the user, onStop() is called, which are due to specific reasons, the application can check that by setting some variable. For complete understanding, study the activity life cycle (Alternate Link)
But why do you need to know what happened to the activity? By overriding appropriate functions and providing proper layout resources, you do not need to know what happened in most cases.
For orientation, you can also get the orientation using getRotation method.
I am trying to handle problems that occur in my application when the phone is plugged into certain types of chargers and put into "Car Mode" or "Driving Mode".
In the running application, onDestroy() is called and immediately followed by onCreate(), and the application starts again normally. However, subsequent calls to update UI elements (in the newly created main Activity) now have no effect, and it looks like I've lost scope on my layout.
RelativeLayout splash = (RelativeLayout) findViewById(R.id.splash);
splash.setVisibility(View.VISIBLE);
What could be ocurring onDestroy() that I'm not accounting for? I don't do much cleanup onDestroy because I didn't think I needed to.
The Activity has been detached from the UI by the time onDestroy() is called so having UI calls to it doesn't make any sense. If you need the splash to be shown, set it to View.VISIBLE in onCreate(), onResume(), or maybe onPause(). I'm not entirely sure if onPause() would act any different.
When the phone rotates the activity is destroyed and recreated. Plugging into a car charger usually forces the phone to landscape mode, thus rotating it (from portrait, most likely) and calling onDestroy. There is a way to prevent this behavior with some activity flags -- but Google advises against it.
We need to see some more code for this Activity to figure out what's going on.
Also, as DeeV points out, the activity is long gone by the time onDestroy gets called, so it might not be the right place to be doing whatever it is that you're doing -- but we need more code to be sure.
As a sidenote, sliding the keyboard up (on phone's that have slideout keyboards) will produce the same effect.
I am logging each onCreate() and onDestroy() calls. I found out that once I click power button on my Android (and on the emulator too!) the phone calls in my activity
> onDestroy();
> onCreate();
Which kills my game and then immediately reopen it from the beginning. Of course once user unlock the screen the game is presented in main menu with all progress killed.
Is it possible to override or disable this behavior?
When you press the power button, the screen lock usually kicks in. This may trigger a configuration change on the activity currently in the foreground (the screen lock is usually in portrait mode), causing it to be destroyed and recreated.
Declaring android:configChanges="keyboardHidden|orientation" for such activities in AndroidManifest.xml prevents them to be destroyed and recreated but also implies that you will handle the configuration changes by yourself (if necessary) by overriding onConfigurationChanged
You can't override when the onCreate() and onDestroy() methods get called (at least not without experiencing extraordinary amounts of pain). The best thing for you to do is to figure out how to work within the confines of when they get called. Save your state in onDestroy(). Make it so that your app can tolerate this call sequence because quite frankly, it supposed/has to. That's just how android works.