call method when program exits - onDestroy not reliable - android

I want to execute some functions when the program is exited by hitting the back button.
This is now done by onDestroy() which works in every case but one. When coming back from another activity in some cases on exiting the program, onDestroy is not called.
I know that in theory onDestroy should only be called when Android closes the app due to low memory, but for me, onDestroy works always and only in a very special case it does not.
Using onPause or onStop does not work because I only want to call the function when the program is exited but not when just another activity is called.
So is the last way to catch the back-button-click and call the function there? Or is there any other solution?

Tactically, use onBackPressed().
Strategically, reconsider your architecture. A well-written activity should not care if onDestroy() is called, as it is guaranteed to NOT always be called. For example, Android can terminate your process whenever it wants (e.g., extreme low memory conditions). The fact that you need onDestroy() to work reliably suggests there are problems that should be resolved.

Related

Can an Activity call its own onPause(), onStop()?

My app interfaces with a Bluetooth peripheral. When the peripheral wants to shut down, can I clean up the app simply by calling my Activity's own onPause() and onStop() methods? Is the fact that they call the superclass's methods likely to cause any problems?
The idea would be to call finish() after that.
Technically, yes, you can. What you should be asking is "Should I"? Which the answer is no.
Like you've mentioned, since they do call the superclass methods, there is some extra Android OS cleanup magic that happens. It may result in a successful case once in a while, but it's not guaranteed. There is a lot of things that happen in the backround that you don't want to fool with. Don't reinvent the wheel.
If there is code that is ran within the onPause and onStop methods that you would like to use elsewhere, I would create a function called cleanupBluetooth and the onPause and onStop would call and anywhere else it needs to.
If you need to actually call the onPause and onStop methods because you need to stop and halt the activity, you can do that by calling finish() (how to use finish()). The finish() method will call the appropriate Android OS magic that's needed to be called.
You can call them manually, but you shouldn't let Android do it itself when it needs to. If you wish to call those activities, you are likely not really wanting the activity any more, so you can just call finish and then android will call the relevant methods based on the activities life cycle.
You can find more info about the activity life cycle by going here
OnPause() is also a method in your activity and it will likely normal method. It overrides method of activity and you can call it from anywhere in activity and from interface also.

When onDestroy is not called, which lifecycle methods are called upon resurrection?

Android documentation about Activity says that onDestroy may not get called if the system kills your process to reclaim memory.
My questions are
Is there a way (developer tool etc) to simulate this situation (no onDestroy) for testing?
Suppose my process is killed by the system to reclaim memory and user navigates back to my activity, what methods are called? Does onCreate get called again?
onDestroy simply isn't guaranteed to be called. In both situations everything has to be created again... so onCreate, onStart etc. You don't need a tool - if its some code that MUST run, don't put it there. https://developer.android.com/reference/android/app/Activity.html#onDestroy%28%29

Android - What method will get called when the App is getting killed?

I'm writing a game that players take turns in. At the end of a turn, I send my data to the server and update my database to let me know that it is now the other player's turn. The problem is, what if someone were to kill the app mid-turn? I'm talking going to Task Manager and actually kill it.
I read that onDestory is not always called, so that's a no go. I was then thinking onStop, but onStop is called in other places too. So how can I be sure that the app is actually getting killed and they aren't just like putting the app in the background for example?
Edit: I should also mention this is in a Fragment that I'm checking this, but don't think that'd make a difference.
I am not sure if this will help you solve the problem completely, but if you want to use onStop() instead of onDestroy(), there is a way to distinguish between a call to onStop() because the activity is dying and a call to onStop() because it's just going to the background:
if (this.isFinishing ())
{
// activity dying
}
else
{
// activity not dying just stopping
}
However I do want to point out that although onStop() MIGHT be more reliable that onDestroy(), it's still not guaranteed to be called right away. In my experience onStop() is called eventually, but maybe some time later.
In your example, there is no method that gets called. The Linux process hosting your application is killed, interrupting the Java Virtual Machine running your application's code in the middle of whatever it was doing. The application ends without any notice or warning - even finalizers don't run, because there's not really any "cleanup" needed.. the memory is simply reclaimed by the Linux system.
What you should do is design your application architecture so that if one of the players times out (application is killed, network connection is broken, battery dies, phone gets dropped out of a car and ran over by a truck and tossed into a lake), the server is able to detect the timeout and handle the situation accordingly - most likely, end the player's turn for him and move play onward.
You can use the following method. Its called when you swipe the app from the recent list:
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.e("onDetachedFromWindow", "activity dying");
}

Is it safe to do all cleaning up in onDestroy?

