unable to reopen Android App after this.finish() - android

My Android App is getting a bit hefty and it runs slow. I haven't got round to optimizing yet. I'm still ironing out some bugs.
Just some background: my app is a game, that the user can win or lose (naturally). I havent made a "win sequence" or "lose sequence yet" so I just put the code in
if(userWins())
this.finish();
where the app exits abruptly. Nothing wrong so far. But, when I try to open the app again I get a blank screen, when I should get option buttons. If I turn off my phone and turn on again I can use the app, but otherwise I can't. I have no idea why this is.
Side note: My copy of AngryBirds has a similar problem. If I exit the game screen "improperly" (i.e. while in the middle of a game, not in the options menu) I cannot turn on the app again until I reboot my phone.

When you call finish() Android don't kill the process yet. In case you restart your application, the process will be kept running unless the OS need the ressources.
see: http://developer.android.com/reference/android/app/Activity.html#ProcessLifecycle
This is why it works when you reboot. (you do not need to reboot, just kill the process using adb shell kill <PID> or a task killer if you aren't root)
Your application is likely leaving some variables initialized with old values, and when you restart your activity you find yourself in an unstable state with variables pointing to the old data and other variables to newly initialized data.
You need to either set the old data to null in the onDestroy() event, either ensure initialisation is done in the onCreate() event. You choose wich one depending on if the data can be reused or not.
Look for singletons, or for this kind of initialisation structures:
if (mVar == null) {
mVar = "stuff";
}

Related

How does Android go about freeing up memory when low, and how does it restart them?

Please note the following vocabulary to avoid confusion
1) When I say reinstantiating an activity, I mean Activity.onCreate(bundle)
2) When I say starting from scratch an activity, I mean Activity.onCreate(null)
(Although I am not sure it makes a difference) For the purposes of this post, please assume that the Android applications I am interested in all have their activities launched in the same task
How does Android go about freeing memory from apps?
Lets say I have a phone. I am using many applications at once. I got bored of the current Snapchat application. So I press the home button and open Facebook. Note that I did not press the back button, and so Snapchat lives on in the recent apps overview.
Suddenly for some reason the phone is very low on memory and needs to start forcefully freeing up some from background apps.
Will the Android OS kill some activities of Snapchat in order to free memory
Will the Android OS kill all activities of Snapchat in order to free memory
How does Android go about managing "killed" apps?
Now lets say I want to go back to Snapchat. I hit the overview button and select Snapchat from the scrolling list of recently used apps.
Will the Android OS reinstantiate some activities of Snapchat
Will the Android OS reinstantiate all activities of Snapchat
Will the Android OS reinstantiate zero activities of Snapchat and just starting from scratch with the initial launcher activity.
TL;DRD: all activities are killed.
The ActivityManagerService doesn't seem to kill anything anymore (it just forces GC calls and dispatches trim events).
if (false) {
// For now we won't do this; our memory trimming seems
// to be good enough at this point that destroying
// activities causes more harm than good.
if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
&& app != mHomeProcess && app != mPreviousProcess) {
// Need to do this on its own message because the stack may not
// be in a consistent state at this point.
// For these apps we will also finish their activities
// to help them free memory.
mStackSupervisor.scheduleDestroyAllActivities(app, "trim");
}
}
Though when (if) it did try to kill something it would kill the whole process of a background app (it would simply call kill -9 [PID]). And since by default all your activities are run under one PID they all get destroyed when a process dies.
The same goes to the OOM and Low Memory Killers - the two operate with processes and make no distinction between your activities.
Please note, however, that some people claim that Android sometimes kills particular activities one by one on low memory. I failed to find any evidence of that in AOSP.
==============
Now, about restoring your app. I might not be an expert here cause this is connected to the Android's "Tasks and Back Stack System" which is way trickier than their tutorial videos make it seem.
The operation starts with calling ActivityManager#moveTaskToFront(...) and it eventually leads us to ActivityManagerService#moveTaskToFrontLocked(...)
There the OS will try to retrieve the stored task record associated with your app. If your app's been destroyed, the manager will have to go to ActivityStackSupervisor#restoreRecentTaskLocked(...) and if all goes well it's gona find the task and the back stack and do this for every activity in the task:
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
mWindowManager.addAppToken(0, r.appToken, task.taskId, stack.mStackId,
r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
}
The same method (WindowManager#addAppToken(...)) is called when you start a new activity and it goes with a comment:
// Here it is! Now, if this is not yet visible to the
// user, then just add it without starting; it will
// get started when the user navigates back to it.
So my guess is that when the OS restores an app it recreates the activity stack fully but only the topmost activity actually actually gets restarted. I guess, it's easy to set up an experiment to find out if I'm right here.
=======
One more update :) Yep, these two methods (ActivityStackSupervisor#resumeTopActivitiesLocked() and ActivityStackSupervisor#resumeTopActivityLocked(...)) are called a bit later. Though I really don't undesratnd why they resume activities in more than one stack - as I said, I'm definitely not an expert here.

Why is it a bad idea to exit an Android application? [duplicate]

Moving on in my attempt to learn Android, I just read the following:
Question: Does the user have a choice to kill the application
unless we put a menu option in to kill it? If no such option exists,
how does the user terminate the application?
Answer: (Romain Guy): The user doesn't, the system handles this automatically. That's what the activity lifecycle (especially onPause/onStop/onDestroy) is for. No matter what you do, do not put a "quit" or "exit" application button. It is useless with Android's application model. This is also contrary to how core applications work.
Hehe, for every step I take in the Android world I run into some sort of problem =(
Apparently, you cannot quit an application in Android (but the Android system can very well totally destroy your app whenever it feels like it). What's up with that? I am starting to think that it's impossible to write an app that functions as a "normal app" - that the user can quit the app when he/she decides to do so. That is not something that should be relied upon the OS to do.
The application I am trying to create is not an application for the Android Market. It is not an application for "wide use" by the general public, it is a business app that is going to be used in a very narrow business field.
I was actually really looking forward to developing for the Android platform, since it addresses a lot of issues that exist in Windows Mobile and .NET. However, the last week has been somewhat of a turnoff for me... I hope I don't have to abandon Android, but it doesn't look very good right now =(
Is there a way for me to really quit the application?
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:
First of all, this only happens when your app is in the foreground. If it is in the background the process will terminate just fine. However, if it is in the foreground, the OS assumes that the user wants to keep doing whatever he/she was doing. (If you are trying to kill the process from DDMS, you should hit the home button first, and then kill it)
It also assumes that each activity is independent of all the other activities. This is often true, for example in the case that your app launches the Browser Activity, which is entirely separate and was not written by you. The Browser Activity may or may not be created on the same Task, depending on its manifest attributes.
It assumes that each of your activities is completely self-reliant and can be killed/restored in a moment's notice. (I rather dislike this particular assumption, since my app has many activities which rely on a large amount of cached data, too large to be efficiently serialized during 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.
The final factor is not so much an assumption, but rather a limitation of the OS: killing the app explicitly is the same as the app crashing, and also the same as Android killing the app to reclaim memory. This culminates in our coup de grace: since Android can't tell if the app exited or crashed or was killed in the background, it assumes the user wants to return where they left off, and so the ActivityManager restarts the process.
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:
Don't try to kill the process. Either call finish() on all activities or call moveTaskToBack(true).
If your process crashes or gets killed, and if, like me, you need the data that was in memory which is now lost, you'll need to return to the root activity. To do this, you should call startActivity() with an Intent that contains the Intent.FLAG_ACTIVITY_CLEAR_TOP flag.
If you want to kill your app from the Eclipse DDMS perspective, it had better not be in the foreground, or it will restart itself. You should press the Home button first, and then kill the process.
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.
This debate boils down to the age-old question of whether the developers know best or whether the user knows best. Professional designers in all areas of human factors struggle with this every day.
Ted has made a point in that one of the most downloaded apps on the Market is the 'App Killer'. People get a bit of extra serotonin when they quit applications. They're used to it with a desktop/laptop. It keeps things moving fast. It keeps the processor cool and the fan from turning on. It uses less power.
When you consider that a mobile device is a much smaller ship, then you can especially appreciate their incentive to 'throw overboard what you no longer need'. Now the developers of Android have reasoned that the OS knows best and that quitting an app is antique. I wholeheartedly support this.
However, I also believe that you should not frustrate the user, even if that frustration is borne out of their own ignorance. Because of that, I conclude that having a 'Quit' option is good design, even if it is mostly a placebo button that does nothing more than close a View.
Ted, what you are trying to accomplish can be done, perhaps just not how you are thinking of it right now.
I suggest you read up on Activities and Services. Stop using the term "app" and start referring to the components, i.e. Activity, Service. I think you just need to learn more about the Android platform; it is a change in mindset from a standard PC app. The fact that none of your posts have had the word "Activity" (short of a FAQ quote, i.e. not your words) in them tells me you need to read some more.
Blog post When to Include an Exit Button in Android Apps (Hint: Never) explains it far, far better than I can. I wish every Android developer has read it already.
Excerpts:
In my experience what [the users] really want is:
An unambiguous way to guarantee that an app will stop consuming resources (battery, CPU cycles, data transfer, etc.).
Many users perceive that an exit button implements this requirement
and ask for it to be added. Developers, looking to please their users,
obligingly add one. Shortly thereafter they both fail.
In most cases the exit button simply calls Activity.finish(). This is exactly equivalent to hitting the back button.
Exactly. Services keep running and polling keeps happening. Users may think they've killed the app but they haven't, and soon
they'll be even more annoyed.
Exit behavior is now ambiguous. Should your exit button just close the Activity, or should it also stop all associated Services, Receivers, and Alarms? What should Back do? What happens if they hit Home instead? What happens if your app has a widget? Should the exit button stop that from updating too?
The solution is to make the back button behave as you'd expect the
exit button to. Better yet, simply stop consuming resources whenever
the app isn't visible.
Go ahead and read the complete article.
Answer: (Romain Guy): The user doesn't, the system handles this
automatically. That's what the activity lifecycle (especially
onPause/onStop/onDestroy) is for. No matter what you do, do not put a
"quit" or "exit" application button. It is useless with Android's
application model. This is also contrary to how core applications
work.
1: Totally exiting an application may be generally unmandatory, but it is not useless. What if windows had no exit option? System would be doggy slow as memory was full and the OS had to guess at which programs you were done with. I don't care what Romain Guy or even Larry Page and Sergey Brin say - these are unquestionable facts: Systems run slower when they have to kill tasks to get their memory before a new app can be launched. You just can't tell me that it doesn't take time to kill an app! Even the light from distant stars take time... There is some use in allowing the user to fully close apps.
2: Contrary to how core applications work? What's that supposed to mean? When I'm done running an app for now, it is no longer doing any work...It's just waiting to be killed by the OS when its memory is needed.
In summary, there is a distinct difference between minimizing and exiting, and neither pinch hits well for the other. Do we leave a screwdriver in every screw? Or a key in every door? Do we leave all of our appliances on high until the breaker blows and we need to turn on another appliance? Do we leave the dish washer full of dishes, and only take out enough each time to make room for some new dirty ones? Do we leave all the cars running in the driveway until -- oh never mind.
If the user wants to minimize an app, then the best thing is to minimize it. If a user wants to exit an app, then by all means it is best to exit.
Is it frowned on? That's Android's view - they frown on it. And many many independent rookie Android developers frown on it.
But when it comes right down to it, there is good coding and bad coding. There is good program flow models and there are bad program flow models.
Leaving programs in memory when the user knows they are done with them simply is not good program flow. It serves absolutely no purpose whatsoever, and it slows things down when launching new apps or when running apps allocate more memory.
It is sort of like your car: There are times when you leave it running, like stopping at a stop light, or perhaps the fast food drive through, or stopping at the ATM. But there are other situations where you do want to shut it off - like when you get to work, or the grocery store or even home.
Similarly, if you're playing a game and the phone rings, yes. Pause the game and keep it running. But if the user is done with the game for a while, then by all means let them exit.
The exit button on some applications should be more out in front than others. Games, for example, or programs where the user is likely to want to fully exit, should have an obvious exit. Other programs, like, perhaps, email programs, where exiting is an unlikely desire (so that it can keep checking for email) -- these programs should not waste prime control input screen space with an exit option, but for good program flow, it should have an exit option. What if someone decides they don't want their mail program trying to check email when they are in poor coverage area, or maybe in a Skype call or whatever? Let them exit the email program if they want!
Suspending and exiting are two vital tasks and neither fulfills the role of the other.
If you are unable to fathom how to make your data/connections (and thereby your "application") persistent, then you will be unable to do what you "need" to do with Android.
Those who do download those cutesy little App Killers usually find they do not help battery life or memory usage, but hinder the OS from doing it's job of managing memory efficiently...
http://android-developers.blogspot.com/2010/04/multitasking-android-way.html
I think the point is that there is no need to quit the app unless you have buggy software. Android quits the app when the user is not using it and the device needs more memory. If you have an app that needs to run a service in the background, you will likely want a way to turn the service off.
For example, Google Listen continues to play podcast when the app is not visible. But there is always the pause button to turn the podcast off when the user is done with it. If I remember correctly, Listen, even puts a shortcut in the notification bar so you can always get to the pause button quickly. Another example is an app like a twitter app for instance which constantly polls a service on the internet. These types of apps should really allow the user to choose how often to poll the server, or whether even to poll in a background thread.
If you need to have code that runs on exit, you can override onPause(), onStop(), or onDestroy() as appropriate.
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
I would consider reading "Android Wireless Application Development" published by Addison-Wesley. I am just finishing it up and it is VERY thorough.
It appears that you have some fundamental misunderstandings of the Android platform. I too was a little frustrated at first with the application life-cycle of Android apps, but after coming to a greater understanding, I have come to really enjoy this approach. This book will answer all of your questions and much more. It really is the best resource I have found for new Android developers.
Also, I think you need to let go of a line-for-line port of the existing app. In order to port your application to the Android platform, some of the application design is going to change. The application-lifecycle used is necessary as mobile devices have very limited resources relative to desktop systems and allows Android devices to run several applications in an orderly and resource-aware fashion. Do some more in depth study of the platform, and I think you will realize that what you are wanting to do is entirely feasible. Best of luck.
By the way, I am no way affiliated with Addison-Wesley or any person or organization associated with this book. After re-reading my post I feel that I came off a little fanboyish. I just really, really enjoyed it and found it extremely helpful. :)
Almost 99% of the time there is no need for an Android application to take over its own life cycle. Most of the time it comes down to better planning or smarter design of the application. For example, rather build an internal service (not exported) to handle downloads, etc., or design actions and tasks around user workflow.
But that being said, where there is a will there is a way. Android provides - through the android.os.Process class, a much better API than Java to control the underlying process. And unlike Java it does not treat the developer like a moron by hiding it all behind a simple java.lang.System.exit() call.
So how do you ask your application to commit suicide in Android? Well, the trick is simple:
Create your own Android application class by inheriting from the standard android.app.Application class (remember to declare it in the AndroidManifest.xml file).
Override the onCreate() method, and store the process ID which started your application:
this.pid = android.os.Process.myPid(); // Save for later use.
Now to kill your application, provide a kill() method:
android.os.Process.sendSignal(pid, android.os.Process.SIGNAL_KILL);
Now whenever you need your app to commit suicide just type cast the application context, and call your kill method!
((MySuicidalApp) context.getApplicationContext()).kill()
Just remember that due to the process management policies in Android, specifically related to services, Android may just opt to restart your service (see You should not use task killers on Android).
When I conceive an application in Android, I see it this way:
You are working with your application
The phone rang
You take the call
At the end of the call, you come back to your application at the same place you were
To do that, you only need the Back button or the Home button of your phone (either by short or long press) and the notification bar.
When I exit my application, I only use the Back button until I am out of it or the Home button.
That's how most of the applications are conceived I think. But if I need some sort of session or connection, I made it clear to the user with a login/logout button and notification (title bar or anything else). This is a rather different style than the pure "exit" style application.
On PCs, you have a multi-GUI desktop, and on Android, you obviously have multi-tasks, but you only display one app at a time (I don't consider widgets here ^^). And on a mobile phone, at anytime, you could have a notification for something more important than what you are doing.
So the whole concept of an application rely on something different that "enter application - work - exit application".
Hmmmm...
I think that you just don't see the Android app the right way. You can do something almost like what you want easily:
Do the app activities save/restore state like it is encouraged in the developer livecycle documentation.
If some login is needed at the restore stage (no login/session information available) then do it.
Eventually add a button/menu/timeout in which case you will do a finish() without saving the login and other session info, making implicitly the end of app session: so if the app is started/brought to front again it will start a new session.
That way you don't really care if the app is really removed from memory or not.
If you really want to remove it from memory (this is discouraged, and BTW for what purpose?) you can kill it conditionally at the end of onDestroy() with java.lang.System.exit(0) (or perhaps restartPackage(..)?). Of course do it only in the case where you want to "really end the app", because the onDestroy() is part of the normal lifecycle of activities and not an app end at all.
As an Application in an Android context is just a bunch of vaguely related Activities, quitting an Application doesn't really make much sense. You can finish() an Activity, and the view of the previous Activity in the Activity stack will be drawn.
I agree with Ted. I understand that exiting the application is not the
"Android way", but it doesn't seem like it should be precluded. Here
are three reasons why you might want a real exit to the application (not
just the activity):
The user might want some control over which app gets killed in the
case of low memory. If important app A is running in the background,
then you might like to exit app B when you are done with it so
that app A doesn't get killed by the operating system.
If your application has sensitive data cached in memory, you might
like to kill the app so that a virus/worm/rogue app can't get at it. I
know the security model is supposed to prevent that, but just in case...
If your application uses resources (like network, CPU, sensors, etc.)
that could adversely affect the phone, then one way of ensuring that
those resources are freed up is to exit the application. I understand
that well-behaved apps should free up resources when they are not needed. But again, exiting the application seems like a reasonable way of ensuring that.
I hope things will change over time. The user should be able to kill an app or process if the app process is sandboxed correctly by the OS. There is a notion that apps should be written perfectly or user will use only the apps that follow all SDK recommendations. I think that is a tall order.
The Linux kernel has a feature called Out-of-memory killer (as mentioned above, the policies are configurable at the userspace level as well as the kernel is not an optimal one, but by no means unnecessary).
And it is heavily used by Android:
OOM killer is not for userspace
Android Notes (OOM Killer Info - where you can configure the OOM feature on Android)
Android Porting On Real Target
Some userspace apps are available to assist with these kill apps, for example:
Autokiller/Configuring Android's internal task killer
You apparently have found the answer you want in the finish() command. This will not remove your app from memory, but Android will do so whenever it needs the resources, so it doesn't make any difference that you won't be doing that explicitly.
I would only add that in order to attain the full effect that an application exit would typically have, you would want to reset the app's state to whatever its state is normally at the time it is first run after a boot of the device, just prior to calling finish() on all of your activities. That way, if the user selects your app again, it will appear to have been run "fresh," without any state left over from the point prior to the simulated "exit."
If there are some special actions that should only occur on "exit," such as saving the user's work or whatever, you can also perform them prior to the re-initialization part of the above routine.
This approach allows you to accomplish your goal of having an "exit" command without violating Android's philosophy of leaving the management of OS resources, including the closing of apps, in the hands of the operating system.
Personally, I would not use this approach, because Android users expect an app to preserve its continuity when they revisit it, and so they are not used to the modality of "exiting" an app. I would instead support a "clear" function that a user can invoke to reset the app to some default initial state, without the necessity of "leaving" it in the process.
The one exception would be when the user has hit the back button a sufficient number of times to cause the app to close. In that situation, there is no expectation on the user's part that state will have been saved (and if there is unsaved state in the app, then you, as the developer, should have code handling the back button that detects that unsaved data, and prompts the user to save it to SharedPreferences or to a file, or to some other non-volatile medium).
Regarding system.exit(0):
If you do decide to use system.exit(0) to close your app with rude finality (e.g., as a result of a final back button press), then I would warn you that although for me this "works," and in some cases has been the only way I've been able to close an app without any trace of it remaining, there is one minor glitch that occurs in Jelly Bean when you use this approach.
Specifically, if you use the Recent Apps list to open your app, and then use the back button to close the app (with that close implemented via system.exit(0)), the Recent Apps list will become visible again, as it will never have been closed. If you then tap on your app's entry in that list to run it a second time from the same, already-open, Recent Apps list, there will be no response.
I suspect that the cause of this is that the Recent Apps list is holding on to a reference to your app that has become non-functional due to your having closed the app using system.exit(0). A more civilized closing of your app using finish() might have informed the OS in a manner that would have allowed it to refresh its Recent Apps list, but system.exit(0) apparently does not do this.
This is not a huge problem in and of itself, as very few people will open an app from Recent Apps, then exit it, and then immediately open it again from the same open Recent Apps list. And if they tap the home button and then re-open the Recent Apps list, your app's entry will be there, and it will be fully functional. But I think that it shows that the use of system.exit(0) can interfere with proper communication between your app and the OS, and this suggests that there may be other, more serious, possibly subtle, consequences of using this approach.
The Android application life cycle is designed for mobile phone users, not computer users.
The app life-cycle is the brutally simplistic paradigm required to turn a Linux server into a consumer appliance.
Android is Java over Linux, a real cross-platform server OS. That is how it spread so quickly. The app life-cycle encapsulates the underlying reality of the OS.
To mobile users, apps are just installed or not installed. There is no concept of running or exiting. In fact, app processes are meant to run until the OS releases them for their held resources.
Since this is Stack Overflow, anyone reading this is a computer user and must turn off 90% of their knowledge to understand the mobile app lifecycle.
There is a (relatively) simple design which will allow you to get around the "exit" conundrum. Make your app have a "base" state (activity) which is just a blank screen. On the first onCreate of the activity, you can launch another activity that your app's main functionality is in. The "exit" can then be accomplished by finish()ing this second activity and going back to the base of just a blank screen. The OS can keep this blank screen in memory for as long as it wants...
In essence, because you cannot exit out to OS, you simply transform into a self-created nothingness.
Without an exit function for the application developer to kill their own application it is very bad design.
My application needs to allow the user to dynamically change data dynamically during runtime and the user needs to restart my application to make the change effect, but Android did not allow my application restart by itself. Android OS has a very bad design application life cycle.
For closing an app at any point use FLAG_ACTIVITY_CLEAR_TOP flag in Intent and then system.exit();
Or there is similar way, but without system.exit() when you want to exit call this method:
public void exit() {
startActivity(new Intent(this, HomeActivity.class).
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK).putExtra(EXIT_FLAG, true));
}
In your HomeActivity.onCreate() add following code
protected void onCreate(Bundle savedInstanceState) {
if (getIntent().getBooleanExtra(EXIT_FLAG, false)) {
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
finish();
}
}
......................
This will work without breaking the Android life-cycle.
First of all, never never never use System.exit(0). It is like making a person sleep punching him on the head!
Second: I'm facing this problem. Before sharing my solution a I want to share my thoughts.
I think that an "Exit Button" is stupid. Really really really stupid. And I think that users (consumer) that ask for an exit button for your application is stupid too. They don't understand how the OS is working and how is managing resources (and it does a great job).
I think that if you write a good piece of code that do the right things (updates, saves, and pushes) at the right moment and conditions and using the correct things (Service and Receiver) it will work pretty well and no one will complain.
But to do that you have to study and learn how things works on Android.
Anyway, this is my solution to provide to users an "Exit Button".
I created an Options Menu always visible in each activity (I've a super activity that do that).
When the user clicks on that button this is what happens:
Intent intent = new Intent(this, DashBoardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SharedPreferences settings = getSharedPreferences(getString(PREF_ID), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(FORCE_EXIT_APPLICATION, true);
// Commit the edits!
editor.commit();
startActivity(intent);
finish();
So I'm saving in SharedPreferences that I want to kill my app, and I start an Intent. Please look at those flags; those will clear all my backstack calling my DashBoard Activity that is my "home" activity.
So in my Dashboard Activity I run this method in the onResume:
private void checkIfForceKill() {
// CHECK IF I NEED TO KILL THE APP
// Restore preferences
SharedPreferences settings = getSharedPreferences(
getString(MXMSettingHolder.PREF_ID), Context.MODE_PRIVATE);
boolean forceKill = settings.getBoolean(
MusicSinglePaneActivity.FORCE_EXIT_APPLICATION, false);
if (forceKill) {
//CLEAR THE FORCE_EXIT SETTINGS
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(FORCE_EXIT_APPLICATION, false);
// Commit the edits!
editor.commit();
//HERE STOP ALL YOUR SERVICES
finish();
}
}
And it will work pretty well.
The only thing that I don't understand why it's happening is that when I do the last finish (and I've checked: it's following all the correct flow of onPause → onStop → onDestroy) the application is still on the recent activity (but it's blank).
It seems like the latest intent (that has started the DashboardActivity) is still in the system.
I've to dig more in order to also remove it.
It took me longer to read this Q&A than to actually implement a semi-proper Android Application Lifecycle.
It's a GPS app that polls for points and sends the current location to a webservice every few seconds using a thread... This could be polling every 5 minutes in Ted's case for an update, then onStop can simply start the update activity Ted was soo concerned about if one was found (asynchronous Ted, don't code like a Windows programmer or your programs will run like Windows programs ... eww, it's not that hard).
I did some initial code in onCreate to set up things for the activity lifetime, including checkUpdate.start();:
...
#Override
public void onStart() {
super.onStart();
isRemote = true;
checkUpdate.resume();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, luh);
}
#Override
public void onPause() {
isRemote = false;
checkUpdate.suspend();
locationManager.removeUpdates(luh);
super.onStop();
}
This code may be completely wrong, but it works. This is one of my first Android applications.
Voilà, an application that doesn't consume CPU when it's in the background, yet is instantly ready to reopen because it is in RAM (although not holding RAM as is the Android lifecycle) ... an app is always ready, it's a phone, guys/gals. If an app was to use up all the RAM and couldn't be shut down by the OS then the thing might stop ringing =P That's why the OS needs to be able to close your app when it's in the background (if your application isn't a resource hog it won't be closed BTW), so let's just write better applications.
Every time while you move to the next page through intent, use:
`YourActivityname.this.finish()`;
Example:
Intent intent = new Intent(getApplicationContext(), SMS.class);
startActivity(intent);
MainActivity.this.finish();
So that no activity will be running on background and when you want to Exit your app, use:
MainActivity.this.finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
getParent().finish();
This exiting worked like a charm for me :)
You have probably spent many years writing "proper" programs for "proper" computers. You say you are learning to program in Android. This is just one of the things you have to learn. You can't spent years doing watercolour painting and assume that oil painting works exactly the same way. This was the very least of the things that were new concepts to me when I wrote my first app eight years ago.
In any case, if you want to terminate your application you can always call System.exit(0);.

Android App Exit Button

I'm not sure whether I need to add an exit button to my app. Is there any point to doing this? And if on exiting one activity or service is not .finish() or closed properly could this cause a lot of damage?
You don't need to add en exit button. If you don't, your activity will just be kept in memory until the system reclaims it. It will not consume any cpu.
Of course, if you have any worker threads running you should stop them in onStop() or onPause(), depending on what your threads are doing.
Many applications add an exit button, for some reason. I guess the reason is that they don't trust themselves to write proper code or they don't trust the Android OS to clean up properly.
Not going through the correct finish procedures will not cause any damage to others than yourself.
Anyone who says you don't need an exit button is right but putting one in never hurts. Users like to see a way to exit to the application, it's not about bad programming, it's actually about proper programming, give the user an exit button and if they never use it great and if it's there even better.
You don't need an exit button in your app. This is how android works. The user is not given any way to actually exit the application.
When you call 'finish', the application stack is just pushed to the background. It still exists in the memory. Android itself decides when to close the application(i.e. remove its instance from the memory) and generally this is done when your application becomes the oldest application which was not used for the longest time.
No, you don't. Read up on the activity lifecycle at developer.android.com
On older versions of android you had to be careful not to accidentally leave a background service running and holding resources but that's been reworked.
Guys you're righteous, but there are some cases when Exit button may have a sense. Let's say you're keeping some application-wide global data in YourApplication class (child of Application), e.g. some sensitive data or so. When user closes final activity and it's destroyed Application won't be terminated. As read Android developer resource - developer should not rely on Application.onTerminate() method. You can easily check it - even in case when all activities closed Application still alive. Whenever Application instance alive it's relatively easy to get access to those object and collect data.
I have found 2 ways how to kill Application class instance:
null'ate all object references (which is hardly possible for large projects) then call garbage collection
call
android.os.Process.killProcess(android.os.Process.myPid());
So Exit button may have function to finish all activities, call garbage collection then call killProcess() - which will guarantee safe removing of global data stored in Application.
I agree with above post by barmaley.
Long story short, you don't need to exit your application if your concerns are related to the Android system itself. Don't worry, be happy. And that applies especially for lazy users (remember the old Symbian days).
However, if you have something in mind about your application itself, then please go ahead and do it. You can finish the activity, nullify and kill. Just be reasonable because, as always, common sense is going to be better than all the tutorials and references in the world.
Anyway, just my 2c.
From a technical perspective, no, you don't need to add a quit button for all the very good reasons listed here.
Unfortunately users aren't informed in this way and regularly drop review scores because they have to 'use a task killer' or 'force close' your app.
It is a regular request and criticism in reviews/feedback for my app. So it may be necessary to appease users.
I think an exit button can provide the user with assurance that your app is closed.
I know, that it still doesn't mean that the app is definitely closed, but if the user feels more in control with an exit button then I say it is a good idea.
When I first started coding for Android, I thought it was a good idea to manually exit my main activity. What I discovered is that closing the activity via stopSelf leads to corrupt instanceState data, which caused a lot of ANRs when the activity was opened again.
The Activity Lifecycle document is information directly from the Google framework engineers. Every word is for a reason.
Consider that garbage collection takes cpu. This may seem trivial, but in designing a framework for a mobile platform, wouldn't you try to cache as much in memory as possible in case it was needed again, as cpu time = battery, and loading from flash is expensive?
GCing an entire app is non-trivial. Especially when the activity might be used repeatedly. The design had to consider all possible use cases. Cacheing makes sense. The system is designed with this principle.
I would say that not following the Activity Lifecycle document is asking for problems.
Some apps alter the configuration of the device while running or consume lots of CPU or data. You may want to give users an option to Exit the app altogether.
There are proper usecases for an Exit button.
For example, an app i made also needs to manage WiFi networks: the device configuration is changed continuously. Terrific and all while app is in active use, in this case a user would expect the behavior to effectively stop after exiting the application.
So my application has an Exit button mainly to cleanup the WiFi configs it created. I could make a button Stop and Cleanup, but no user would understand. They just want to turn the app off, thus Exit.
App running: wifi managed by app.
App exited: diy/android wifi.
Right now, choosing Exit in my application does the cleanup followed by a finish(), but the application itself lingers in the background. Functionally ok but confusing users. I could make a toggle action named "wifi feature on/off" but that wont make things simpler.

Close Android Application [duplicate]

This question already has answers here:
Is quitting an application frowned upon?
(40 answers)
Closed 9 years ago.
Please suggest how I may close my whole Android Application with one line code.
Yes - Why, then how(sort of):
Short answer:
System.exit(0);
This nicely and cleanly terminates the whole java machine which is dedicated to running the app. However, you should do it from the main activity, otherwise android may restart your app automatically. (Tested this on Android 7.0)
Details and explanation of why this is a good question and a programmer may have a very legitimate reason to terminate their app this way:
I really don't see the gain in speaking harshly to someone who's looking for a way to terminate their app.
Good is a friendly reminder to beginners that on Android you don't have to worry about closing your app -- but some people actually do want to terminate their app even though they know that they don't have to -- and their question of how to do so is a legitimate question with a valid answer.
Perhaps many folks live in an ideal world and don't realize that there's a real world where real people are trying to solve real problems.
The fact is that even with android, it is still a computer and that computer is still running code, and that it is perfectly understandable why someone may wish to truly exit their "app" (i.e. all of the activities and resources belonging to their app.)
It is true that the developers at Google designed a system where they believed nobody would ever need to exit their app. And maybe 99% of the time they are right!
But one of the amazing things about allowing millions of programmers to write code for a platform is that some of them will try to push the platform to its limits in order to do amazing things! -- Including things that the Android Developers never even dreamed of!
There is another need for being able to close a program, and that is for troubleshooting purposes. That is what brought me to this thread: I'm just learning how to utilize the audio input feature to do realtime DSP.
Now don't forget that I said the following: I well know that when I have everything done right, I won't need to kill my app to reset the audio interface.
BUT: Remember, perfect apps don't start out as perfect apps! They start out as just barely working apps and grow to become proper ideal apps.
So what I found was that my little audio oscilloscope test app worked great until I pressed the android Home button. When I then re-launched my oscilloscope app, there was no audio coming in anymore.
At first I would go into
Settings->Applications->Manage Applications->AppName->Force Stop.
(Note that if the actual linux process is not running, the Force Stop button will be disabled. If the button is enabled, then the Linux process is still running!)
Then I could re-launch my app and it worked again.
At first, I was just using divide by zero to crash it - and that worked great.
But I decided to look for a better way - which landed me here!
So here's the ways I tried and what I found out:
Background:
Android runs on Linux.
Linux has processes and process IDs (PIDs) just like Windows does, only better.
To see what processes are running on your android (with it connected into the USB and everything) run adb shell top and you will get an updating list of all the processes running in the linux under the android.
If you have linux on your PC as well, you can type
adb shell top | egrep -i '(User|PID|MyFirstApp)' --line-buffered
to get just the results for your app named MyFirstApp. You can see how many Linux Processes are running under that name and how much of the cpu power they are consuming.
(Like the task manager / process list in Windows)
Or if you want to see just the running apps:
adb shell top | egrep -i '(User|PID|app_)' --line-buffered
You can also kill any app on your device by running
adb shell kill 12345
where 12345 is it's PID number.
From what I can tell, each single-threaded app just uses a single Linux process.
So what I found out was that (of course) if I just activate the android Home option, my app continues to run.
And if I use the Activity.finish(), it still leaves the process running.
Divide by zero definitely terminates the linux process that is running.
Killing the PID from within the app seems the nicest so far that I've found, at least for debugging purposes.
I initially solved my need to kill my app by adding a button that would cause a divide by zero, like this in my MainActivity.java:
public void exit(View view)
{
int x;
x=1/0;
}
Then in my layout XML file section for that button I just set the android:onClick="exit".
Of course divide by zero is messy because it always displays the "This application stopped..." or whatever.
So then I tried the finish, like this:
public void exit(View view)
{
finish();
}
And that made the app disappear from the screen but it was still running in the background.
Then I tried:
public void exit(View view)
{
android.os.Process.killProcess(android.os.Process.myPid());
}
So far, this is the best solution I've tried.
UPDATE: This is the same as above in that it instantly terminates the Linux process and all threads for the app:
public void exit(View view)
{
System.exit(0);
}
It instantly does a nice full exit of the thread in question without telling the user that the app crashed.
All memory used by the app will be freed. (Note: Actually, you can set parameters in your manifest file to cause different threads to run in different Linux processes, so it gets more complicated then.)
At least for quick and dirty testing, if you absolutely need to know that the thread is actually fully exited, the kill process does it nicely. However, if you are running multiple threads you may have to kill each of those, probably from within each thread.
EDIT: Here is a great link to read on the topic:
http://developer.android.com/guide/components/fundamentals.html
It explains how each app runs in its own virtual machine, and each virtual machine runs under its own user ID.
Here's another great link that explains how (unless specified otherwise in manifest) an app and all of its threads runs in a single Linux process: http://developer.android.com/guide/components/processes-and-threads.html
So as a general rule, an app really is a program running on the computer and the app really can be fully killed, removing all resources from memory instantly.
(By instantly I mean ASAP -- not later whenever the ram is needed.)
PS: Ever wonder why you go to answer your android phone or launch your favorite app and it freezes for a second? Ever reboot because you get tired of it? That's probably because of all the apps you ran in the last week and thought you quit but are still hanging around using memory. Phone kills them when it needs more memory, causing a delay before whatever action you wanted to do!
Update for Android 4/Gingerbread: Same thing as above applies, except even when an app exits or crashes and its whole java virtual machine process dies, it still shows up as running in the app manager, and you still have the "force close" option or whatever it is. 4.0 must have an independent list of apps it thinks is running rather than actually checking to see if an app is really even running.
You could finish your Activity by calling Activity.finish(). However take care of the Android Activity life-cycle.
You could close your Android Application by calling System.exit(0).
just call the finish() in the method you would like to end the activity in, for example when you use the onCreate() method, in the end of the method, just add finish() and you will see the activity ends as soon as it is created!
As per my knowledge, finish function close the current displayed screen only.
Refer this example (where see the answer given by 'plusminus'), it will sure help you to close your application.
Before doing so please read this other question too:
android.os.Process.killProcess(android.os.Process.myPid());
android.os.Process.killProcess(android.os.Process.myPid());
This code kill the process from OS
Using this code disturb the OS. So I would recommend you to use the below code
this.finish();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
The answer depends on what you mean by "close app". In android's terms its either about an "activity", or a group of activities in a temporal/ancestral order called "task".
End activity: just call finish()
End task:
clear activity task-stack
navigate to root activity
then call finish on it.
This will end the entire "task"
not a one-line-code solution, but pretty easy:
sub-class Activity, then override and add finish() to onPause() method
this way, activity will be gone once it enters background, therefore the app won't keep a stack of activities, you can finish() the current activity and the app is gone!
If you close the main Activity using Activity.finish(), I think it will close all the activities.
MAybe you can override the default function, and implement it in a static way, I'm not sure
I don't think you can do it in one line of code. Try opening your activities with startActivityForResult. As the result you can pass something like a CLOSE_FLAG, which will inform your parent activity that its child activity has finished.
That said, you should probably read this answer.
That's one of most useless desires of beginner Android developers, and unfortunately it seems to be very popular. How do you define "close" an Android application? Hide it's user interface? Interrupt background work? Stop handling broadcasts?
Android applications are a set of modules, bundled in an .apk and exposed to the system trough AndroidManifest.xml. Activities can be arranged and re-arranged trough different task stacks, and finish()-ing or any other navigating away from a single Activity may mean totally different things in different situations. Single application can run inside multiple processes, so killing one process doesn't necessary mean there will be no application code left running. And finally, BroadcastReceivers can be called by the system any time, recreating the needed processes if they are not running.
The main thing is that you don't need to stop/kill/close/whatever your app trough a single line of code. Doing so is an indication you missed some important point in Android development. If for some bizarre reason you have to do it, you need to finish() all Activities, stop all Services and disable all BroadcastReceivers declared in AndroidManifest.xml. That's not a single line of code, and maybe launching the Activity that uninstalls your own application will do the job better.

Is quitting an application frowned upon?

Moving on in my attempt to learn Android, I just read the following:
Question: Does the user have a choice to kill the application
unless we put a menu option in to kill it? If no such option exists,
how does the user terminate the application?
Answer: (Romain Guy): The user doesn't, the system handles this automatically. That's what the activity lifecycle (especially onPause/onStop/onDestroy) is for. No matter what you do, do not put a "quit" or "exit" application button. It is useless with Android's application model. This is also contrary to how core applications work.
Hehe, for every step I take in the Android world I run into some sort of problem =(
Apparently, you cannot quit an application in Android (but the Android system can very well totally destroy your app whenever it feels like it). What's up with that? I am starting to think that it's impossible to write an app that functions as a "normal app" - that the user can quit the app when he/she decides to do so. That is not something that should be relied upon the OS to do.
The application I am trying to create is not an application for the Android Market. It is not an application for "wide use" by the general public, it is a business app that is going to be used in a very narrow business field.
I was actually really looking forward to developing for the Android platform, since it addresses a lot of issues that exist in Windows Mobile and .NET. However, the last week has been somewhat of a turnoff for me... I hope I don't have to abandon Android, but it doesn't look very good right now =(
Is there a way for me to really quit the application?
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:
First of all, this only happens when your app is in the foreground. If it is in the background the process will terminate just fine. However, if it is in the foreground, the OS assumes that the user wants to keep doing whatever he/she was doing. (If you are trying to kill the process from DDMS, you should hit the home button first, and then kill it)
It also assumes that each activity is independent of all the other activities. This is often true, for example in the case that your app launches the Browser Activity, which is entirely separate and was not written by you. The Browser Activity may or may not be created on the same Task, depending on its manifest attributes.
It assumes that each of your activities is completely self-reliant and can be killed/restored in a moment's notice. (I rather dislike this particular assumption, since my app has many activities which rely on a large amount of cached data, too large to be efficiently serialized during 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.
The final factor is not so much an assumption, but rather a limitation of the OS: killing the app explicitly is the same as the app crashing, and also the same as Android killing the app to reclaim memory. This culminates in our coup de grace: since Android can't tell if the app exited or crashed or was killed in the background, it assumes the user wants to return where they left off, and so the ActivityManager restarts the process.
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:
Don't try to kill the process. Either call finish() on all activities or call moveTaskToBack(true).
If your process crashes or gets killed, and if, like me, you need the data that was in memory which is now lost, you'll need to return to the root activity. To do this, you should call startActivity() with an Intent that contains the Intent.FLAG_ACTIVITY_CLEAR_TOP flag.
If you want to kill your app from the Eclipse DDMS perspective, it had better not be in the foreground, or it will restart itself. You should press the Home button first, and then kill the process.
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.
This debate boils down to the age-old question of whether the developers know best or whether the user knows best. Professional designers in all areas of human factors struggle with this every day.
Ted has made a point in that one of the most downloaded apps on the Market is the 'App Killer'. People get a bit of extra serotonin when they quit applications. They're used to it with a desktop/laptop. It keeps things moving fast. It keeps the processor cool and the fan from turning on. It uses less power.
When you consider that a mobile device is a much smaller ship, then you can especially appreciate their incentive to 'throw overboard what you no longer need'. Now the developers of Android have reasoned that the OS knows best and that quitting an app is antique. I wholeheartedly support this.
However, I also believe that you should not frustrate the user, even if that frustration is borne out of their own ignorance. Because of that, I conclude that having a 'Quit' option is good design, even if it is mostly a placebo button that does nothing more than close a View.
Ted, what you are trying to accomplish can be done, perhaps just not how you are thinking of it right now.
I suggest you read up on Activities and Services. Stop using the term "app" and start referring to the components, i.e. Activity, Service. I think you just need to learn more about the Android platform; it is a change in mindset from a standard PC app. The fact that none of your posts have had the word "Activity" (short of a FAQ quote, i.e. not your words) in them tells me you need to read some more.
Blog post When to Include an Exit Button in Android Apps (Hint: Never) explains it far, far better than I can. I wish every Android developer has read it already.
Excerpts:
In my experience what [the users] really want is:
An unambiguous way to guarantee that an app will stop consuming resources (battery, CPU cycles, data transfer, etc.).
Many users perceive that an exit button implements this requirement
and ask for it to be added. Developers, looking to please their users,
obligingly add one. Shortly thereafter they both fail.
In most cases the exit button simply calls Activity.finish(). This is exactly equivalent to hitting the back button.
Exactly. Services keep running and polling keeps happening. Users may think they've killed the app but they haven't, and soon
they'll be even more annoyed.
Exit behavior is now ambiguous. Should your exit button just close the Activity, or should it also stop all associated Services, Receivers, and Alarms? What should Back do? What happens if they hit Home instead? What happens if your app has a widget? Should the exit button stop that from updating too?
The solution is to make the back button behave as you'd expect the
exit button to. Better yet, simply stop consuming resources whenever
the app isn't visible.
Go ahead and read the complete article.
Answer: (Romain Guy): The user doesn't, the system handles this
automatically. That's what the activity lifecycle (especially
onPause/onStop/onDestroy) is for. No matter what you do, do not put a
"quit" or "exit" application button. It is useless with Android's
application model. This is also contrary to how core applications
work.
1: Totally exiting an application may be generally unmandatory, but it is not useless. What if windows had no exit option? System would be doggy slow as memory was full and the OS had to guess at which programs you were done with. I don't care what Romain Guy or even Larry Page and Sergey Brin say - these are unquestionable facts: Systems run slower when they have to kill tasks to get their memory before a new app can be launched. You just can't tell me that it doesn't take time to kill an app! Even the light from distant stars take time... There is some use in allowing the user to fully close apps.
2: Contrary to how core applications work? What's that supposed to mean? When I'm done running an app for now, it is no longer doing any work...It's just waiting to be killed by the OS when its memory is needed.
In summary, there is a distinct difference between minimizing and exiting, and neither pinch hits well for the other. Do we leave a screwdriver in every screw? Or a key in every door? Do we leave all of our appliances on high until the breaker blows and we need to turn on another appliance? Do we leave the dish washer full of dishes, and only take out enough each time to make room for some new dirty ones? Do we leave all the cars running in the driveway until -- oh never mind.
If the user wants to minimize an app, then the best thing is to minimize it. If a user wants to exit an app, then by all means it is best to exit.
Is it frowned on? That's Android's view - they frown on it. And many many independent rookie Android developers frown on it.
But when it comes right down to it, there is good coding and bad coding. There is good program flow models and there are bad program flow models.
Leaving programs in memory when the user knows they are done with them simply is not good program flow. It serves absolutely no purpose whatsoever, and it slows things down when launching new apps or when running apps allocate more memory.
It is sort of like your car: There are times when you leave it running, like stopping at a stop light, or perhaps the fast food drive through, or stopping at the ATM. But there are other situations where you do want to shut it off - like when you get to work, or the grocery store or even home.
Similarly, if you're playing a game and the phone rings, yes. Pause the game and keep it running. But if the user is done with the game for a while, then by all means let them exit.
The exit button on some applications should be more out in front than others. Games, for example, or programs where the user is likely to want to fully exit, should have an obvious exit. Other programs, like, perhaps, email programs, where exiting is an unlikely desire (so that it can keep checking for email) -- these programs should not waste prime control input screen space with an exit option, but for good program flow, it should have an exit option. What if someone decides they don't want their mail program trying to check email when they are in poor coverage area, or maybe in a Skype call or whatever? Let them exit the email program if they want!
Suspending and exiting are two vital tasks and neither fulfills the role of the other.
If you are unable to fathom how to make your data/connections (and thereby your "application") persistent, then you will be unable to do what you "need" to do with Android.
Those who do download those cutesy little App Killers usually find they do not help battery life or memory usage, but hinder the OS from doing it's job of managing memory efficiently...
http://android-developers.blogspot.com/2010/04/multitasking-android-way.html
I think the point is that there is no need to quit the app unless you have buggy software. Android quits the app when the user is not using it and the device needs more memory. If you have an app that needs to run a service in the background, you will likely want a way to turn the service off.
For example, Google Listen continues to play podcast when the app is not visible. But there is always the pause button to turn the podcast off when the user is done with it. If I remember correctly, Listen, even puts a shortcut in the notification bar so you can always get to the pause button quickly. Another example is an app like a twitter app for instance which constantly polls a service on the internet. These types of apps should really allow the user to choose how often to poll the server, or whether even to poll in a background thread.
If you need to have code that runs on exit, you can override onPause(), onStop(), or onDestroy() as appropriate.
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
I would consider reading "Android Wireless Application Development" published by Addison-Wesley. I am just finishing it up and it is VERY thorough.
It appears that you have some fundamental misunderstandings of the Android platform. I too was a little frustrated at first with the application life-cycle of Android apps, but after coming to a greater understanding, I have come to really enjoy this approach. This book will answer all of your questions and much more. It really is the best resource I have found for new Android developers.
Also, I think you need to let go of a line-for-line port of the existing app. In order to port your application to the Android platform, some of the application design is going to change. The application-lifecycle used is necessary as mobile devices have very limited resources relative to desktop systems and allows Android devices to run several applications in an orderly and resource-aware fashion. Do some more in depth study of the platform, and I think you will realize that what you are wanting to do is entirely feasible. Best of luck.
By the way, I am no way affiliated with Addison-Wesley or any person or organization associated with this book. After re-reading my post I feel that I came off a little fanboyish. I just really, really enjoyed it and found it extremely helpful. :)
Almost 99% of the time there is no need for an Android application to take over its own life cycle. Most of the time it comes down to better planning or smarter design of the application. For example, rather build an internal service (not exported) to handle downloads, etc., or design actions and tasks around user workflow.
But that being said, where there is a will there is a way. Android provides - through the android.os.Process class, a much better API than Java to control the underlying process. And unlike Java it does not treat the developer like a moron by hiding it all behind a simple java.lang.System.exit() call.
So how do you ask your application to commit suicide in Android? Well, the trick is simple:
Create your own Android application class by inheriting from the standard android.app.Application class (remember to declare it in the AndroidManifest.xml file).
Override the onCreate() method, and store the process ID which started your application:
this.pid = android.os.Process.myPid(); // Save for later use.
Now to kill your application, provide a kill() method:
android.os.Process.sendSignal(pid, android.os.Process.SIGNAL_KILL);
Now whenever you need your app to commit suicide just type cast the application context, and call your kill method!
((MySuicidalApp) context.getApplicationContext()).kill()
Just remember that due to the process management policies in Android, specifically related to services, Android may just opt to restart your service (see You should not use task killers on Android).
When I conceive an application in Android, I see it this way:
You are working with your application
The phone rang
You take the call
At the end of the call, you come back to your application at the same place you were
To do that, you only need the Back button or the Home button of your phone (either by short or long press) and the notification bar.
When I exit my application, I only use the Back button until I am out of it or the Home button.
That's how most of the applications are conceived I think. But if I need some sort of session or connection, I made it clear to the user with a login/logout button and notification (title bar or anything else). This is a rather different style than the pure "exit" style application.
On PCs, you have a multi-GUI desktop, and on Android, you obviously have multi-tasks, but you only display one app at a time (I don't consider widgets here ^^). And on a mobile phone, at anytime, you could have a notification for something more important than what you are doing.
So the whole concept of an application rely on something different that "enter application - work - exit application".
Hmmmm...
I think that you just don't see the Android app the right way. You can do something almost like what you want easily:
Do the app activities save/restore state like it is encouraged in the developer livecycle documentation.
If some login is needed at the restore stage (no login/session information available) then do it.
Eventually add a button/menu/timeout in which case you will do a finish() without saving the login and other session info, making implicitly the end of app session: so if the app is started/brought to front again it will start a new session.
That way you don't really care if the app is really removed from memory or not.
If you really want to remove it from memory (this is discouraged, and BTW for what purpose?) you can kill it conditionally at the end of onDestroy() with java.lang.System.exit(0) (or perhaps restartPackage(..)?). Of course do it only in the case where you want to "really end the app", because the onDestroy() is part of the normal lifecycle of activities and not an app end at all.
As an Application in an Android context is just a bunch of vaguely related Activities, quitting an Application doesn't really make much sense. You can finish() an Activity, and the view of the previous Activity in the Activity stack will be drawn.
I agree with Ted. I understand that exiting the application is not the
"Android way", but it doesn't seem like it should be precluded. Here
are three reasons why you might want a real exit to the application (not
just the activity):
The user might want some control over which app gets killed in the
case of low memory. If important app A is running in the background,
then you might like to exit app B when you are done with it so
that app A doesn't get killed by the operating system.
If your application has sensitive data cached in memory, you might
like to kill the app so that a virus/worm/rogue app can't get at it. I
know the security model is supposed to prevent that, but just in case...
If your application uses resources (like network, CPU, sensors, etc.)
that could adversely affect the phone, then one way of ensuring that
those resources are freed up is to exit the application. I understand
that well-behaved apps should free up resources when they are not needed. But again, exiting the application seems like a reasonable way of ensuring that.
I hope things will change over time. The user should be able to kill an app or process if the app process is sandboxed correctly by the OS. There is a notion that apps should be written perfectly or user will use only the apps that follow all SDK recommendations. I think that is a tall order.
The Linux kernel has a feature called Out-of-memory killer (as mentioned above, the policies are configurable at the userspace level as well as the kernel is not an optimal one, but by no means unnecessary).
And it is heavily used by Android:
OOM killer is not for userspace
Android Notes (OOM Killer Info - where you can configure the OOM feature on Android)
Android Porting On Real Target
Some userspace apps are available to assist with these kill apps, for example:
Autokiller/Configuring Android's internal task killer
You apparently have found the answer you want in the finish() command. This will not remove your app from memory, but Android will do so whenever it needs the resources, so it doesn't make any difference that you won't be doing that explicitly.
I would only add that in order to attain the full effect that an application exit would typically have, you would want to reset the app's state to whatever its state is normally at the time it is first run after a boot of the device, just prior to calling finish() on all of your activities. That way, if the user selects your app again, it will appear to have been run "fresh," without any state left over from the point prior to the simulated "exit."
If there are some special actions that should only occur on "exit," such as saving the user's work or whatever, you can also perform them prior to the re-initialization part of the above routine.
This approach allows you to accomplish your goal of having an "exit" command without violating Android's philosophy of leaving the management of OS resources, including the closing of apps, in the hands of the operating system.
Personally, I would not use this approach, because Android users expect an app to preserve its continuity when they revisit it, and so they are not used to the modality of "exiting" an app. I would instead support a "clear" function that a user can invoke to reset the app to some default initial state, without the necessity of "leaving" it in the process.
The one exception would be when the user has hit the back button a sufficient number of times to cause the app to close. In that situation, there is no expectation on the user's part that state will have been saved (and if there is unsaved state in the app, then you, as the developer, should have code handling the back button that detects that unsaved data, and prompts the user to save it to SharedPreferences or to a file, or to some other non-volatile medium).
Regarding system.exit(0):
If you do decide to use system.exit(0) to close your app with rude finality (e.g., as a result of a final back button press), then I would warn you that although for me this "works," and in some cases has been the only way I've been able to close an app without any trace of it remaining, there is one minor glitch that occurs in Jelly Bean when you use this approach.
Specifically, if you use the Recent Apps list to open your app, and then use the back button to close the app (with that close implemented via system.exit(0)), the Recent Apps list will become visible again, as it will never have been closed. If you then tap on your app's entry in that list to run it a second time from the same, already-open, Recent Apps list, there will be no response.
I suspect that the cause of this is that the Recent Apps list is holding on to a reference to your app that has become non-functional due to your having closed the app using system.exit(0). A more civilized closing of your app using finish() might have informed the OS in a manner that would have allowed it to refresh its Recent Apps list, but system.exit(0) apparently does not do this.
This is not a huge problem in and of itself, as very few people will open an app from Recent Apps, then exit it, and then immediately open it again from the same open Recent Apps list. And if they tap the home button and then re-open the Recent Apps list, your app's entry will be there, and it will be fully functional. But I think that it shows that the use of system.exit(0) can interfere with proper communication between your app and the OS, and this suggests that there may be other, more serious, possibly subtle, consequences of using this approach.
The Android application life cycle is designed for mobile phone users, not computer users.
The app life-cycle is the brutally simplistic paradigm required to turn a Linux server into a consumer appliance.
Android is Java over Linux, a real cross-platform server OS. That is how it spread so quickly. The app life-cycle encapsulates the underlying reality of the OS.
To mobile users, apps are just installed or not installed. There is no concept of running or exiting. In fact, app processes are meant to run until the OS releases them for their held resources.
Since this is Stack Overflow, anyone reading this is a computer user and must turn off 90% of their knowledge to understand the mobile app lifecycle.
There is a (relatively) simple design which will allow you to get around the "exit" conundrum. Make your app have a "base" state (activity) which is just a blank screen. On the first onCreate of the activity, you can launch another activity that your app's main functionality is in. The "exit" can then be accomplished by finish()ing this second activity and going back to the base of just a blank screen. The OS can keep this blank screen in memory for as long as it wants...
In essence, because you cannot exit out to OS, you simply transform into a self-created nothingness.
Without an exit function for the application developer to kill their own application it is very bad design.
My application needs to allow the user to dynamically change data dynamically during runtime and the user needs to restart my application to make the change effect, but Android did not allow my application restart by itself. Android OS has a very bad design application life cycle.
For closing an app at any point use FLAG_ACTIVITY_CLEAR_TOP flag in Intent and then system.exit();
Or there is similar way, but without system.exit() when you want to exit call this method:
public void exit() {
startActivity(new Intent(this, HomeActivity.class).
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK).putExtra(EXIT_FLAG, true));
}
In your HomeActivity.onCreate() add following code
protected void onCreate(Bundle savedInstanceState) {
if (getIntent().getBooleanExtra(EXIT_FLAG, false)) {
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
finish();
}
}
......................
This will work without breaking the Android life-cycle.
First of all, never never never use System.exit(0). It is like making a person sleep punching him on the head!
Second: I'm facing this problem. Before sharing my solution a I want to share my thoughts.
I think that an "Exit Button" is stupid. Really really really stupid. And I think that users (consumer) that ask for an exit button for your application is stupid too. They don't understand how the OS is working and how is managing resources (and it does a great job).
I think that if you write a good piece of code that do the right things (updates, saves, and pushes) at the right moment and conditions and using the correct things (Service and Receiver) it will work pretty well and no one will complain.
But to do that you have to study and learn how things works on Android.
Anyway, this is my solution to provide to users an "Exit Button".
I created an Options Menu always visible in each activity (I've a super activity that do that).
When the user clicks on that button this is what happens:
Intent intent = new Intent(this, DashBoardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SharedPreferences settings = getSharedPreferences(getString(PREF_ID), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(FORCE_EXIT_APPLICATION, true);
// Commit the edits!
editor.commit();
startActivity(intent);
finish();
So I'm saving in SharedPreferences that I want to kill my app, and I start an Intent. Please look at those flags; those will clear all my backstack calling my DashBoard Activity that is my "home" activity.
So in my Dashboard Activity I run this method in the onResume:
private void checkIfForceKill() {
// CHECK IF I NEED TO KILL THE APP
// Restore preferences
SharedPreferences settings = getSharedPreferences(
getString(MXMSettingHolder.PREF_ID), Context.MODE_PRIVATE);
boolean forceKill = settings.getBoolean(
MusicSinglePaneActivity.FORCE_EXIT_APPLICATION, false);
if (forceKill) {
//CLEAR THE FORCE_EXIT SETTINGS
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(FORCE_EXIT_APPLICATION, false);
// Commit the edits!
editor.commit();
//HERE STOP ALL YOUR SERVICES
finish();
}
}
And it will work pretty well.
The only thing that I don't understand why it's happening is that when I do the last finish (and I've checked: it's following all the correct flow of onPause → onStop → onDestroy) the application is still on the recent activity (but it's blank).
It seems like the latest intent (that has started the DashboardActivity) is still in the system.
I've to dig more in order to also remove it.
It took me longer to read this Q&A than to actually implement a semi-proper Android Application Lifecycle.
It's a GPS app that polls for points and sends the current location to a webservice every few seconds using a thread... This could be polling every 5 minutes in Ted's case for an update, then onStop can simply start the update activity Ted was soo concerned about if one was found (asynchronous Ted, don't code like a Windows programmer or your programs will run like Windows programs ... eww, it's not that hard).
I did some initial code in onCreate to set up things for the activity lifetime, including checkUpdate.start();:
...
#Override
public void onStart() {
super.onStart();
isRemote = true;
checkUpdate.resume();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, luh);
}
#Override
public void onPause() {
isRemote = false;
checkUpdate.suspend();
locationManager.removeUpdates(luh);
super.onStop();
}
This code may be completely wrong, but it works. This is one of my first Android applications.
Voilà, an application that doesn't consume CPU when it's in the background, yet is instantly ready to reopen because it is in RAM (although not holding RAM as is the Android lifecycle) ... an app is always ready, it's a phone, guys/gals. If an app was to use up all the RAM and couldn't be shut down by the OS then the thing might stop ringing =P That's why the OS needs to be able to close your app when it's in the background (if your application isn't a resource hog it won't be closed BTW), so let's just write better applications.
Every time while you move to the next page through intent, use:
`YourActivityname.this.finish()`;
Example:
Intent intent = new Intent(getApplicationContext(), SMS.class);
startActivity(intent);
MainActivity.this.finish();
So that no activity will be running on background and when you want to Exit your app, use:
MainActivity.this.finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
getParent().finish();
This exiting worked like a charm for me :)
You have probably spent many years writing "proper" programs for "proper" computers. You say you are learning to program in Android. This is just one of the things you have to learn. You can't spent years doing watercolour painting and assume that oil painting works exactly the same way. This was the very least of the things that were new concepts to me when I wrote my first app eight years ago.
In any case, if you want to terminate your application you can always call System.exit(0);.

Categories

Resources