This will eventually get to your question, but I first want to address a number of issues you raise in your various comments to the various answers already given at the time of this writing. I have no intention of changing your mind -- rather, these are here for others who come to read this post in the future.
The point is that I cannot allow for Android to determine when my app is going to be terminated. that must be the choice of the user.
Millions of people are perfectly happy with the model where the environment closes up the application as needed. Those users simply don't think about "terminating" the Android app, any more than they think about "terminating" a Web page or "terminating" a thermostat.
iPhone users are much the same way, in that pressing the iPhone button does not necessarily "feel" like the app was terminated since many iPhone apps pick up where the user left off, even if the app really was shut down (since iPhone only allows one third-party app at a time, at present).
As I said above, there is a lot of things going on in my app (data being PUSHed to the device, lists with tasks that always should be there, etc.).
I don't know what "lists with tasks that always should be there" means, but the "data being PUSHed to the device" is a pleasant fiction and should not be done by activity in any case. Use a scheduled task (via AlarmManager
) to update your data for maximum reliability.
Our users log in and can't be doing that every time they get a phone call and Android decides to kill the app.
There are many iPhone and Android applications that deal with this. Usually, it is because they hold onto login credentials, rather than forcing users to log in every time manually.
For example, we want to check updates when exiting the application
That is a mistake on any operating system. For all you know, the reason your application is being "exited" is because the OS is shutting down, and then your update process will fail mid-stream. Generally, that's not a good thing. Either check updates on start or check updates totally asynchronously (e.g., via a scheduled task), never on exit.
Some comments suggest that hitting the back button does not kill the app at all (see link in my question above).
Pressing the BACK button does not "kill the app". It finishes the activity that was on-screen when the user pressed the BACK button.
It should only terminate when the users want to terminate it - never ever any other way. If you can't write apps that behave like that in Android, then I think that Android can't be used for writing real apps =(
Then neither can Web applications. Or WebOS, if I understand their model correctly (haven't had a chance to play with one yet). In all of those, users don't "terminate" anything -- they just leave. iPhone is a bit different, in that it only presently allows one thing to run at a time (with a few exceptions), and so the act of leaving implies a fairly immediate termination of the app.
Is there a way for me to really quit the application?
As everybody else told you, users (via BACK) or your code (via finish()
) can close up your currently-running activity. Users generally don't need anything else, for properly-written applications, any more than they need a "quit" option for using Web applications.
No two application environments are the same, by definition. This means that you can see trends in environments as new ones arise and others get buried.
For example, there is a growing movement to try to eliminate the notion of the "file". Most Web applications don't force users to think of files. iPhone apps typically don't force users to think of files. Android apps generally don't force users to think of files. And so on.
Similarly, there is a growing movement to try to eliminate the notion of "terminating" an app. Most Web applications don't force the user to log out, but rather implicitly log the user out after a period of inactivity. Same thing with Android, and to a lesser extent, iPhone (and possibly WebOS).
This requires more emphasis on application design, focusing on business goals, and not sticking with an implementation model tied to a previous application environment. Developers who lack the time or inclination to do this will get frustrated with newer environments that break their existing mental model. This is not the fault of either environment, any more than it is the fault of a mountain for storms flowing around it rather than through it.
For example, some development environments, like Hypercard and Smalltalk, had the application and the development tools co-mingled in one setup. This concept did not catch on much, outside of language extensions to apps (e.g., VBA in Excel, Lisp in AutoCAD). Developers who came up with mental models that presumed the existence of development tools in the app itself, therefore, either had to change their model or limit themselves to environments where their model would hold true.
So, when you write:
Along with other messy things I discovered, I think that developing our app for Android is not going to happen.
That would appear to be for the best, for you, for right now. Similarly, I would counsel you against attempting to port your application to the Web, since some of the same problems you have reported with Android you will find in Web applications as well (e.g., no "termination"). Or, conversely, someday if you do port your app to the Web, you may find that the Web application's flow may be a better match for Android, and you can revisit an Android port at that time.
I'd just like to add a correction here for the future readers of this thread. This particular nuance has escaped my understanding for a long time so I want to make sure none of you make the same mistakes:
System.exit()
does not kill your app if you have more than one activity on the stack. What actually happens is that the process is killed and immediately restarted with one fewer activity on the stack. This is also what happens when your app is killed by the Force Close dialog, or even when you try to kill the process from DDMS. This is a fact that is entirely undocumented, to my knowledge.
The short answer is, if you want to exit your application, you've got to keep track of all activities in your stack and finish()
ALL of them when the user wants to exit (and no, there is no way to iterate through the Activity stack, so you have to manage all of this yourself). Even this does not actually kill the process or any dangling references you may have. It simply finishes the activities. Also, I'm not sure whether Process.killProcess(Process.myPid())
works any better; I haven't tested it.
If, on the other hand, it is okay for you to have activities remaining in your stack, there is another method which makes things super easy for you: Activity.moveTaskToBack(true)
will simply background your process and show the home screen.
The long answer involves explanation of the philosophy behind this behavior. The philosophy is born out of a number of assumptions:
onSaveInstanceState
, but whaddya gonna do?) For most well-written Android apps this should be true, since you never know when your app is going to be killed off in the background.When you think about it, this is appropriate for the platform. First, this is exactly what happens when the process is killed in the background and the user comes back to it, so it needs to be restarted where it left off. Second, this is what happens when the app crashes and presents the dreaded Force Close dialog.
Say I want my users to be able to take a picture and upload it. I launch the Camera Activity from my activity, and ask it to return an image. The Camera is pushed onto the top of my current Task (rather than being created in its own Task). If the Camera has an error and it crashes, should that result in the whole app crashing? From the standpoint of the user, only the Camera failed, and they should be returned to their previous activity. So it just restarts the process with all the same Activities in the stack, minus the Camera. Since your Activities should be designed so that they can be killed and restored at the drop of a hat, this shouldn't be a problem. Unfortunately, not all apps can be designed that way, so it is a problem for many of us, no matter what Romain Guy or anyone else tells you. So, we need to use workarounds.
So, my closing advice:
finish()
on all activities or call moveTaskToBack(true)
.startActivity()
with an Intent that contains the Intent.FLAG_ACTIVITY_CLEAR_TOP
flag.All of my applications have quit buttons... and I quite frequently get positive comments from users because of it. I don't care if the platform was designed in a fashion that applications shouldn't need them. Saying "don't put them there" is kind of ridiculous. If the user wants to quit... I provide them the access to do exactly that. I don't think it reduces how Android operates at all and seems like a good practice. I understand the life cycle... and my observation has been that Android doesn't do a good job at handling it.... and that is a basic fact.
Stop thinking of your application as a monolithic application. It is a set of UI screens that the user can interact with your "application", and "functions" provided via Android services.
Not knowing what your mysterious app "does" is not really important. Let's assume it tunnels into some super secure corporate intranet, performing some monitoring or interaction and stays logged in until the user "quits the application". Because your IT department commands it, users must be very conscious of when they are IN or OUT of the intranet. Hence your mindset of it being important for users to "quit".
This is simple. Make a service that puts an ongoing notification in the notification bar saying "I'm in the intranet, or I am running". Have that service perform all the functionality that you need for your application. Have activities that bind to that service to allow your users to access the bits of UI they need to interact with your "application". And have an Android Menu -> Quit (or logout, or whatever) button that tells the service to quit, then closes the activity itself.
This is, for all intents and purposes exactly what you say you want. Done the Android way. Look at Google Talk or Google Maps Navigation for examples of this "exit" is possible mentality. The only difference is that pressing back button out of your activity might leave your UNIX process lying in wait just in case the user wants to revive your application. This is really no different than a modern operating system that caches recently accessed files in memory. After you quit your windows program, most likely resources that it needed are still in memory, waiting to be replaced by other resources as they are loaded now that they are no longer needed. Android is the same thing.
I really don't see your problem.
This is an interesting and insightful discussion with so many experts contributing. I feel this post should be looped back from within the Android development main website, because it does revolve around one of the core designs of the Android OS.
I would also like to add my two cents here.
So far I have been impressed with Android's way of handling lifecycle events, bringing the concept of a web-like experience to native apps.
Having said that I still believe that there should be a Quit button. Why? ... not for me or Ted or any of the tech gurus here, but for the sole purpose of meeting an end user demand.
Though I am not a big fan of Windows, but long back they introduced a concept that most end users are used to (an X button) ... "I want to quit running a widget when 'I' want to".
That does not mean someone (OS, developer?) will take care of that at its/his/her own discretion... it simply means "where is my Red X button that I am used to". My action should be analogous to 'end a call on pressing of a button', 'turn off the device by pressing a button', and so on and so forth ... it's a perception. It brings a satisfaction per se that my action indeed achieve its purpose.
Even though a developer can spoof this behavior using suggestions given here, the perception still remains i.e. an application should completely cease to function (now), by an independent, trusted and neutral source (OS) on demand from the end user.
You can quit, either by pressing the Back button or by calling finish()
in your Activity
. Just call finish()
from a MenuItem
if you want to explicitly kill it off.
Romain isn't saying it can't be done, just that it's pointless — users don't need to care about quitting or saving their work or whatever, as the way the application lifecycle works encourages you to write smart software that automatically saves and restores its state no matter what happens.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With