More concretely: Is it safe to place the canceling of a task in onDestroy? Also, is it safe to use onDestroy for unregistering receivers and freeing up resources?
My aim is to make sure that my task is canceled/destroyed when the Activity is destroyed, but not before.
onDestroy():
is called when the activity is destroyed and resources must be
released.
is NOT called when the activity is destroyed in a hurry (when the
system is low on resources etc).
The first case is clear: I do all cleaning in onDestroy and no problems arise. The second case is a bit of a problem though. When the Activity is destroyed and onDestroy is skipped (so I don't cancel my task), could it happen that the task continues execution, then completes and tries to update the dead Activity, so the app crashes?
We come to the real question:
When an Activity is killed and onDestroy is skipped, is everything attached to that Activity automatically destroyed? (Is onDestroy skipped only in case that everything will be wiped out altogether? Tasks, registered receivers etc)
If onDestroy is skipped does this mean that the whole app is being killed?
Let's focus on onDestroy(), because the solution is not in onPause() or onStop(). Arguments:
onStop() could be skipped when the Activity is being destroyed, just like onDestroy
onPause is called too early and too often, so it is not appropriate for the use case. Examples:
Screen lock: onPause can be called when the device screen is locked. Very often this happens like a screensaver and the user unlocks immediately because he is standing there looking at the screen. Canceling tasks and stopping everything my app is doing in such a case will only degrade user experience. I don't want my app to choke and misbehave just because of an incidental "screensaver".
In an example app I have two screens that are Activities. The user can quickly switch between them. In this app users tend to switch screens often and quickly.
Navigation: One of the screens has a map which receives location updates from the system. It records a precise graphical log of the changes in location (route), so it needs to run constantly until the Activity is closed. Normally I would register and unregister any receivers in onResume and onPause. However, this would make the app very unusable, as the updates on the map will stop every time the user navigates away. Therefore, I would like to unregister the receivers in onDestroy.
Loading list: The second screen has a list that shows data from a webservice. It takes 4 seconds to download the data. I use an AsyncTask and I know I should cancel when necessary. It should not be canceled in onPause, because it should continue loading while the user switches between screens. Therefore, I would like to cancel it in onDestroy.
There can be many more examples. Some of them might not be totally appropriate in everyone's opinion (you might even suggest using a service instead of AsyncTask). But the idea is important, and all of them have the same idea: keep on doing work that's specific to the Activity, while the Activity is paused, but ENSURE to stop doing it when the Activity is destroyed. (It does not matter whether I am using an AsyncTask or a Service. In either case, the work should be stopped when the Activity is destroyed.)
P.S. If the answer is that it is not safe to do the clean up in onDestroy, this would mean that the Android framework requires us to stop everything we are doing in onPause. And then I would not see any reason for using onDestroy...
I would like to refer you to this baby: http://developer.android.com/reference/android/content/ComponentCallbacks2.html#onTrimMemory(int)
Essentially it gives you all the places where the system finds it useful to cancel tasks and clean its memory:
Please take a closer looks at the following 2 cases:
TRIM_MEMORY_UI_HIDDEN - the process had been showing a user interface, and is no longer doing so.
TRIM_MEMORY_COMPLETE - the process is nearing the end of the background LRU list.
Which are the cases for most of what you asked.
In the same method you can also catch TRIM_MEMORY_RUNNING_CRITICAL which will alert you to a case where the system has no memory and special actions must be taken immediately.
This method has made my development life much better in similar cases.
If you just need to do some cleanup, no matter how the activity is closed, you should be able to use a combination of onSaveInstanceState() and onDestroy(). One of those should be called no matter what. Maybe have a boolean cleanupDone in your activity, which is set whenever one of the two finishes.
Concerning saving of user data, have a look at Saving Persistent State:
Google suggest a
"edit in place" user model
That is: save as soon as the user creates new data, at the latest in onPause(). This does not mean that you need to recreate the data in onResume(), just that it should have been saved.
By the way: onStop() can be skipped only on pre-Honeycomb devices, that is, as of June 2015, less than 6 % of all devices. Still, onSaveInstanceState() should be called if either onDestroy() or onStop() are omitted.
As far as I gone with android,
1 When your apps crashes every resource relevant to it are destroyed.
2 When the device changes configuration resulting the Activity to be destroyed and recreated.
3 When apps running in background and Android kill it due to running on Low Memory
apart from these the other callback method are called i e
1 when another Activity come in front , or your device locks ..etc
In all case according to your requirement you can release all your resources in onDestroy and cancel the Thread and Asyntask and stop all the services etc .if you want your task remain paused and alive while on destroy called then you can save the configuration and retain it while onCreate is called again by check is null or not.

How can I know an activity is going to be killed by OS?

I know I can use isFinishing() in onPause() to know whether an activity is going to be killed by finish().
Then, how can I know an activity is going to be killed by OS temporarily due to low memory?
Thanks.
Per the docs, onDestroy should be called right before the Activity is destroyed, regardless of the reason. If the finish was requested, isFinishing will return true. So if it is false, you can assume that the system needed to finish.
However, as the docs also say
Note: do not count on this method
being called as a place for saving
data!
In general, you cannot guarantee that your Activity will be killed nicely. Things like task killers mess with the lifecycle.
Use onPause or onSaveInstanceState to save things properly.
You cannot.
It's possible your activity could go away without the rest of your app going way, in this case onDestroy would be called. However it's also possible that your whole app is going to get killed at once, this like a kill -9 in unix. Your app cannot run any code at this time, it's killed instantly and without warning.
To handle this properly, you want to design your app to save all vital information to disk in onPause and be ready to retrieve it later in onCreate if needed.

Categories

Resources