Determine whether Activity was closed or re-drawn - android

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.

Related

What we should do in onStart, OnResume, OnPause

Hi I have gone though activity lifecyle on many threads, but I could not find what we should do in onStart, onResume, onPause method of the activity.
In the onStart() method, you add code that's relevant at the beginning of the activity.
Let's say, you have an app that reads the temperature of the device's battery. You'll want to have an initial value, so as to show the user.
So in the onStart(), you'd add code that goes ahead and fetches the information you'd need, and displays it for the user, before your timer (for example) goes and reads the information a minute later.
The onPause() method is called before the application goes in to the background.
To stay with our example, in the onPause() method, you'd save the last recorded temperature to the device; so you can show a comparison when the user next opens the app.
The onResume() method is called when the application is brought back to the foreground (i.e.: you've gone to the task manager, and tapped on your app to show it again).
Again, staying with the going example; in the onResume() method, you'd go ahead, read your saved data, load fresh data, and show a comparison of the two in the application.
Then, when your timer ticks next, only fresh data will be shown.
Your question is a bit vague, so answer might not be super specific..
I would say there are no strict "rules" around what we should do in corresponding activity lifecycle methods.
In fact, you can do nothing there (just make sure you call super method if you decided to override those). I.e. your custom activity might not even override these methods - it will work just fine.
onStart, onResume and onPause methods are just hints to you about activity lifecycle change, so you can react accordingly, i.e. start/stop specific to your activity operations at the appropriate time.
For instance, when onResume is called it means that activity became fully visible to the user, so you might want to start some animation (if necessary)
Again, you are not obligated to put any code in there.
Usually most of the operations are performed within oncreate and onresume.
However for your info let me brief it out,
Onstart- this is called after Oncreate, once activity is visible to the user, if you want to perform some operations before the visibility do it in Oncreate, because most of codes should be operated before user views the activity.
OnResume-Be cautious on Onresume is it is quite tricky it will be called whenever you activity is brought to foreground.
Onpause-Called before Onresume, codes wont be executed here, so strictly avoid adding codes in Onpause instead add inside Onresume.
Hope it helps,

Getting around onDestroy being called on orientation change?

I have a stock Nexus 5 running 4.4.2 (using ART if it matters) and I've found an interesting scenario. I have this as my onDestroy():
#Override
protected void onDestroy() {
super.onDestroy();
t.setText("onDestroy");
t.show();
}
It's a GPS oriented app so I'm up and walking around. I am using the technique mentioned in this question to show a lot of debug toast messages.
Anyway, when I rotate my app, the toast appears. I understand that the activity is destroyed and recreated for the new orientation, but how can I know what's really going on? How can I tell when my app is REALLY getting destroyed and not just being rotated? Similar to this question, I want to log out when a particular activity is destroyed.
Since Honeycomb, the isChangingConfigurations() method can be queried to check whether the Activity is being recreated due to configuration changes. Alternatively, the isFinishing() method can be queried on any API level to check whether the Activity is actually being finished, or is only being destroyed temporarily by the system.
As far as I can determine, the two methods should always return mutually consistent results in practice. The only point where they might have diverged is when the system kills the process to clear memory, but there are no callbacks or interaction with the app at that point.
The documentation of the onDestroy() method mentions the use of the isFinishing() method:
Perform any final cleanup before an 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.
You can put it in a fragment with setRetainInstanceState(true) set. Place your code in the onDestroy() method of the fragment. Then, the fragment will not be destroyed on orientation changes.
First of all, you should not use onDestroy() to do anything because its not guaranteed to be called. I would put things on the onPause() method; I wouldn't even put things in onStop().
Also, Im not sure why you want to log out a user when they navigate away from the app. I would rather implement some kind of timer on the app or server to log out after x time.
Now, the answer lies in the documentation: http://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges
You might want to override onConfigurationChanged so that your activity is not restarted.
I found a couple of solutions which are really just patterns to detect when the screen rotates. Alternatively, you can determine that the device was actually destroyed by checking some static data member to see if it was initialized or not.
Configuration changed solutions:
The first one involves handling all of the configuration changes in the onConfigurationChanged callback.
"Note that this will only be called if you have selected
configurations you would like to handle with the configChanges
attribute in your manifest."
The second involves listening for Display.getRotation() which returns a Surface.ROTATION_* object. Which is the new orientation of your screen relative to the natural state of the device orientation.
Again, you can use the configuration changes along with the static member.
Add ConfigChanges.UiMode flag to the ConfigurationChanges attribute for your MainActivity class, and this solves the problem.
More details: Android Launcher "OnDestroy" gets called twice

android: when to use onStart(), onStop()?

I've read several posts that describe the difference between onStart() and onResume(): onStart() is called when the activity becomes visible, onResume() is called when the activity is ready for interaction from the user. fine.
I've always just added code to onPause() and onResume(), and never bothered with onStart() and onStop().
Can anyone give some concrete examples of what you might do in onStart(), vs. onResume()? Same goes for onStop() and onPause(), how is onStop() useful? I must be missing something fundamental here.
onStop() will (for example) be called when you leave the activity for some other activity (edit: almost. see commonswares comment about dialog themed activities).
For example if you use startActivity() in activity A to start activity B. When you press back in activity B you will return to activity A and onStart will be called.
This differs from some of the reasons onPause might be called without onStop being called. If for example the screen times out or you press the standy button onPause will be called, but probably not onStop (depending on memory available and whatnot), so it is a "lighter pause". onStop will be probably be called eventually even in this case, but not immediately.
Ok, but what's the use
Often there is no specific use, but there might be. Since your activities will keep its memory state on the stack even after you start some other activity, that stack will increase with the number of activities started (height of the stack).
This can lead to large memory usage in some applications. After a while the framework will kick in and kill some activities on the stack, but this is rather blunt and will probably mean a lot of states to be retained when returning.
So an example use for onStart/onStop is if you want to release some state when leaving an activity for another and recreate it when you get back.
I have used it to set listadapters to null, empty image caches and similar (in very specific applications). If you want to free the memory used by visible views in a listadapter you can recreate it in onstart and let the views be picked up by the gc. This will increase the likelyhood that the rest of the memory state of the activity will live on.
Some resources can be deemed good enough to save while the activity instance is alive and some only when it is on the front of the stack. It is up to you to decide what is best in your application and the granularity of create/start/resume gives you that.
onStart() works after onCreate() ended its task.
It's a good place to put a broadcastReceiver or initialize some state about the UI that should display consistently anytime the user comes back to this activity.
onResume() works when you come back to your Intent or Activity by pressing the back button. So onPause will be called every time a different activity comes to the foreground.
i think that your question is pretty explained here on the doc : read about the Activity Life Cycle

Android - Losing scope on UI elements after onDestroy()

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.

What does "visibility" refer to in the Activity Lifecycle? onPause vs onStop?

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

Categories

Resources