I'm trying to find the official documentation about the Android Application class lifecycle. Apparently, for what I found on StackOverflow here and here the Application class can be killed if the system needs memory. Even this tutorial says so.
But few things irritates me a bit about this:
I can't find an official documentation telling me that yes, the Application class can be killed on low memory.
I can't find any official diagram representing the Application lifecycle neither.
I can't find any proper callback to use when the Application class is killed except onLowMemory(). Does it mean that I have to use this method to persist my data?
If the Application class is killed on low memory pressure and the app comes to foreground again, how can I know in its onCreate() that the app has been recreated after a system kill? In an Activity I would test the savedInstanceState, but as far as I know there is nothing similar in the Application class.
Thank you for your enlightenments.
I can't find an official documentation telling me that yes, the Application class can be killed on low memory.
Below are the references to where it's been stated:
Application Fundamentals
Processes and Threads
Multitasking the Android Way
I can't find any official diagram representing the Application lifecycle neither.
This is a reasonable observation... Although the following is opinion-based, my best guess is that such a diagram would contradict the Android's multitasking "philosophy" as described in the last reference provided:
"A key to how Android handles applications in this way is that processes don't shut down cleanly. When the user leaves an application, its process is kept around in the background, allowing it to continue working (for example downloading web pages) if needed, and come immediately to the foreground if the user returns to it. If a device never runs out of memory, then Android will keep all of these processes around, truly leaving all applications "running" all of the time."
I can't find any proper callback to use when the Application class is killed excepted onLowMemory(). Does it mean that I have to use this method to persist my data?
Regarding onLowMemory() whose description is quite straightforward, are we talking about a background process or foreground UI?...
If none of application Activities is in foreground and OS is low on memory, it may kill the app so that none of the Application's or the app component's (Activity, Service) callbacks will be invoked. That said, (since you're dealing with Activities) I recommend to store all persistent data as per the documentation, in onPause().
If the Application class is killed on low memory pressure and the app comes to foreground again, how can I know in its onCreate() that the app has been recreated after a system kill?
You can't recognize it in Application's onCreate().
As far as I know, you can't handle the application killed event. Here is a quote from the Application's onTerminate method:
This method is for use in emulated process environments. It will never
be called on a production Android device, where processes are removed
by simply killing them; no user code (including this callback) is
executed when doing so.
The general idea is that you shouldn't care whether the application was killed or not. If it was, the OS will restart the app next time it is needed otherwise it will be resume (and you'll use the Activity / Fragment lifecycle events to achieve this).
What data do you need to store - is it possible to store it earlier (when it is received from web service and so on) instead of waiting for the last moment?
Related
I am developing a simple app that just play a white noise sound in background while I am doing other things.
It works very well when I switch to other apps ( like games, chrome browser, etc ) but sometimes ( for example when there are many chrome tab opened ) the white noise sound stop and I need to reload my app.
I am NOT using Services, is this the reason ?
Because your apps is getting killed by the system to give up resources for to other apps (games, chrome, etc). So you need to use a Service.
Here an excerpt from Processes and Application Life Cycle
for more details explanation:
An unusual and fundamental feature of Android is that an application
process's lifetime is not directly controlled by the application
itself. Instead, it is determined by the system through a combination
of the parts of the application that the system knows are running, how
important these things are to the user, and how much overall memory is
available in the system.
...
A cached process is one that is not currently needed, so the system is free to kill it as desired when memory is needed elsewhere. In a
normally behaving system, these are the only processes involved in
memory management: a well running system will have multiple cached
processes always available (for more efficient switching between
applications) and regularly kill the oldest ones as needed. Only in
very critical (and undesirable) situations will the system get to a
point where all cached processes are killed and it must start killing
service processes. These processes often hold one or more Activity
instances that are not currently visible to the user (the onStop()
method has been called and returned). Provided they implement their
Activity life-cycle correctly (see Activity for more details), when
the system kills such processes it will not impact the user's
experience when returning to that app: it can restore the previously
saved state when the associated activity is recreated in a new
process.
I think Services is What You are looking For.
A Service is an application component that can perform long-running
operations in the background, and it does not provide a user
interface.
For better chance of preventing OS to kill your app, you should use a
Foreground Service
following the official guide here: https://developer.android.com/guide/components/services.html#Foreground
Remember that there is no way to be certain that OS will never kill your app, because when RAM becomes really low it could kill every process indipendently from type, following his priority rules
I have noticed that the facebook android app is extremely resilient and cannot be shut down. Even though I have forced stop the application and killed all its associated services, it is somehow able to magically restart itself after a while.
This leads me to the questions:
1) How do I actually stop the app and all facebook services without uninstalling it.
2) What methodology does the app apply to prevent itself from getting killed (i.e. how do you program something similar in android)?
1) How do I actually stop the app and all facebook services without
uninstalling it.
Process termination is executed whenever Android needs more resources to handle logic of another processes of higher priority.
How does it apply to the Android's Service?
The Service returns specific code in onStartCommand():
START_STICKY - briefly speaking, once the application's process is killed by returning this constant we ask the OS to restore the application's Service whenever available resources appear. Thus, the application's process is recreated.
START_NOT_STICKY - once the application's process is killed by returning this constant we tell the OS to not to bother about our Service recreation.
START_REDELIVER_INTENT - same as START_STICKY but with subtle distinction. Whenever our Service is restored we demand to have the onStartCommand() with same Intent we delivered for the last time before termination.
The explanation for your observations could be that Facebook uses aforementioned constants to bring Services back to work.
2) What methodology does the app apply to prevent itself from getting
killed (i.e. how do you program something similar in android)?
Few things are worth remembering whenever we want to prevent our application from being a first candidate to be terminated:
Relying on Activity.onLowMemory() or Application.onLowMemory() methods - if we hide the application to the background or abandon it then this method is invoked. In this case it is worth releasing resources including:
Caches or Cache entries (e. g. LruCache),
Expensive objects (Bitmap, temporary POJOs, etc.)
unregistering dynamic BroadcastReceivers
Unregistering statically declared broadcast receivers whenever we don't need them.
Preventing application from having memory leaks - most of the processes leaking their memory are undisputably the first ones to be terminated by the system.
Preventing from objects creation and designing our code to be immutable (book) (link)
organizing our HTTP requests in batches (link) (link) (link) (link) instead executing them on demand.
Hope that helps somehow.
I have a simple app with native code. That is, an Activity plus native code.
When the activity is entering background, I keep the native code running to do some processing. The problem is when the activity is killed by OS (due to low resource), JNI code seems to have no knowledge of what happened in Java land and still doing its job, hence wasting resource. Why does Android kill just the Activity instead of the whole process? and in this case, how does native code know that the activity was killed? OnDestroy() may not get called.
An Activity in an Android application is described in the documentation as
An activity is a single, focused thing that the user can do.
It is usually something that is visible on screen and has the user's attention. It has associated with it a state-machine that describes the life-cycle of being shown and hidden when another activity become active. The operating system is at liberty to start and stop activities as it choses - and memory permits.
In addition, a key point of the Android architecture is that activities and services are reusable software components and do not necessarily have a one-one relationship to processes. Inside the same process as your activity may be a service in use by another process in the system.
If the JNI portion of your code is still active in the background when an activity has received an onPause(), onStop(), onDestroy() notifications, it can only be because you haven't forwarded these messages to it. The system certainly doesn't know how to clean up native code's resource utilisation - particularly memory allocated with new() or malloc(). Unless you free it, it will only ever be recovered upon process termination.
If your concern is that your activity is not being killed fast enough by the system and as a result holding references to resources in native-land, it's a good sign that the system isn't resource limited.
You might consider implementing the native portion of your application as a Service and have it self-destruct after short periods on dis-iuse.
You could have multiple Activities in one Android Application. As your Activities go into the background, they can be killed to reclaim resources. The application is typically kept around until the phone runs really low on memory, or the user goes and kills your app manually. The process sticks around until the application is killed, roughly speaking.
Because you can continue processing in the background, when your Activity is re-created you can check the status of your global variables and perhaps pick up where you left off.
Keep in mind that Activities are killed quite often, so there's not much point to doing processing in the background but stopping when the Activity is killed. You might as well stop when onStop() is called in this case.
My Problem
I have a Service within which I monitor location changes. Its vital this stays running when in the background so it is a Foreground service.
My problem is whilst its in the background and things are getting destroyed, how do I save this data.
My Question
This brings me onto my potential solution.
I have a subclass of Application which I declare in my manifest file.
Would it be safe to see that any objects stored in this Singleton would be accessible throughout my Service's life and therefore give me a means to save my locations?
Thanks in advance
The short answer to your question is yes, Application basically lives as long as your process does so anything that you store there is as stable as it can be in memory until such time that Android may need to reclaim your app from the background to get more memory for a foreground application. However, not much benefit is added over simply saving your state data inside the Service itself. Android does not have a mechanism by which components out of an application are selectively destroyed to reclaim memory. If it needs additional memory to keep the foreground process happy, it simply kills the entire process of other apps in order of priority (based on recent use and their foreground/background priority state).
By having a running Service in your process, your application has already promoted its priority to be more important than other apps in the system that are in the background, reducing the likelihood that your process gets killed. By making your Service run as foreground, you've only slightly increased this priority level further and it's not the sort of thing Google recommends you do for long periods of time. When the system comes under enough memory pressure that apps start getting killed, eventually your process will suffer the same fate.
If you truly need any of your data to live beyond the life of your process, you need to persist it into any of Android's local storage formats.
I would say no. Even if you have a static class with static variables that you are setting, you have no guarantee that the OS will not arbitrarily kill your process at any time it chooses. Maybe 99% of the time what you are saying may work but it would not be a solid solution in my opinion.
You should, as suggested, store any important data in a database or in the android preferences, which ever is more logical for your application/data.
The Application object is the longest-lived object in the Android lifecycle. So yes, it has a lifespan at least as long as your Service. I'm unsure how it helps you save anything, though. Once Android kills your process -- and it will at some point, foreground service or no -- you'll still have to reload or recreate your data when your Service is next created.
Is there something in the Android developer guidelines that disuades developers from providing the option to "exit" (stop running) an application from within the application itself?
I love multitasking and all but it's not clear to me why:
the vast majority of apps don't have their own Exit functions and hence just keep running forever
don't give you a choice about running when you turn on the phone - they just do by default
Both of these things lead to memory usage constantly increasing and your device running with this performance burden all of the time despite the fact that you may only want certain apps to run some of the time.
Am I missing something?
Is there something in the Android
developer guidelines that disuadea
developers from providing the option
to "exit" (stop running) an
application from within the
application itself?
Yes. It is generally not needed, just as it is generally not needed to restart a Web server because some user with a browser decided (s)he is done with a Web app.
the vast majority of apps don't have
their own Exit functions and hence
just keep running forever
They don't keep running forever. Android will close things up as needed.
don't give you a choice about running
when you turn on the phone - they just
do by default
Those developers aren't paying attention to me.
Both of these things lead to memory
usage constantly increasing
Generally, it doesn't. If you find specific apps that do this, uninstall them.
and your device running with this
performance burden all of the time
Generally, it doesn't. If you find specific apps that do this, uninstall them.
Also, this question is a duplicate of this one.
"Both of these things lead to memory usage constantly increasing"
Which doesn't matter since Android apps are limited to a fixed amount of RAM. Freeing RAM won't give more RAM to other apps.
Essentially, there's no need for a quit button as long as the developer does a good job of designing their app. Android activities are stopped when they aren't visible and resources are needed elsewhere, so the are no longer consuming resources. You can read about the lifecycle here:
Here's a related question:
From Google's Android Application Fundamentals page:
Shutting down components
A content provider is active only while it's responding to a request from a ContentResolver. And a broadcast receiver is active only while it's responding to a broadcast message. So there's no need to explicitly shut down these components.
Activities, on the other hand, provide the user interface. They're in a long-running conversation with the user and may remain active, even when idle, as long as the conversation continues. Similarly, services may also remain running for a long time. So Android has methods to shut down activities and services in an orderly way:
An activity can be shut down by calling its finish() method. One activity can shut down another activity (one it started with startActivityForResult()) by calling finishActivity().
A service can be stopped by calling its stopSelf() method, or by calling Context.stopService().
Components might also be shut down by the system when they are no longer being used or when Android must reclaim memory for more active components. A later section, Component Lifecycles, discusses this possibility and its ramifications in more detail.
So it seems like Content Providers and Broadcast receivers should never be explicitly shut down, as they are inert while not handling their specific events.
As for Activities, I would argue in favor of having an end to it, but in certain cases. If your app has a finite state in which the user is done using it, why keep it alive until GC gets it? The activity manager still needs to keep track of that Activity while the user has finished their task. My best example for this is the Calculator. You open it, you have it solve a problem for you, and then you close it. If the onCreate function is so expensive that it's more effective to do onCreate once and then onRestart whenever the user moseys back to your application then you're probably doing something wrong. Maybe I'm misinterpreting how Android handles Activities, and if so I'm always interested in learning more :)
It all comes back to the answer that users want total control of their running and auto-start list and what they do and don't want installed, example: google maps, etc etc. there are no two ways about this.