is it really wrong to release resources in onDestroy? - android

Android documentation says (in http://developer.android.com/training/basics/activity-lifecycle/stopping.html):
In extreme cases, the system might simply kill your app process without calling the activity's final onDestroy() callback, so it's important you use onStop() to release resources that might leak memory.
Sounds like it is wrong. How could killed process leak memory?

Suppose you started a service in your onStart() method, and you intend to stop that service when the user gets out of the Activity.
If you put the code to stop the service in onDestroy(), that code may never get called, which can leave that service running until Android decides to kill it (which may not happen for a while, if ever). That running service is and example of leaking memory/resources outside your application.
You should put cleanup code like that in a method that is guaranteed to be called.
Note that a process is killable after onPause() has been called, so onPause() is really the place you want to do cleanup that absolutely must happen.
(See table 1 in https://developer.android.com/guide/components/activities.html for details on the Activity lifecycle)
Another thing that might be really bad to leak: Bluetooth discovery or location reporting (GPS or network-based) turned on but not off as soon as possible - very bad for battery life.

Related

Android - Ensuring that Wakelock is released when a Service's process is killed by OS

I want my FusedLocationProvider to ping for location even when the screen is off. For this, in my service, I have a PARTIAL_WAKE_LOCK, to keep the CPU running and to ensure that the service continues to run even when the screen is off.
That being said, I know the Android OS will kill off services/apps in the background when it needs memory. Due to this, my service can be killed off.
When this happens, onDestroy() in the Service is not guaranteed to be called. If that is the case, how do I ensure that the WakeLock gets released?
I call mWakeLock.acquire(); in onStartCommand, and in onDestroy I call mWakeLock.release();
how do I ensure that the WakeLock gets released?
According to the docs:
If the service is currently executing code in its onCreate(),
onStartCommand(), or onDestroy() methods, then the hosting process will be a
foreground process to ensure this code can execute without being killed.
What this means is that if the code in any of those methods is currently being executed, then the process won't be killed (or at least will be given a very high priority) till the code finishes executing.
However, the short answer to your question is that there is NO way to ensure that onDestroy() or onPause() gets called. onPause(), though, does have a far greater probability of getting called, so you could look into that. There is also a method, Application.onTerminate() which you may want to use for further research on this. The method is only called when running the app on emulators.
I don't think you need to worry about a memory leak, though (assuming that we are both on the same page regarding what such a leak constitutes). When a process is killed, the memory is reclaimed by the kernel, not by the GC, so there isn't going to be a memory leak in that case.
EDIT:
I have confirmed that if a process is killed, an acquired wakelock will necessarily be released:
1. Does the android os release a wakelock if the app or service holding it is killed ?.
2. What happens with the partial wake lock if the process that acquires is killed ?.
3. Binders & Death Recipients.
4. How to deal with (orphaned) WakeLocks?.

Will activity run onDestroy when system kill it?

I am wondering that will activity run the method "onDestroy" when killed by system?
for example, when the state of "activity A" is onStop ( user may press the Home button directly ),
at the same time, system find out that the memory is not enough so system have to kill some background processes to keep foreground activity alife, say system kill activity A.
Will activity A run the method "onDestroy" in this situation?
It will purely depend on the system condition at that time. Docs clearly says about onDestroy() that:
There are situations where the system will simply kill the activity's
hosting process without calling this method (or any others) in it, so
it should not be used to do things that are intended to remain around
after the process goes away.
See Here
From the developer.android.com :
When your activity receives a call to the onStop() method, it's no longer visible and should release almost all resources that aren't needed while the user is not using it. Once your activity is stopped, the system might destroy the instance if it needs to recover system memory. In extreme cases, the system might simply kill your app process without calling the activity's final onDestroy() callback, so it's important you use onStop() to release resources that might leak memory.
So, android usually will call onDestroy() of your activity before it is killed but it is not guaranteed.
Link : http://developer.android.com/training/basics/activity-lifecycle/stopping.html
Depends, as when system kills an application, it's associated PID killed by it directly. As Android is nothing but Linux, it sends SIG9 (9 number signal is "kill")/ kill (Application's PID) to kill application without invoking it's callback methods.

Situations when a Service's onDestroy() method doesn't get called?

I'm aware that a Service's onDestroy() method may never be called but can someone tell me when such a scenario might occur? I'm especially interested in whether it's possible for a Service to be killed, yet its VM would continue to run.
I ask because I have a service that registers ContentObservers in the service's onStartCommand() method and unregisters them onDestroy(). If the service's onDestroy() method was never called because the whole VM was killed (along with the observers it created,) that would be fine. But I'm wondering if it's possible for a service to "go away" without onDestroy() being called, while the observers it created would live on and continue to receive changes.
I'm aware that a Service's onDestroy() method may never be called but can someone tell me when such a scenario might occur?
Here are three off the top of my head:
If the user Force Stops you from the Settings app
If Android needs RAM in a hurry (e.g., to process an incoming phone call) and elects to terminate your process to free up that RAM
You terminate the process from DDMS
Also, if your service crashes with an unhandled exception somewhere, Android may consider the service to be defunct and skip onDestroy(). I'm not sure about this one, as I haven't specifically tried it.
But I'm wondering if it's possible for a service to "go away" without onDestroy() being called, while the observers it created would live on and continue to receive changes.
Other than the unhandled-exception possibility I mention above, I am reasonably certain that if the process will be terminated in the conditions where onDestroy() is not called.
Also if the app is reinstalled/updated , ondestroy() is never called.

Is an android service guaranteed to call onDestroy()?

The life cycle diagram of an Activity on an android does not guarantee that onDestroy() would be called, but that the process may be killed and the Activity is removed abruptly. The life cycle diagram of a Service on an android does guarantee that onDestroy() would be called. So I have two questions relating to this difference.
Firstly, if the Service is part of the same process as the Activity, is the Service onDestroy() called, though the Activity onDestroy() is not called? I would think not, as "killing a process" suggest that the operating system is stopping its threads and releasing its resources.
And if that is the case, can a Service-only-process be abruptly killed by the OS?
I'm not sure where you're seeing that a Service is guaranteed to have onDestroy() called. As far as I know, this isn't the case. If you read this page of the docs, it describes the conditions in which a service could be killed. So if you're asking if a process which hosts both an activity and service is being killed, will onDestroy() be called on the service (but not on the activity) then the answer is no; a service's onDestroy() will not necessarily be called. As to whether a service-only process can be abruptly killed by the OS: yes, it can. This is especially true when you have a lot of work to do, and your onStartCommand call only queues up the work to do asynchronously. Then the service will be spending the majority of its time not in the protected onCreate, onStartCommand or onDestroy methods.
There are two things to consider:
Android might decide to shut down a process at some point, when memory
is low and required by other processes that are more immediately
serving the user. Application components running in the process that's
killed are consequently destroyed. A process is started again for
those components when there's again work for them to do. Source
In this case onDestroy() is not called as the Android OS will reclaim resources anyway (this is a basic task of the OS in general).
A service can be both started and have connections bound to it. In
such a case, the system will keep the service running as long as
either it is started or there are one or more connections to it with
the Context.BIND_AUTO_CREATE flag. Once neither of these situations
hold, the service's onDestroy() method is called and the service is
effectively terminated. All cleanup (stopping threads, unregistering
receivers) should be complete upon returning from
onDestroy(). Source
So when the Android OS notices that the Service has finished its job and is not needed anymore it will be destroyed. The OS gives the app a chance to release the Service's resources to prevent memory leaks. In this case onDestroy() is called as this is the place where the app can release its resources. Of course in this case the application's process stays untouched (as there may be other Services/Activities running in it).

Application.onLowMemory() not invloked

I've create an Application class of my own.
I try to debug it and the code stops at Application.onCreate() but does not stop at onLowMemory.
To test the scenario I open a lot of other high memory applications.
What I see is that the debug session terminated (in eclipse) and some of my static variables turned to null - indicates the the process has ended.
Not only did the debug NOT stop # the breakpoint of the method, I've put a Log.e(...) line and don't see it as well.
Any idea of why the method was not invoked?
Thanks.
I don't think that there are any guarantees that this method will ever be called.
From the docs:
While the exact point at which this
will be called is not defined,
generally it will happen around the
time all background process have been
killed, that is before reaching the
point of killing processes hosting
service and foreground UI that we
would like to avoid killing.
Since the point at which it is called is not defined, it could choose to never call it.
In general, Android is free to kill your Application whenever it wants, as long as it is in the background. You should only rely on methods in the lifecycle (like onPause, onStop, onDestroy) that specifically state that they are guaranteed to be called in order to do any necessary cleanup.

Categories

Resources