正在放弃申请吗?
在我学习Android的尝试中,我刚刚阅读了以下内容 :
问题: 用户是否可以select杀死应用程序,除非我们放入一个菜单选项来杀死它? 如果不存在这样的选项,用户如何终止应用程序?
答:(罗曼盖伊): 用户没有,系统自动处理这个。 这就是活动的生命周期(特别是onPause / onStop / onDestroy)。 不pipe你做什么,不要放一个“退出”或“退出”应用程序button。 Android的应用程序模型是无用的。 这与核心应用程序的工作方式也是相反的。
嘿嘿,我在Android世界的每一步都遇到了一些问题=(
显然,你不能退出Android的应用程序(但Android系统可以很好地彻底摧毁你的应用程序,只要感觉像)。 怎么了? 我开始认为编写一个“普通应用程序”的应用程序是不可能的 – 用户可以在他/她决定这样做时退出应用程序。 这不是应该依靠操作系统来做的事情。
我试图创build的应用程序不是Android Market的应用程序。 这不是一般公众“广泛使用”的应用程序,它是一个将在狭窄的业务领域使用的商业应用程序。
实际上,我真的很期待为Android平台开发,因为它解决了Windows Mobile和.NET中存在的许多问题。 不过,上个星期对我来说有点closures了……我希望我不必放弃Android,但是现在看起来不是很好=(
有没有办法让我真的退出应用程序?
这最终会解决你的问题,但是我首先要解决你在各种意见中提到的一些问题,以便在撰写本文时给出的各种答案。 我无意改变你的想法,相反,这些对于未来来读这篇文章的人来说是在这里。
关键是我不能让Android来确定我的应用程序将被终止。 那必须是用户的select。
数以百万计的人对于环境closures应用程序的模型非常满意。 那些用户根本就不会考虑“终止”Android应用程序,而是想到“终止”网页或“终止”恒温器。
iPhone用户的方式大致相同,因为按下iPhonebutton并不一定“感觉”应用程序已经终止,因为许多iPhone应用程序会在用户停止的地方接收到,即使应用程序真的closures了(因为只有iPhone一次允许一个第三方应用程序)。
正如我上面所说,我的应用程序中有很多事情正在进行(数据被压入设备,列表中总是应该存在的任务等)。
我不知道“总是应该存在的任务列表”是什么意思,但是“被压入设备的数据”是一个令人愉快的小说,不应该由任何情况下的活动来完成。 使用计划任务(通过AlarmManager
)更新您的数据以获得最大的可靠性。
我们的用户login,每次打电话都不能这样做,Android决定终止应用程序。
有很多iPhone和Android应用程序处理这个问题。 通常,这是因为他们坚持login凭据,而不是强迫用户每次手动login。
例如,我们希望在退出应用程序时检查更新
这在任何操作系统上都是错误的。 对于你所知道的,你的应用程序“退出”的原因是因为操作系统正在closures,然后你的更新过程将在中途失败。 一般来说,这不是一件好事。 检查更新开始或检查更新完全asynchronous(例如,通过计划的任务),永远不会退出。
一些意见build议,点击后退button不会杀死应用程序(请参阅上面的问题中的链接)。
按BACKbutton不会“杀死应用程序”。 当用户按下BACKbutton时,它完成屏幕上的活动。
它应该只在用户想要终止时终止 – 永远不会有任何其他的方式。 如果你不能在Android中编写这样的应用程序,那么我认为Android不能用于编写真正的应用程序=(
那么既不可以Web应用程序。 或者WebOS ,如果我正确地理解他们的模型(还没有机会玩一个)。 在所有这些,用户不“终止”任何东西 – 他们只是离开。 iPhone有点不同,因为它目前只允许一件事情在某个时间运行(有一些例外),所以离开的行为意味着相当立即终止应用程序。
有没有办法让我真的退出应用程序?
正如其他人告诉你的,用户(通过BACK)或者你的代码(通过finish()
)可以closures你正在运行的活动。 对于正确编写的应用程序,用户通常不需要其他任何东西,不需要使用Web应用程序的“退出”选项。
根据定义,没有两个应用程序环境是相同的。 这意味着你可以看到环境中的趋势,因为新的环境会出现,而其他的则会被埋没。
例如,试图消除“档案”概念的运动正在发展。 大多数Web应用程序不会强制用户考虑文件。 iPhone应用程序通常不强制用户考虑文件。 Android应用程序通常不会强制用户考虑文件。 等等。
同样,越来越多的运动试图消除“终止”应用程序的概念。 大多数Web应用程序不强制用户注销,而是在一段时间不活动之后隐式地将用户注销。 与Android同样的东西,在较小的程度上,iPhone(可能还有WebOS)。
这需要更多地强调应用程序devise,专注于业务目标,而不是坚持与以前的应用程序环境绑定的实现模型。 那些缺乏时间或倾向的开发人员会因为破坏现有心智模式的新环境而感到沮丧。 这不是任何一个环境的错误,不仅仅是因为风暴在周围stream淌而不是通过它的山峰的错误。
例如,一些开发环境,如Hypercard和Smalltalk,将应用程序和开发工具混合在一个设置中。 除了应用程序的语言扩展(例如, Excel中的 VBA ,AutoCAD中的Lisp )之外,这个概念还没有得到很大的发展。 开发人员提出了假设应用程序本身存在开发工具的心智模型,因此要么改变他们的模型,要么将他们自己限制在他们的模型将成立的环境中。
所以,当你写:
除了我发现的其他杂乱的东西,我认为开发我们的Android应用程序不会发生。
对于你来说,这似乎是最好的。 同样,我会劝你不要试图把你的应用程序移植到Web上,因为你在Android应用程序中也会遇到同样的问题(例如,没有“终止”)。 或者相反,有一天,如果你将应用程序移植到Web上,你可能会发现Web应用程序的stream程可能会更适合Android,并且可以在那个时候重新访问Android端口。
我只想在这里为这个线程的未来读者添加一个更正。 这个特殊的细微差别已经逃脱了我很长一段时间的理解,所以我想确保你们没有犯同样的错误:
如果您在堆栈上有多个活动, System.exit()
不会System.exit()
您的应用程序。 实际上发生的事情是该进程被终止,并立即重新启动 ,只有一个活动在堆栈上。 当您的应用程序被“强制closures”对话框终止时,甚至当您尝试从DDMS中终止进程时,也会发生这种情况。 就我所知,这是一个完全没有logging的事实。
简单的回答是,如果你想退出你的应用程序,你必须跟踪你的堆栈中的所有活动,并在用户想要退出时finish()
所有这些活动(否则无法迭代活动堆栈,所以你必须自己pipe理所有这一切)。 即使这实际上并没有杀死这个过程或任何你可能有的悬而未决的引用。 它只是完成了活动。 另外,我不确定Process.killProcess(Process.myPid())
是否工作得更好; 我没有testing过。
另一方面,如果您的活动仍然存在于您的堆栈中,还有另一种方法可以使您的操作变得非常简单: Activity.moveTaskToBack(true)
将简单地显示您的进程背景并显示主屏幕。
漫长的回答涉及这一行为背后的哲学的解释。 哲学诞生于一些假设:
- 首先,这只有当你的应用程序在前台时才会发生。 如果它在后台进程将终止正常。 但是,如果它在前台,操作系统会假定用户想要继续做他/她正在做的事情。 (如果你试图从DDMS中杀死进程,你应该首先点击主页button,然后杀死它)
- 它还假定每个活动都独立于所有其他活动。 这通常是正确的,例如在您的应用程序启动浏览器活动,这是完全独立的,不是由你写的情况下。 浏览器活动可能会也可能不会在同一个任务上创build,具体取决于其清单属性。
- 它假设你的每一项活动都是完全自力更生的,并且可以立刻被杀死/恢复。 (我宁愿不喜欢这个特定的假设,因为我的应用程序有很多活动依赖于大量的caching数据,太大而无法在
onSaveInstanceState
期间有效地序列化,但是whaddya会怎么办?)对于大多数写得很好的Android应用程序,这应该是真实的,因为你永远不知道什么时候你的应用程序将在后台被杀害。 - 最后的因素不是一个假设,而是操作系统的一个限制: 明确地杀死应用程序与应用程序崩溃相同,也与Android杀死应用程序以回收内存一样。 这最终导致我们的coup de grace:由于Android无法确定应用程序是否在后台退出,崩溃或被杀死,因此假定用户想要返回停止的位置,ActivityManager重新启动该进程。
当你考虑这个问题的时候,这个平台是适合的。 首先,当进程在后台被终止并且用户返回时,会发生这种情况,所以需要在停止的地方重新启动。 其次,这是应用程序崩溃,并提出了可怕的强制closures对话框时发生的。
假设我希望我的用户能够拍照并上传照片。 我从我的活动启动相机活动,并要求它返回一个图像。 相机被推到我当前任务的顶部(而不是在自己的任务中创build)。 如果相机有错误,崩溃,应该导致整个应用程序崩溃? 从用户的angular度来看,只有相机失败了,他们应该返回到以前的活动。 所以它只是重新启动堆栈中所有相同的活动,减去相机的过程。 既然你的活动应该被devise成能够在一顶帽子下被杀死和恢复,这应该不成问题。 不幸的是,并不是所有的应用程序都可以这样devise,所以对我们很多人来说都是一个问题,无论罗曼·盖伊或其他人告诉你什么。 所以,我们需要使用解决方法。
所以,我最后的build议是:
- 不要试图杀死这个过程。 要么在所有活动上调用
finish()
,要么调用moveTaskToBack(true)
。 - 如果你的进程崩溃或被杀害,并且如果像我一样,你需要在内存中丢失的数据,你将需要返回到根活动。 为此,您应该使用包含
Intent.FLAG_ACTIVITY_CLEAR_TOP
标志的Intent调用startActivity()
。 - 如果你想从Eclipse DDMS的angular度来杀死你的应用程序,最好不要在前台,否则会重新启动。 您应该首先按主页button, 然后终止进程。
我所有的应用程序都退出button…我经常从用户那里得到积极的评论。 我不在乎平台的devise是否应用程序不需要它们。 说“不要把它们放在那里”是荒谬的。 如果用户想要退出…我为他们提供访问来完成这个任务。 我不认为这会降低Android的运作方式,似乎是一个很好的做法。 我了解生命周期……而我的观察一直认为,Android在处理它方面做得并不好……这是一个基本事实。
停止将您的应用程序作为一个整体应用程序来思考。 这是一组UI屏幕,用户可以与通过Android服务提供的“应用程序”和“function”进行交互。
不知道你的神秘应用程序“做”是不是真的很重要。 我们假设它通过一些超级安全的公司内部网,进行一些监控或交互,并保持login状态,直到用户“退出应用程序”。 由于您的IT部门对其进行命令控制,因此用户必须非常清楚何时进入内部networking或外部networking。 因此,对于用户来说“退出”是非常重要的。
这很简单。 在通知栏中提供一个正在进行通知的服务,说:“我在内联网,或者我正在运行”。 让该服务执行您的应用程序所需的所有function。 具有绑定到该服务的活动,以允许您的用户访问他们需要与您的“应用程序”进行交互的UI位。 并有一个Android菜单 – >退出(或注销,或其他)button,告诉服务退出,然后closures活动本身。
这是,所有的意图和目的完全是你说你想要的。 完成Android的方式。 看看谷歌对话或谷歌地图导航这个“退出”的例子是可能的心态。 唯一的区别是,按下退出button可能会让您的UNIX进程处于等待状态,以防止用户想要恢复应用程序。 这与现代操作系统在内存中caching最近访问的文件没有什么不同。 在你退出windows程序之后,它所需要的大部分资源仍然在内存中,等待被其他资源replace时,现在不再需要它们。 Android是同样的事情。
我真的没有看到你的问题。
这是一个有趣的和有见地的讨论与许多专家的贡献。 我觉得这个post应该从Android开发主网站内部回圈,因为它确实围绕着Android OS的核心devise之一。
我也想在这里加两分钱。
到目前为止,我已经对Android处理生命周期事件的方式留下了深刻的印象,将类似于networking的体验概念带入本地应用程序。
话虽如此,我仍然认为应该有一个退出button。 为什么? …不适合我或Ted或任何这里的技术大师,而仅仅是为了满足最终用户的需求。
尽pipe我不是Windows的忠实拥趸,但是早在那时他们就介绍了一个大多数最终用户习惯使用的概念(一个Xbutton)……“我想在'我'想要退出时运行一个部件。
这并不意味着某人(操作系统,开发人员)会自行处理这个问题……它只是意味着“我习惯于在哪里使用我的Red Xbutton”。 我的行为应该类似于“按下button结束呼叫”,“按下buttonclosures设备”,等等等等……这是一种感知。 它本身就令我满意,我的行动确实达到了目的。
尽pipe开发人员可以使用这里给出的build议来欺骗这种行为,但是这种看法仍然存在,即应用程序应该完全停止运行(现在),由最终用户根据需要提供独立,可信和中立的来源(OS)。
您可以通过按“ 后退”button或在“ Activity
调用finish()
来退出。 只要从MenuItem
调用finish()
,如果你想明确地把它closures。
Romain并不是说这是无法完成的,只是没有意义 – 用户不需要关心退出或保存工作,因为应用程序生命周期的工作方式鼓励您编写智能软件,自动保存和无论发生什么事情都会恢复其状态。
这个辩论可以归结为开发人员是否知道最好或者用户是否知道最好的这个古老的问题。 每一个人类因素的所有领域的专业devise师每天都在为此而斗争。
泰德已经指出,在市场上下载最多的应用程序之一是“应用程序杀手”。 离开申请时,人们会得到一些额外的5-羟色胺。 他们已经习惯了桌面/笔记本电脑。 它使事情快速移动。 它使处理器保持冷静,风扇不会启动。 它使用较less的权力。
当你考虑到移动设备是一个小得多的船,那么你可以特别欣赏他们“抛弃你不再需要的东西”的动机。 现在Android的开发者已经推断操作系统知道最好,退出应用程序是古董。 我全心全意支持这一点。
不过,我也相信,即使这种挫败感是由于自己的无知,也不应该让使用者感到沮丧。 因此,我得出这样的结论:“退出”选项是很好的devise,即使它主要是一个安慰剂button,只不过是closures视图而已。
泰德,你正在努力完成的事情可能已经完成了,或许你现在正在想的不是这样。
我build议你阅读活动和服务。 停止使用术语“应用程序”,并开始引用组件,即活动,服务。 我想你只需要更多地了解Android平台; 这是从一个标准的PC应用程序的思想变化。 事实上,你的任何文章都没有“活动”一词(缺less常见问题的引用,即不是你的话)告诉我,你需要阅读更多。
博客文章何时在Android应用程序中包含退出button(提示:从不)向我们解释了这一点, 远远胜过我。 我希望每个Android开发者已经阅读它。
摘录:
根据我的经验,用户真正需要的是: 确保应用程序停止消耗资源(电池,CPU周期,数据传输等)的明确方法。
许多用户认为退出button实现了这个要求并要求添加它。 开发人员,要取悦他们的用户,有意添加一个。 此后不久,他们都失败了。
- 在大多数情况下,退出button只需调用
Activity.finish()
。 这完全等同于点击后退button。 究竟。 服务继续运行,轮询不断发生。 用户可能认为他们已经杀了应用程序,但他们没有,很快他们会更加恼火。- 退出行为现在是不明确的。 如果您的退出button只是closures了活动,还是应该停止所有相关的服务,接收器和报警? 应该做什么? 如果他们打回家,会发生什么? 如果你的应用有一个小部件,会发生什么 退出button应该停止更新吗?
解决方法是使后退button的行为与您期望的退出button一样。 更好的是,只要应用程序不可见,就停止使用资源。
继续阅读完整的文章。
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
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 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. 祝你好运。
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.
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.
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.
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 (eg, 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.
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.
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.
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.
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.
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.
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.
Every time while you move to the next page through intent, use:
`YourActivityname.this.finish()`;
例:
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 🙂
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.
In any case, if you want to terminate your application you can always call System.exit(0);
。
If you have 10,20 .. multiple Activities running and you want to finish all them and exit from system.
Create a static array in application class
or constants class.
常量
public class Constants { public static ArrayList<Activity> activities = new ArrayList<Activity>(); }
MainActivity Add current activity reference in this array
activity = MainActivity.this; Constants.activities.add(activity);
public class MainActivity extends Activity { private ImageView imageButton; private Activity activity; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); activity = MainActivity.this; Constants.activities.add(activity); imageButton = (ImageView) findViewById(R.id.camera); imageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // existing app. if (Constants.activities != null) { for (int i = 0; i < Constants.activities.size(); i++) { Activity s = Constants.activities.get(i); s.finish(); } } //super.finish(); finish(); android.os.Process.killProcess(android.os.Process.myPid()); System.exit(1); } }); } }