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.
Related
I have an activity that contains an Instance of FileObserver. I start watching in onCreate and stop watching in onDestroy of the activity. So what happens if onEvent is doing some operation and the activity is destroyed (user presses back button)? Does my onEvent continue to finish what it was doing? Basically I am wondering whether onEvent should start a service or handle its business itself.
Does my onEvent continue to finish what it was doing?
At least briefly, yes. FileObserver is not tied to a specific component's lifecycle, like that of an Activity.
However, once your app is no longer in the foreground, your process can be terminated at any point, to free up system RAM for other apps. Android is not going to pay any attention to your FileObserver and its onEvent() processing when this occurs, by default.
If you expect the work to happen quickly — say, under a second — you should be able to keep it where it is.
If, however, the sort of work that you are doing is more substantial, I would consider having a service do the work. Per our prior discussion, while the FileObserver should not be in an IntentService, the work triggered by the FileObserver could be. onEvent() would call startService() to tell the service to go do the work. Services are a signal to the OS that you are actively doing work on behalf of the user, and so your process is more likely to hang around for a bit longer.
Unless the Application is stopped the code in your onEvent will continue to run.
FileObserver.onEvent documentation
This method is invoked on a special FileObserver thread. It runs independently of any threads, so take care to use appropriate synchronization! Consider using post(Runnable) to shift event handling work to the main thread to avoid concurrency problems.
So the only think you need to be concerned with is what exactly you are doing in onEvent. For instance if you are updating UI or interacting with the Activity / Fragment in your onEvent method then this could cause a crash if the Activity goes away.
With that in mind a service will certainly increase the odds that the application does not terminate while you are performing your work.
Service documentation
The Android system will force-stop a service only when memory is low and it must recover system resources for the activity that has user focus. If the service is bound to an activity that has user focus, then it's less likely to be killed, and if the service is declared to run in the foreground (discussed later), then it will almost never be killed. Otherwise, if the service was started and is long-running, then the system will lower its position in the list of background tasks over time and the service will become highly susceptible to killing—if your service is started, then you must design it to gracefully handle restarts by the system. If the system kills your service, it restarts it as soon as resources become available again...
So the bottom line is that a service is more likely to keep your application alive. Event more likely if you call startForeground but in this case you need to be willing to show a notification to the user.
I have an android Service class which has a long running onDestroy. I need to prevent this as it can cause a hang when there are activities running.
It seems some people are happy starting a thread/AsyncTask in the onDestroy method to hold the long running code, though I'm concerned that the threads may be killed. Another solution may be to use startService instead of stopService with an intent that tells the service to start a shutdown thread which calls stopSelf at the end.
Are any of these solutions sensible, or is there another way?
A shutdown Intent is a reasonable way to go here.
Starting another Thread in onDestroy is a bad idea though. It might be called or not called when you don't expect or want it.
Edit: To persist important information neither of these ways is a good idea.
You cannot assure that these methods actually get run before your process is killed. For non-important data you could of course go these ways, but you'd better persist your data as soon as you get it, or at least within a fixed interval (if you have a continous data input).
From the official Documentation:
Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here.
This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. 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.
And here the Documentation specifcally for services:
Called by the system to notify a Service that it is no longer used and is being removed. The service should clean up any resources it holds (threads, registered receivers, etc) at this point. Upon return, there will be no more calls in to this Service object and it is effectively dead.
(I've included the Activities documentation, because it is more precise)
You should be aware that there is no absolute guarantee for onDestroy to be executed.
It seems some people are happy starting a thread/AsyncTask in the onDestroy method to hold the long running code, though I'm concerned that the threads may be killed.
I would assume that you're trying to either free some resources or send some sort of message to server.
In case of resources there is no need worry - if you'll start new thread it will be killed only together with hosting process (your app). If that would happen - it's ok, system will release resources for you.
In case of server message - that is a bit more complicated. I like your idea with sending command to a Service instead of calling stopService. Other option would be to start another tear-down Service from your onDestroy which will perform long running operation and shut down itself.
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.
I am trying to determine how to keep my app safe under various Android lifecycle conditions, such as another app being start, phone going to sleep, etc. I understand the lifecycle states and the event methods I can hook into, but I am not sure how memory is handled in regard to things I already had references to. I am well aware that my app may be killed at any time if the OS needs to, but what about individual references? Here are a few example scenarios: if my app is running and the user gets a phone call, or the user starts another app, or the phone goes to sleep. Assuming my app did not get killed, can I safely use my references or will I get random null pointers? I guess what this comes down to is... does Android either kill or not kill and app or will it reclaim some memory (where there are still valid references) from an app without killing it?
Most of the time when the user switches to another app or answers the phone, you app will simply be suspended. When it comes back, onResume() will be called and it will continue on it's way with no issues. References and that kind of thing should be fine. It is recommended that you unregister listeners and re-register them in onResume(), though.
You should always remeber that your app may also be completely killed at any time, so save your data.
The truth is most of the time the application will not get killed in a brief interruption, for example a call or email, but if you want support these situations you should preform cleanup or saving the data in onPause(). When the application comes back it will execute onResume().
References will not disappear until the activity is destroyed, do not worry about NPE in the pause -> resume scenario unless you are doing something very odd.
If you are using listeners or GPS, you should unregister during onPause() and resume it later.
This doesn't appear to be well documented or I missed it, so before I run a bunch of my own tests I was wondering if anyone already knows the answers to some of these questions.
First off, when I say "Application" I am referring to extending the Application class. http://developer.android.com/reference/android/app/Application.html
The questions I have are as follows, some are related.
When an a user leaves an Activity from within the Application, and goes to the Activity of another application, does the Application somehow get paused as well, even though it doesn't have an onPause()? Or does it continue to live unpaused until all of it's activities are destroyed?
when does the Application stop? When all of it's Activities are destroyed?
Is there ever a chance that one of the Applications Activities could be running without an instance of the Application, or will the Application class always exist if one of the Activities does?
If there is some process running on the Application, and it's Activities are all paused, will that process continue to run?
Is the Application effected by rotation in any way or does rotation only change Activities?
Thanks
As you say the application does not have onPause so nothing happens to the application. When onPause gets called in your Activity nothing special happens, your Activity continues to run and can do whatever it wants including run new threads, timers can go off, whatever.
I believe what you are asking is: when is an Application destroyed and when the onTerminate method in an Application called? The answer is hard to pinpoint and is up to the system, it does not necessarily happen when all activities get onDestroyed called. In fact even when onDestroy is called, your Activities aren't necessarily garbage collected. When the system gets low on memory the process that your Application lives in can be killed, meaning your Application will disappear; onTerminate may or may not be called. At that time all the Activities, Services, etc, are killed too.
The Application is always instantiated first, an Activity must have an associated Application, just like how you define it in the AndroidManifest.xml.
Processes never pause in Android, the onPause method does not actually really do anything other than tell you to pause things in your app. Other than that the process keeps chugging away, your threads keep running, even the main thread receive Intents with a BroadcastReceiver.
The Application gets rotation callbacks in the Application's onConfigurationChanged(). I'm not sure if you can disable that since there is no configChanges attributes supported by application tags in the AndroidManifest.xml.
A good comparison to Application is static field in any of your classes. The static fields will live as long the process is not destroyed, just like the Application. Static fields can be accessed by all Activities, Services, etc (assume the static fields are public), just like your Application.
Good Luck!
Jacob
The easiest way to understand this is to just forget that Application exists. Application has nothing to do with the application lifecycle. It is just a global on a process, that can be useful for some things, but is not needed for anything. Everything about how an application runs revolves around the Activity, BroadcastReceiver, Service, and ContentProvider components declared in its .apk.
An instance of Application can continue to exist after your last Activity is destroyed. Even if ALL activities are gone (ie. have all had their onDestroy methods called), the Application instance could still exist.
This application instance could be "re-used" for what you might otherwise think are two separate runs of your application.
This is all explained in detail here: http://developer.android.com/reference/android/app/Activity.html. If you read through it, you should understand everything.
Real quick:
Every activity has an onPause. You can choose not to override it, but it'll get called nonetheless. As soon as you switch away, onPause will be called.
Define "stop". Define "Application". The process may linger around forever, but it'll simply sleep and wait until one of its activities is started.
It's impossible for an activity to exist without being instantiated.
Every code executed runs in a process, so there's always one process for your app. The process will continue to exist after you switch to a different app, but it'll be in sleeping state. Android could at any time kill the process if system resources run low.
Every time you rotate the screen, your activity will be destroyed and recreated, unless you specifically disable that.